From dd5ae4c36c89da5dbe8d1628939b26c00db98753 Mon Sep 17 00:00:00 2001 From: Przemyslaw Kedzierski Date: Tue, 9 Dec 2014 12:17:24 +0100 Subject: [PATCH] bus-proxy: cloning smack label 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 | 11 ++++++++-- configure.ac | 4 ++++ src/bus-proxyd/bus-proxyd.c | 22 +++++++++++++++++++ src/shared/capability.c | 18 +++++++++++++++ src/shared/capability.h | 2 ++ ...e.in => systemd-bus-proxyd@.service.m4.in} | 2 +- .../{user@.service.in => user@.service.m4.in} | 4 ++++ 7 files changed, 60 insertions(+), 3 deletions(-) rename units/{systemd-bus-proxyd@.service.in => systemd-bus-proxyd@.service.m4.in} (95%) rename units/{user@.service.in => user@.service.m4.in} (87%) diff --git a/Makefile.am b/Makefile.am index 7b43733eb..78cf4a94f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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/user@.service.in \ + units/user@.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@.service.in \ + units/systemd-bus-proxyd@.service.m4.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 diff --git a/configure.ac b/configure.ac index 356a3c3d6..94b4a0233 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 42fb0da0e..5d304538f 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,23 @@ 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) { +#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; @@ -1274,6 +1292,10 @@ int main(int argc, char *argv[]) { 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) { diff --git a/src/shared/capability.c b/src/shared/capability.c index 5d156ab3c..65d7e038a 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 3e6d9995f..6f2f6f997 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@.service.in b/units/systemd-bus-proxyd@.service.m4.in similarity index 95% rename from units/systemd-bus-proxyd@.service.in rename to units/systemd-bus-proxyd@.service.m4.in index 23b5ffa07..3f3ab64de 100644 --- a/units/systemd-bus-proxyd@.service.in +++ b/units/systemd-bus-proxyd@.service.m4.in @@ -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 -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 diff --git a/units/user@.service.in b/units/user@.service.m4.in similarity index 87% rename from units/user@.service.in rename to units/user@.service.m4.in index 1e21d51aa..340c02b59 100644 --- a/units/user@.service.in +++ b/units/user@.service.m4.in @@ -17,3 +17,7 @@ ExecStart=-@rootlibexecdir@/systemd --user Slice=user-%i.slice KillMode=mixed Delegate=yes +m4_ifdef(`HAVE_SMACK', +Capabilities=cap_mac_admin=i +SecureBits=keep-caps +) -- 2.30.2