@@ -1,7 +1,10 @@
AM_CFLAGS = -Wall
+ACLOCAL_AMFLAGS = -I aclocal
+
root_sbindir = "/sbin"
root_sbin_PROGRAMS = mount.cifs
mount_cifs_SOURCES = mount.cifs.c mtab.c util.c
+mount_cifs_LDADD = @LIBCAP@
man_MANS = mount.cifs.8
new file mode 100644
@@ -0,0 +1,20 @@
+dnl Checks for libcap.so
+dnl
+AC_DEFUN([AC_LIBCAP], [
+
+ dnl look for prctl
+ AC_CHECK_FUNC([prctl], , )
+
+ dnl look for the library; do not add to LIBS if found
+ AC_CHECK_LIB([cap], [cap_get_proc], enable_libcap="yes", enable_libcap="no", )
+
+ AC_CHECK_HEADERS([sys/capability.h], ,
+ [AC_MSG_WARN([libcap headers not found. mount.cifs will be built without support for dropping capabilities. Consider installing libcap-devel.]) ; enable_libcap="no"])
+
+ if test "$enable_libcap" = "yes"; then
+ AC_DEFINE([HAVE_LIBCAP],[1], [Define if libcap exists])
+ LIBCAP=-lcap
+ AC_SUBST(LIBCAP)
+ fi
+
+])dnl
@@ -5,6 +5,7 @@ AC_INIT([cifs-utils], [4.1], [jlayton@samba.org], [cifs-utils], [http://samba.or
AC_CONFIG_SRCDIR([replace.h])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([Makefile])
+AC_CONFIG_MACRO_DIR(aclocal)
AM_INIT_AUTOMAKE
@@ -80,4 +81,6 @@ fi
AM_CONDITIONAL(CONFIG_CIFSUPCALL, [test "$enable_cifsupcall" != "no"])
+AC_LIBCAP
+
AC_OUTPUT
@@ -43,6 +43,9 @@
#include <fstab.h>
#include <sys/mman.h>
#include <sys/wait.h>
+#ifdef HAVE_LIBCAP
+#include <sys/capability.h>
+#endif /* HAVE_LIBCAP */
#include "mount.h"
#include "util.h"
@@ -1131,6 +1134,63 @@ add_mtab_exit:
return rc;
}
+#ifdef HAVE_LIBCAP
+static int
+drop_capabilities(int parent)
+{
+ int rc = 0;
+ cap_t caps;
+ cap_value_t cap_list[2];
+
+ caps = cap_get_proc();
+ if (caps == NULL) {
+ fprintf(stderr, "Unable to get current capability set: %s\n",
+ strerror(errno));
+ return EX_SYSERR;
+ }
+
+ if (cap_clear(caps) == -1) {
+ fprintf(stderr, "Unable to clear capability set: %s\n",
+ strerror(errno));
+ rc = EX_SYSERR;
+ goto free_caps;
+ }
+
+ /* parent needs to keep some capabilities */
+ if (parent) {
+ cap_list[0] = CAP_SYS_ADMIN;
+ cap_list[1] = CAP_DAC_OVERRIDE;
+ if (cap_set_flag(caps, CAP_PERMITTED, 2, cap_list, CAP_SET) == -1) {
+ fprintf(stderr, "Unable to set permitted capabilities: %s\n",
+ strerror(errno));
+ rc = EX_SYSERR;
+ goto free_caps;
+ }
+ if (cap_set_flag(caps, CAP_EFFECTIVE, 2, cap_list, CAP_SET) == -1) {
+ fprintf(stderr, "Unable to set effective capabilities: %s\n",
+ strerror(errno));
+ rc = EX_SYSERR;
+ goto free_caps;
+ }
+ }
+
+ if (cap_set_proc(caps) != 0) {
+ fprintf(stderr, "Unable to set current process capabilities: %s\n",
+ strerror(errno));
+ rc = EX_SYSERR;
+ }
+free_caps:
+ cap_free(caps);
+ return rc;
+}
+#else /* HAVE_LIBCAP */
+static int
+drop_capabilities(int parent)
+{
+ return 0;
+}
+#endif /* HAVE_LIBCAP */
+
/* have the child drop root privileges */
static int
drop_child_privs(void)
@@ -1166,6 +1226,10 @@ assemble_mountinfo(struct parsed_mount_info *parsed_info,
{
int rc;
+ rc = drop_capabilities(0);
+ if (rc)
+ goto assemble_exit;
+
rc = drop_child_privs();
if (rc)
goto assemble_exit;
@@ -1278,6 +1342,10 @@ int main(int argc, char **argv)
if (check_setuid())
return EX_USAGE;
+ rc = drop_capabilities(1);
+ if (rc)
+ return EX_SYSERR;
+
if (geteuid()) {
fprintf(stderr, "%s: not installed setuid root - \"user\" "
"CIFS mounts not supported.", thisprogram);