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.
This commit is contained in:
Przemyslaw Kedzierski 2014-12-09 12:17:24 +01:00 committed by Lennart Poettering
parent 4c213d6cf4
commit dd5ae4c36c
7 changed files with 60 additions and 3 deletions

View 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/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

View 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([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]),

View File

@ -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) {

View File

@ -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;
}

View 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_capability(cap_value_t cv);
DEFINE_TRIVIAL_CLEANUP_FUNC(cap_t, cap_free);
#define _cleanup_cap_free_ _cleanup_(cap_freep)

View 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
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

View File

@ -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
)