summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2010-04-01 15:28:57 -0400
committerJeff Layton <jlayton@redhat.com>2010-04-01 15:28:57 -0400
commitda54228cd9e6fe144efcb2d6da87e3cbb5db5b4c (patch)
tree637b63873a366cd5a98977cc4c75e3c05f6238e0
parent810f7e4e0f2dbcbee0294d9b371071cb08268200 (diff)
downloadcifs-utils-da54228cd9e6fe144efcb2d6da87e3cbb5db5b4c.tar.gz
cifs-utils-da54228cd9e6fe144efcb2d6da87e3cbb5db5b4c.tar.bz2
cifs-utils-da54228cd9e6fe144efcb2d6da87e3cbb5db5b4c.zip
mount.cifs: drop capabilities if libcap is available
Might as well be as safe as possible. Have child drop all capabilities, and have the parent drop all but CAP_SYS_ADMIN (needed for mounting) and CAP_DAC_OVERRIDE (needed in case mtab isn't writable by root). We might even eventually consider being clever and dropping CAP_DAC_OVERRIDE when root has access to the mtab. Signed-off-by: Jeff Layton <jlayton@redhat.com>
-rw-r--r--Makefile.am3
-rw-r--r--aclocal/libcap.m420
-rw-r--r--configure.ac3
-rw-r--r--mount.cifs.c68
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);