[systemd-devel] [PATCH] bus-proxy: cloning smack label

Przemyslaw Kedzierski p.kedzierski at samsung.com
Tue Dec 9 03:17:24 PST 2014


When dbus client connects to systemd-bus-proxyd through
Unix domain socket proxy takes client's smack label and sets for itself.

It is done before and independent of dropping privileges.

The reason of such soluton is fact that tests of access rights
performed by lsm may take place inside kernel, not only
in userspace of recipient of message.

The bus-proxyd needs CAP_MAC_ADMIN to manipulate its label.

In case of systemd running in system mode, CAP_MAC_ADMIN
should be added to CapabilityBoundingSet in service file of bus-proxyd.

In case of systemd running in user mode ('systemd --user')
it can be achieved by addition
Capabilities=cap_mac_admin=i and SecureBits=keep-caps
to user at .service file
and setting cap_mac_admin+ei on bus-proxyd binary.
---
 Makefile.am                             | 11 +++++++++--
 configure.ac                            |  4 ++++
 src/bus-proxyd/bus-proxyd.c             | 20 ++++++++++++++++++++
 src/shared/capability.c                 | 18 ++++++++++++++++++
 src/shared/capability.h                 |  2 ++
 units/systemd-bus-proxyd at .service.in    | 22 ----------------------
 units/systemd-bus-proxyd at .service.m4.in | 22 ++++++++++++++++++++++
 units/user at .service.in                  | 19 -------------------
 units/user at .service.m4.in               | 23 +++++++++++++++++++++++
 9 files changed, 98 insertions(+), 43 deletions(-)
 delete mode 100644 units/systemd-bus-proxyd at .service.in
 create mode 100644 units/systemd-bus-proxyd at .service.m4.in
 delete mode 100644 units/user at .service.in
 create mode 100644 units/user at .service.m4.in

diff --git a/Makefile.am b/Makefile.am
index 7b43733..78cf4a9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -591,7 +591,7 @@ EXTRA_DIST += \
 	units/systemd-fsck at .service.in \
 	units/systemd-fsck-root.service.in \
 	units/systemd-machine-id-commit.service.in \
-	units/user at .service.in \
+	units/user at .service.m4.in \
 	units/debug-shell.service.in \
 	units/systemd-suspend.service.in \
 	units/quotaon.service.in \
@@ -2579,9 +2579,16 @@ dist_userunit_DATA += \
 endif
 
 EXTRA_DIST += \
-	units/systemd-bus-proxyd at .service.in \
+	units/systemd-bus-proxyd at .service.m4.in \
 	units/user/systemd-bus-proxyd at .service.in
 
+if HAVE_SMACK
+bus-proxyd-set-cap-hook:
+	$(SETCAP) cap_mac_admin+ei $(DESTDIR)$(rootlibexecdir)/systemd-bus-proxyd
+
+INSTALL_EXEC_HOOKS += bus-proxyd-set-cap-hook
+endif
+
 # ------------------------------------------------------------------------------
 systemd_tty_ask_password_agent_SOURCES = \
 	src/tty-ask-password-agent/tty-ask-password-agent.c
diff --git a/configure.ac b/configure.ac
index 356a3c3..94b4a02 100644
--- a/configure.ac
+++ b/configure.ac
@@ -90,6 +90,8 @@ AC_PATH_PROG([XSLTPROC], [xsltproc])
 AC_PATH_PROG([QUOTAON], [quotaon], [/usr/sbin/quotaon], [$PATH:/usr/sbin:/sbin])
 AC_PATH_PROG([QUOTACHECK], [quotacheck], [/usr/sbin/quotacheck], [$PATH:/usr/sbin:/sbin])
 
+AC_PATH_PROG([SETCAP], [setcap], [/usr/sbin/setcap], [$PATH:/usr/sbin:/sbin])
+
 AC_PATH_PROG([KILL], [kill], [/usr/bin/kill], [$PATH:/usr/sbin:/sbin])
 
 AC_PATH_PROG([KMOD], [kmod], [/usr/bin/kmod], [$PATH:/usr/sbin:/sbin])
