chiark / gitweb /
bus: properly shift cgroup data returned from kdbus by the container's root before...
authorLennart Poettering <lennart@poettering.net>
Tue, 24 Dec 2013 18:31:44 +0000 (19:31 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 24 Dec 2013 18:31:44 +0000 (19:31 +0100)
src/libsystemd-bus/bus-control.c
src/libsystemd-bus/bus-creds.c
src/libsystemd-bus/bus-creds.h
src/libsystemd-bus/bus-internal.h
src/libsystemd-bus/bus-kernel.c
src/libsystemd-bus/sd-bus.c
src/shared/cgroup-util.c
src/shared/cgroup-util.h
src/test/test-cgroup-util.c

index 55986f3..511ca20 100644 (file)
@@ -33,6 +33,7 @@
 #include "bus-control.h"
 #include "bus-bloom.h"
 #include "bus-util.h"
+#include "cgroup-util.h"
 
 _public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
         int r;
@@ -489,6 +490,18 @@ static int bus_get_owner_kdbus(
                                         goto fail;
                                 }
 
+                                if (!bus->cgroup_root) {
+                                        r = cg_get_root_path(&bus->cgroup_root);
+                                        if (r < 0)
+                                                goto fail;
+                                }
+
+                                c->cgroup_root = strdup(bus->cgroup_root);
+                                if (!c->cgroup_root) {
+                                        r = -ENOMEM;
+                                        goto fail;
+                                }
+
                                 c->mask |= m;
                         }
                         break;
index ffd72a7..b2cf687 100644 (file)
@@ -91,6 +91,7 @@ _public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) {
                         free(c->capability);
                         free(c->label);
                         free(c->unique_name);
+                        free(c->cgroup_root);
                         free(c);
                 }
         } else {
@@ -283,7 +284,13 @@ _public_ int sd_bus_creds_get_unit(sd_bus_creds *c, const char **ret) {
         assert(c->cgroup);
 
         if (!c->unit) {
-                r = cg_path_get_unit(c->cgroup, (char**) &c->unit);
+                const char *shifted;
+
+                r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
+                if (r < 0)
+                        return r;
+
+                r = cg_path_get_unit(shifted, (char**) &c->unit);
                 if (r < 0)
                         return r;
         }
@@ -304,7 +311,13 @@ _public_ int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **ret) {
         assert(c->cgroup);
 
         if (!c->user_unit) {
-                r = cg_path_get_user_unit(c->cgroup, (char**) &c->user_unit);
+                const char *shifted;
+
+                r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
+                if (r < 0)
+                        return r;
+
+                r = cg_path_get_user_unit(shifted, (char**) &c->user_unit);
                 if (r < 0)
                         return r;
         }
@@ -325,7 +338,13 @@ _public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) {
         assert(c->cgroup);
 
         if (!c->slice) {
-                r = cg_path_get_slice(c->cgroup, (char**) &c->slice);
+                const char *shifted;
+
+                r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
+                if (r < 0)
+                        return r;
+
+                r = cg_path_get_slice(shifted, (char**) &c->slice);
                 if (r < 0)
                         return r;
         }
@@ -346,7 +365,13 @@ _public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) {
         assert(c->cgroup);
 
         if (!c->session) {
-                r = cg_path_get_session(c->cgroup, (char**) &c->session);
+                const char *shifted;
+
+                r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
+                if (r < 0)
+                        return r;
+
+                r = cg_path_get_session(shifted, (char**) &c->session);
                 if (r < 0)
                         return r;
         }
@@ -356,6 +381,9 @@ _public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) {
 }
 
 _public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) {
+        const char *shifted;
+        int r;
+
         assert_return(c, -EINVAL);
         assert_return(uid, -EINVAL);
 
@@ -364,7 +392,11 @@ _public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) {
 
         assert(c->cgroup);
 
-        return cg_path_get_owner_uid(c->cgroup, uid);
+        r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
+        if (r < 0)
+                return r;
+
+        return cg_path_get_owner_uid(shifted, uid);
 }
 
 _public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) {
@@ -711,6 +743,10 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
                 if (r < 0)
                         return r;
 
+                r = cg_get_root_path(&c->cgroup_root);
+                if (r < 0)
+                        return r;
+
                 c->mask |= missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID);
         }
 
@@ -816,6 +852,10 @@ int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret)
                 if (!n->cgroup)
                         return -ENOMEM;
 
+                n->cgroup_root = strdup(c->cgroup_root);
+                if (!n->cgroup_root)
+                        return -ENOMEM;
+
                 n->mask |= mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_OWNER_UID);
         }
 
index 089a64b..d8b4aca 100644 (file)
@@ -62,6 +62,8 @@ struct sd_bus_creds {
         char *unique_name;
 
         char **well_known_names;
+
+        char *cgroup_root;
 };
 
 sd_bus_creds* bus_creds_new(void);
index 673f30e..e4ef6e6 100644 (file)
@@ -264,6 +264,8 @@ struct sd_bus {
 
         struct kdbus_creds fake_creds;
         char *fake_label;
+
+        char *cgroup_root;
 };
 
 #define BUS_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC))
