chiark / gitweb /
bus-proxy: cloning smack label
authorPrzemyslaw Kedzierski <p.kedzierski@samsung.com>
Tue, 9 Dec 2014 11:17:24 +0000 (12:17 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 9 Dec 2014 17:23:24 +0000 (18:23 +0100)
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@.service file
and setting cap_mac_admin+ei on bus-proxyd binary.

Makefile.am
configure.ac
src/bus-proxyd/bus-proxyd.c
src/shared/capability.c
src/shared/capability.h
units/systemd-bus-proxyd@.service.m4.in [moved from units/systemd-bus-proxyd@.service.in with 95% similarity]
units/user@.service.m4.in [moved from units/user@.service.in with 87% similarity]

index 7b43733eb1d683f5c7a477fb7251ed33e6b3e870..78cf4a94f0880603b8b1be07b4953dc15809d53c 100644 (file)
@@ -591,7 +591,7 @@ EXTRA_DIST += \
        units/systemd-fsck@.service.in \
        units/systemd-fsck-root.service.in \
        units/systemd-machine-id-commit.service.in \
        units/systemd-fsck@.service.in \
        units/systemd-fsck-root.service.in \
        units/systemd-machine-id-commit.service.in \
-       units/user@.service.in \
+       units/user@.service.m4.in \
        units/debug-shell.service.in \
        units/systemd-suspend.service.in \
        units/quotaon.service.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 += \
 endif
 
 EXTRA_DIST += \
-       units/systemd-bus-proxyd@.service.in \
+       units/systemd-bus-proxyd@.service.m4.in \
        units/user/systemd-bus-proxyd@.service.in
 
        units/user/systemd-bus-proxyd@.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
 # ------------------------------------------------------------------------------
 systemd_tty_ask_password_agent_SOURCES = \
        src/tty-ask-password-agent/tty-ask-password-agent.c
index 356a3c3d67d007b00d3ce1d0032ca38e4c5f55a4..94b4a0233aa32a6ef27540b55920a32ab80920a2 100644 (file)
@@ -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([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])
 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
 
         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]),
 # ------------------------------------------------------------------------------
 AC_ARG_ENABLE([gcrypt],
         AS_HELP_STRING([--disable-gcrypt],[Disable optional GCRYPT support]),
index 42fb0da0ef56ec2319139921a941dfd97fc440d0..5d304538fd757db56006f9bef807062ac35a6ef6 100644 (file)
@@ -46,6 +46,7 @@
 #include "capability.h"
 #include "bus-policy.h"
 #include "bus-control.h"
 #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;
 
 static char *arg_address = NULL;
 static char *arg_command_line_buffer = NULL;
@@ -1235,6 +1236,23 @@ static int patch_sender(sd_bus *a, sd_bus_message *m) {
         return 0;
 }
 
         return 0;
 }
 
+static int mac_smack_apply_label_and_drop_cap_mac_admin(pid_t its_pid, const char *new_label) {
+#ifdef HAVE_SMACK
+        int r = 0, k;
+
+        if (!mac_smack_use())
+                return 0;
+
+        if (new_label && its_pid > 0)
+                r = mac_smack_apply_pid(its_pid, new_label);
+
+        k = drop_capability(CAP_MAC_ADMIN);
+        return r < 0 ? r : k;
+#else
+        return 0;
+#endif
+}
+
 int main(int argc, char *argv[]) {
 
         _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
 int main(int argc, char *argv[]) {
 
         _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
@@ -1274,6 +1292,10 @@ int main(int argc, char *argv[]) {
         if (is_unix) {
                 (void) getpeercred(in_fd, &ucred);
                 (void) getpeersec(in_fd, &peersec);
         if (is_unix) {
                 (void) getpeercred(in_fd, &ucred);
                 (void) getpeersec(in_fd, &peersec);
+
+                r = mac_smack_apply_label_and_drop_cap_mac_admin(getpid(), peersec);
+                if (r < 0)
+                        log_warning_errno(r, "Failed to set SMACK label (%s) and drop CAP_MAC_ADMIN: %m", peersec);
         }
 
         if (arg_drop_privileges) {
         }
 
         if (arg_drop_privileges) {
index 5d156ab3cd62e95f44f2347b309ca6ad3daf566e..65d7e038a7a39d305352bf9b4de8d865085a79da 100644 (file)
@@ -271,3 +271,21 @@ int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities) {
 
         return 0;
 }
 
         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;
+}
index 3e6d9995f54209e26ce3355a6b244034687520f3..6f2f6f997d247b29647587444031deba76d8028c 100644 (file)
@@ -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_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)
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(cap_t, cap_free);
 #define _cleanup_cap_free_ _cleanup_(cap_freep)
 
similarity index 95%
rename from units/systemd-bus-proxyd@.service.in
rename to units/systemd-bus-proxyd@.service.m4.in
index 23b5ffa072a3b9d74badc1ebcfbc376455c3c315..3f3ab64deed430b33a4f69dd0082bc3aa132c033 100644 (file)
@@ -14,7 +14,7 @@ Description=Legacy D-Bus Protocol Compatibility Daemon
 # space available for this.
 ExecStart=@rootlibexecdir@/systemd-bus-proxyd --drop-privileges --address=kernel:path=/sys/fs/kdbus/0-system/bus xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
 NotifyAccess=main
 # 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
+CapabilityBoundingSet=CAP_IPC_OWNER CAP_SETUID CAP_SETGID CAP_SETPCAP m4_ifdef(`HAVE_SMACK', CAP_MAC_ADMIN )
 PrivateTmp=yes
 PrivateDevices=yes
 PrivateNetwork=yes
 PrivateTmp=yes
 PrivateDevices=yes
 PrivateNetwork=yes
similarity index 87%
rename from units/user@.service.in
rename to units/user@.service.m4.in
index 1e21d51aaef5b1833577b6bd2db6c2536bc87898..340c02b59b469ee4498e2f6f000dc457ae042659 100644 (file)
@@ -17,3 +17,7 @@ ExecStart=-@rootlibexecdir@/systemd --user
 Slice=user-%i.slice
 KillMode=mixed
 Delegate=yes
 Slice=user-%i.slice
 KillMode=mixed
 Delegate=yes
+m4_ifdef(`HAVE_SMACK',
+Capabilities=cap_mac_admin=i
+SecureBits=keep-caps
+)