diff options
-rw-r--r-- | Makefile.am | 3 | ||||
-rw-r--r-- | aclocal/libcap.m4 | 20 | ||||
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | mount.cifs.c | 68 |
4 files changed, 94 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am index fea8bdc..605206e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 diff --git a/aclocal/libcap.m4 b/aclocal/libcap.m4 new file mode 100644 index 0000000..0b42689 --- /dev/null +++ b/aclocal/libcap.m4 @@ -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 diff --git a/configure.ac b/configure.ac index 9f00bea..46a5848 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/mount.cifs.c b/mount.cifs.c index aa5c9f9..c7954ce 100644 --- a/mount.cifs.c +++ b/mount.cifs.c @@ -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" @@ -1146,6 +1149,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) @@ -1181,6 +1241,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; @@ -1292,6 +1356,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); |