[systemd-devel] [PATCH] bus-proxy: --clone-smack-label option

Przemyslaw Kedzierski p.kedzierski at samsung.com
Wed Nov 5 07:08:45 PST 2014


This patch adds a '--clone-smack-label' option to systemd-bus-proxyd.
When dbus client connects to systemd-bus-proxyd through Unix domain socket
and this option is enabled
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.

Change-Id: I5a2c77348d4d293dd3707e82349cf624ddaf744a
Signed-off-by: Przemyslaw Kedzierski <p.kedzierski at samsung.com>
---
 man/systemd-bus-proxyd.xml  |  9 +++++++++
 src/bus-proxyd/bus-proxyd.c | 37 +++++++++++++++++++++++++++++++++++++
 src/shared/capability.c     | 18 ++++++++++++++++++
 src/shared/capability.h     |  2 ++
 src/shared/smack-util.c     | 18 ++++++++++++++++++
 src/shared/smack-util.h     |  1 +
 6 files changed, 85 insertions(+)

diff --git a/man/systemd-bus-proxyd.xml b/man/systemd-bus-proxyd.xml
index f9400f0..0aa24cf 100644
--- a/man/systemd-bus-proxyd.xml
+++ b/man/systemd-bus-proxyd.xml
@@ -87,6 +87,15 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
         </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--clone-smack-label</option></term>
+
+        <listitem>
+          <para>Take client's smack label and set for itself.
+          The <command>systemd-bus-proxyd</command> needs CAP_MAC_ADMIN to manipulate it.</para>
+        </listitem>
+      </varlistentry>
+
       <xi:include href="standard-options.xml" xpointer="help" />
       <xi:include href="standard-options.xml" xpointer="version" />
     </variablelist>
diff --git a/src/bus-proxyd/bus-proxyd.c b/src/bus-proxyd/bus-proxyd.c
index d10de2f..ae8cd02 100644
--- a/src/bus-proxyd/bus-proxyd.c
+++ b/src/bus-proxyd/bus-proxyd.c
@@ -45,11 +45,13 @@
 #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;
 static bool arg_drop_privileges = false;
 static char **arg_configuration = NULL;
+static bool arg_clone_smack_label = false;
 
 static int help(void) {
 
@@ -58,6 +60,7 @@ static int help(void) {
                "  -h --help               Show this help\n"
                "     --version            Show package version\n"
                "     --drop-privileges    Drop privileges\n"
+               "     --clone-smack-label  Clone smack label\n"
                "     --configuration=PATH Configuration file or directory\n"
                "     --machine=MACHINE    Connect to specified machine\n"
                "     --address=ADDRESS    Connect to the bus specified by ADDRESS\n"
@@ -75,6 +78,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_DROP_PRIVILEGES,
                 ARG_CONFIGURATION,
                 ARG_MACHINE,
+                ARG_CLONE_SMACK_LABEL,
         };
 
         static const struct option options[] = {
@@ -84,6 +88,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "drop-privileges", no_argument,       NULL, ARG_DROP_PRIVILEGES },
                 { "configuration",   required_argument, NULL, ARG_CONFIGURATION   },
                 { "machine",         required_argument, NULL, ARG_MACHINE         },
+                { "clone-smack-label", no_argument,     NULL, ARG_CLONE_SMACK_LABEL },
                 {},
         };
 
@@ -149,6 +154,9 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
                 }
 
+                case ARG_CLONE_SMACK_LABEL:
+                        arg_clone_smack_label = true;
+                        break;
                 case '?':
                         return -EINVAL;
 
@@ -1168,6 +1176,35 @@ int main(int argc, char *argv[]) {
         if (is_unix) {
                 (void) getpeercred(in_fd, &ucred);
                 (void) getpeersec(in_fd, &peersec);
+
+                if (arg_clone_smack_label) {
+
+                        if (!mac_smack_use()) {
+                                log_warning("No SMACK found");
+                                goto exit_clone_smack_label;
+                        }
+
+                        if (!peersec) {
+                                log_warning("Invalid SMACK label");
+                                goto exit_clone_smack_label;
+                        }
+
+                        r = have_effective_cap(CAP_MAC_ADMIN);
+                        if (r <= 0) {
+                                log_warning("No CAP_MAC_ADMIN capability");
+                                goto exit_clone_smack_label;
+                        }
+
+                        r = mac_smack_set_current_label(peersec);
+                        if (r < 0) {
+                                log_warning("Failed to set SMACK label %s : %s", peersec, strerror(-r));
+                        }
+exit_clone_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..7d079c7 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_current_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..a34ffd1 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_current_label(char *label);
-- 
2.1.2



More information about the systemd-devel mailing list