@@ -674,6 +676,8 @@ if test "x${have_smack}" = xyes ; then
         AC_DEFINE(HAVE_SMACK, 1, [Define if SMACK is available])
 fi
 
+AM_CONDITIONAL([HAVE_SMACK], [test "x$have_smack" = "xyes"])
+
 # ------------------------------------------------------------------------------
 AC_ARG_ENABLE([gcrypt],
         AS_HELP_STRING([--disable-gcrypt],[Disable optional GCRYPT support]),
diff --git a/src/bus-proxyd/bus-proxyd.c b/src/bus-proxyd/bus-proxyd.c
index 42fb0da..a9940f1 100644
--- a/src/bus-proxyd/bus-proxyd.c
+++ b/src/bus-proxyd/bus-proxyd.c
@@ -46,6 +46,7 @@
 #include "capability.h"
 #include "bus-policy.h"
 #include "bus-control.h"
+#include "smack-util.h"
 
 static char *arg_address = NULL;
 static char *arg_command_line_buffer = NULL;
@@ -1235,6 +1236,18 @@ static int patch_sender(sd_bus *a, sd_bus_message *m) {
         return 0;
 }
 
+static int mac_smack_apply_label_and_drop_cap_mac_admin(pid_t its_pid, const char *new_label) {
+
+        int r1 = 0, r2 = 0;
+        if (mac_smack_use()) {
+                if (new_label && its_pid)
+                        r1 = mac_smack_apply_pid(its_pid, new_label);
+
+                r2 = drop_capability(CAP_MAC_ADMIN);
+        }
+        return (r1 < 0) ? r1 : r2;
+}
+
 int main(int argc, char *argv[]) {
 
         _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
@@ -1274,6 +1287,13 @@ int main(int argc, char *argv[]) {
         if (is_unix) {
                 (void) getpeercred(in_fd, &ucred);
                 (void) getpeersec(in_fd, &peersec);
+
+#ifdef HAVE_SMACK
+                r = mac_smack_apply_label_and_drop_cap_mac_admin(getpid(), peersec);
+                if (r < 0)
+                        log_warning("Failed to set SMACK label (%s) and drop"
+                                    " CAP_MAC_ADMIN : %s", peersec, strerror(-r));
+#endif
         }
 
         if (arg_drop_privileges) {
diff --git a/src/shared/capability.c b/src/shared/capability.c
index 5d156ab..65d7e03 100644
--- a/src/shared/capability.c
+++ b/src/shared/capability.c
@@ -271,3 +271,21 @@ int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities) {
 
         return 0;
 }
+
+int drop_capability(cap_value_t cv) {
+        _cleanup_cap_free_ cap_t tmp_cap = NULL;
+
+        tmp_cap = cap_get_proc();
+        if (!tmp_cap)
+                return -errno;
+
+        if ((cap_set_flag(tmp_cap, CAP_INHERITABLE, 1, &cv, CAP_CLEAR) < 0) ||
+            (cap_set_flag(tmp_cap, CAP_PERMITTED, 1, &cv, CAP_CLEAR) < 0) ||
+            (cap_set_flag(tmp_cap, CAP_EFFECTIVE, 1, &cv, CAP_CLEAR) < 0))
+                return -errno;
+
+        if (cap_set_proc(tmp_cap) < 0)
+                return -errno;
+
+        return 0;
+}
diff --git a/src/shared/capability.h b/src/shared/capability.h
index 3e6d999..6f2f6f9 100644
--- a/src/shared/capability.h
+++ b/src/shared/capability.h
@@ -34,6 +34,8 @@ int capability_bounding_set_drop_usermode(uint64_t drop);
 
 int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilites);
 
+int drop_capability(cap_value_t cv);
+
 DEFINE_TRIVIAL_CLEANUP_FUNC(cap_t, cap_free);
 #define _cleanup_cap_free_ _cleanup_(cap_freep)
 
diff --git a/units/systemd-bus-proxyd at .service.in b/units/systemd-bus-proxyd at .service.in
deleted file mode 100644
index 23b5ffa..0000000
--- a/units/systemd-bus-proxyd at .service.in
+++ /dev/null
@@ -1,22 +0,0 @@
-#  This file is part of systemd.
-#
-#  systemd is free software; you can redistribute it and/or modify it
-#  under the terms of the GNU Lesser General Public License as published by
-#  the Free Software Foundation; either version 2.1 of the License, or
-#  (at your option) any later version.
-
-[Unit]
-Description=Legacy D-Bus Protocol Compatibility Daemon
-
-[Service]
-# The first argument will be replaced by the service by information on
-# the process requesting the proxy, we need a placeholder to keep the
-# space available for this.
-ExecStart=@rootlibexecdir@/systemd-bus-proxyd --drop-privileges --address=kernel:path=/sys/fs/kdbus/0-system/bus xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-NotifyAccess=main
-CapabilityBoundingSet=CAP_IPC_OWNER CAP_SETUID CAP_SETGID CAP_SETPCAP
-PrivateTmp=yes
-PrivateDevices=yes
-PrivateNetwork=yes
-ProtectSystem=full
-ProtectHome=yes
diff --git a/units/systemd-bus-proxyd at .service.m4.in b/units/systemd-bus-proxyd at .service.m4.in
new file mode 100644
index 0000000..3f3ab64
--- /dev/null
+++ b/units/systemd-bus-proxyd at .service.m4.in
@@ -0,0 +1,22 @@
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+[Unit]
+Description=Legacy D-Bus Protocol Compatibility Daemon
+
+[Service]
+# The first argument will be replaced by the service by information on
+# the process requesting the proxy, we need a placeholder to keep the
+# space available for this.
+ExecStart=@rootlibexecdir@/systemd-bus-proxyd --drop-privileges --address=kernel:path=/sys/fs/kdbus/0-system/bus xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+NotifyAccess=main
+CapabilityBoundingSet=CAP_IPC_OWNER CAP_SETUID CAP_SETGID CAP_SETPCAP m4_ifdef(`HAVE_SMACK', CAP_MAC_ADMIN )
+PrivateTmp=yes
+PrivateDevices=yes
+PrivateNetwork=yes
+ProtectSystem=full
+ProtectHome=yes
diff --git a/units/user at .service.in b/units/user at .service.in
deleted file mode 100644
index 1e21d51..0000000
--- a/units/user at .service.in
+++ /dev/null
@@ -1,19 +0,0 @@
-#  This file is part of systemd.
-#
-#  systemd is free software; you can redistribute it and/or modify it
-#  under the terms of the GNU Lesser General Public License as published by
-#  the Free Software Foundation; either version 2.1 of the License, or
-#  (at your option) any later version.
-
-[Unit]
-Description=User Manager for UID %i
-After=systemd-user-sessions.service
-
-[Service]
-User=%i
-PAMName=systemd-user
-Type=notify
-ExecStart=- at rootlibexecdir@/systemd --user
-Slice=user-%i.slice
-KillMode=mixed
-Delegate=yes
diff --git a/units/user at .service.m4.in b/units/user at .service.m4.in
new file mode 100644
index 0000000..340c02b
--- /dev/null
+++ b/units/user at .service.m4.in
@@ -0,0 +1,23 @@
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+[Unit]
+Description=User Manager for UID %i
+After=systemd-user-sessions.service
+
+[Service]
+User=%i
+PAMName=systemd-user
+Type=notify
+ExecStart=- at rootlibexecdir@/systemd --user
+Slice=user-%i.slice
+KillMode=mixed
+Delegate=yes
+m4_ifdef(`HAVE_SMACK',
+Capabilities=cap_mac_admin=i
+SecureBits=keep-caps
+)
-- 
2.1.2



More information about the systemd-devel mailing list