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

Przemyslaw Kedzierski p.kedzierski at samsung.com
Thu Nov 6 02:44:38 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.

Signed-off-by: Przemyslaw Kedzierski <p.kedzierski at samsung.com>
---
 src/bus-proxyd/bus-proxyd.c          | 16 ++++++++++++++++
 src/shared/capability.c              | 18 ++++++++++++++++++
 src/shared/capability.h              |  2 ++
 src/shared/smack-util.c              | 18 ++++++++++++++++++
 src/shared/smack-util.h              |  1 +
 units/systemd-bus-proxyd at .service.in |  2 +-
 units/user at .service.in               |  2 ++
 7 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/src/bus-proxyd/bus-proxyd.c b/src/bus-proxyd/bus-proxyd.c
index d10de2f..066232e 100644
--- a/src/bus-proxyd/bus-proxyd.c
+++ b/src/bus-proxyd/bus-proxyd.c
@@ -45,6 +45,7 @@
 #include "def.h"
 #include "capability.h"
 #include "bus-policy.h"
+#include "smack-util.h"
 
 static char *arg_address = NULL;
 static char *arg_command_line_buffer = NULL;
@@ -1168,6 +1169,21 @@ int main(int argc, char *argv[]) {
         if (is_unix) {
                 (void) getpeercred(in_fd, &ucred);
                 (void) getpeersec(in_fd, &peersec);
+
+                if (mac_smack_use()) {
+                        if (peersec) {
+
+                                r = mac_smack_set_process_label(peersec);
+                                if (r < 0)
+                                        log_warning("Failed to set SMACK label %s : %s", peersec, strerror(-r));
+                        } else {
+                                log_warning("Invalid SMACK label");
+                        }
+
+                        r = drop_capability(CAP_MAC_ADMIN);
+                        if (r < 0)
+                                log_warning("Failed to drop CAP_MAC_ADMIN: %s", strerror(-r));
+                }
         }
 
         if (arg_drop_privileges) {
diff --git a/src/shared/capability.c b/src/shared/capability.c
index 0226542..9dc42ec 100644
--- a/src/shared/capability.c
+++ b/src/shared/capability.c
@@ -285,3 +285,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/src/shared/smack-util.c b/src/shared/smack-util.c
index a8dccd1..3e9810c 100644
--- a/src/shared/smack-util.c
+++ b/src/shared/smack-util.c
@@ -181,3 +181,21 @@ int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
 
         return r;
 }
+
+int mac_smack_set_process_label(char *label) {
+#ifdef HAVE_SMACK
+        int ret;
+
+        if (!label) {
+                log_debug("No SMACK label given");
+                return -1;
+        }
+        ret = write_string_file("/proc/self/attr/current", label);
+        if (ret) {
+                log_debug("Failed to set current SMACK label \"%s\" on self: %s",
+                          label, strerror(-ret));
+                return ret;
+        }
+#endif
+        return 0;
+}
diff --git a/src/shared/smack-util.h b/src/shared/smack-util.h
index 68778da..a49405b 100644
--- a/src/shared/smack-util.h
+++ b/src/shared/smack-util.h
@@ -33,3 +33,4 @@ int mac_smack_apply(const char *path, const char *label);
 int mac_smack_apply_fd(int fd, const char *label);
 int mac_smack_apply_ip_in_fd(int fd, const char *label);
 int mac_smack_apply_ip_out_fd(int fd, const char *label);
+int mac_smack_set_process_label(char *label);
diff --git a/units/systemd-bus-proxyd at .service.in b/units/systemd-bus-proxyd at .service.in
index eef703f..654bfb2 100644
--- a/units/systemd-bus-proxyd at .service.in
+++ b/units/systemd-bus-proxyd at .service.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=/dev/kdbus/0-system/bus --configuration=/etc/dbus-1/system.conf --configuration=/etc/dbus-1/system-local.conf --configuration=/etc/dbus-1/system.d/ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
 NotifyAccess=main
-CapabilityBoundingSet=CAP_IPC_OWNER CAP_SETUID CAP_SETGID CAP_SETPCAP
+CapabilityBoundingSet=CAP_IPC_OWNER CAP_SETUID CAP_SETGID CAP_SETPCAP CAP_MAC_ADMIN
 PrivateTmp=yes
 PrivateDevices=yes
 PrivateNetwork=yes
diff --git a/units/user at .service.in b/units/user at .service.in
index 8091ce1..9c0903e 100644
--- a/units/user at .service.in
+++ b/units/user at .service.in
@@ -16,3 +16,5 @@ Type=notify
 ExecStart=- at rootlibexecdir@/systemd --user
 Slice=user-%i.slice
 KillMode=mixed
+Capabilities=cap_mac_admin=i
+SecureBits=keep-caps
-- 
2.1.2



More information about the systemd-devel mailing list