index 19d97b7..8a5b210 100644 (file)
@@ -35,6 +35,7 @@
 #include "bus-kernel.h"
 #include "bus-bloom.h"
 #include "bus-util.h"
+#include "cgroup-util.h"
 
 #define UNIQUE_NAME_MAX (3+DECIMAL_STR_MAX(uint64_t))
 
@@ -845,6 +846,15 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
                 case KDBUS_ITEM_CGROUP:
                         m->creds.cgroup = d->str;
                         m->creds.mask |= (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID) & bus->creds_mask;
+
+                        if (!bus->cgroup_root) {
+                                r = cg_get_root_path(&bus->cgroup_root);
+                                if (r < 0)
+                                        goto fail;
+                        }
+
+                        m->creds.cgroup_root = bus->cgroup_root;
+
                         break;
 
                 case KDBUS_ITEM_AUDIT:
index 910a5f8..77690a0 100644 (file)
@@ -142,6 +142,7 @@ static void bus_free(sd_bus *b) {
         free(b->kernel);
         free(b->machine);
         free(b->fake_label);
+        free(b->cgroup_root);
 
         free(b->exec_path);
         strv_free(b->exec_argv);
index 74889b6..27eee8e 100644 (file)
@@ -1082,42 +1082,62 @@ int cg_get_root_path(char **path) {
         return 0;
 }
 
-int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) {
-        _cleanup_free_ char *cg_root = NULL;
-        char *cg_process, *p;
+int cg_shift_path(const char *cgroup, const char *root, const char **shifted) {
+        _cleanup_free_ char *rt = NULL;
+        char *p;
         int r;
 
-        assert(pid >= 0);
         assert(cgroup);
+        assert(shifted);
 
         if (!root) {
                 /* If the root was specified let's use that, otherwise
                  * let's determine it from PID 1 */
 
-                r = cg_get_root_path(&cg_root);
+                r = cg_get_root_path(&rt);
                 if (r < 0)
                         return r;
 
-                root = cg_root;
+                root = rt;
         }
 
-        r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cg_process);
+        p = path_startswith(cgroup, root);
+        if (p)
+                *shifted = p - 1;
+        else
+                *shifted = cgroup;
+
+        return 0;
+}
+
+int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) {
+        _cleanup_free_ char *raw = NULL;
+        const char *c;
+        int r;
+
+        assert(pid >= 0);
+        assert(cgroup);
+
+        r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &raw);
         if (r < 0)
                 return r;
 
-        p = path_startswith(cg_process, root);
-        if (p) {
-                char *c;
+        r = cg_shift_path(raw, root, &c);
+        if (r < 0)
+                return r;
 
-                c = strdup(p - 1);
-                free(cg_process);
+        if (c == raw) {
+                *cgroup = raw;
+                raw = NULL;
+        } else {
+                char *n;
 
-                if (!c)
+                n = strdup(c);
+                if (!n)
                         return -ENOMEM;
 
-                *cgroup = c;
-        } else
-                *cgroup = cg_process;
+                *cgroup = n;
+        }
 
         return 0;
 }
index 3e6a3f6..743d902 100644 (file)
@@ -103,6 +103,7 @@ int cg_path_get_user_unit(const char *path, char **unit);
 int cg_path_get_machine_name(const char *path, char **machine);
 int cg_path_get_slice(const char *path, char **slice);
 
+int cg_shift_path(const char *cgroup, const char *cached_root, const char **shifted);
 int cg_pid_get_path_shifted(pid_t pid, const char *cached_root, char **cgroup);
 
 int cg_pid_get_session(pid_t pid, char **session);
index f94f213..12dcc17 100644 (file)
@@ -246,6 +246,21 @@ static void test_slice_to_path(void) {
         test_slice_to_path_one("a-b-c-d-e.slice", "a.slice/a-b.slice/a-b-c.slice/a-b-c-d.slice/a-b-c-d-e.slice", 0);
 }
 
+static void test_shift_path_one(const char *raw, const char *root, const char *shifted) {
+        const char *s = NULL;
+
+        assert_se(cg_shift_path(raw, root, &s) >= 0);
+        assert_se(streq(s, shifted));
+}
+
+static void test_shift_path(void) {
+
+        test_shift_path_one("/foobar/waldo", "/", "/foobar/waldo");
+        test_shift_path_one("/foobar/waldo", "", "/foobar/waldo");
+        test_shift_path_one("/foobar/waldo", "/foobar", "/waldo");
+        test_shift_path_one("/foobar/waldo", "/fuckfuck", "/foobar/waldo");
+}
+
 int main(void) {
         test_path_decode_unit();
         test_path_get_unit();
@@ -258,6 +273,7 @@ int main(void) {
         TEST_REQ_RUNNING_SYSTEMD(test_escape());
         test_controller_is_valid();
         test_slice_to_path();
+        test_shift_path();
 
         return 0;
 }