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

Lennart Poettering lennart at poettering.net
Tue Dec 9 09:26:17 PST 2014


On Tue, 09.12.14 12:17, Przemyslaw Kedzierski (p.kedzierski at samsung.com) wrote:

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

Looks good! Applied!

(made some minor changes though, we try to avoid strerror() nowadays,
and log_warning_errno() instead with %m)

Thanks!

> ---
>  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
> 
> _______________________________________________
> systemd-devel mailing list
> systemd-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Lennart

-- 
Lennart Poettering, Red Hat


More information about the systemd-devel mailing list