From: Lennart Poettering Date: Tue, 24 Dec 2013 18:31:44 +0000 (+0100) Subject: bus: properly shift cgroup data returned from kdbus by the container's root before... X-Git-Tag: v209~663 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9 bus: properly shift cgroup data returned from kdbus by the container's root before parsing --- diff --git a/src/libsystemd-bus/bus-control.c b/src/libsystemd-bus/bus-control.c index 55986f349..511ca20ee 100644 --- a/src/libsystemd-bus/bus-control.c +++ b/src/libsystemd-bus/bus-control.c @@ -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; diff --git a/src/libsystemd-bus/bus-creds.c b/src/libsystemd-bus/bus-creds.c index ffd72a7a3..b2cf68737 100644 --- a/src/libsystemd-bus/bus-creds.c +++ b/src/libsystemd-bus/bus-creds.c @@ -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); } diff --git a/src/libsystemd-bus/bus-creds.h b/src/libsystemd-bus/bus-creds.h index 089a64bfc..d8b4aca2a 100644 --- a/src/libsystemd-bus/bus-creds.h +++ b/src/libsystemd-bus/bus-creds.h @@ -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); diff --git a/src/libsystemd-bus/bus-internal.h b/src/libsystemd-bus/bus-internal.h index 673f30eb9..e4ef6e64e 100644 --- a/src/libsystemd-bus/bus-internal.h +++ b/src/libsystemd-bus/bus-internal.h @@ -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)) diff --git a/src/libsystemd-bus/bus-kernel.c b/src/libsystemd-bus/bus-kernel.c index 19d97b7e0..8a5b210fe 100644 --- a/src/libsystemd-bus/bus-kernel.c +++ b/src/libsystemd-bus/bus-kernel.c @@ -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: diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c index 910a5f813..77690a07b 100644 --- a/src/libsystemd-bus/sd-bus.c +++ b/src/libsystemd-bus/sd-bus.c @@ -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); diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c index 74889b636..27eee8eac 100644 --- a/src/shared/cgroup-util.c +++ b/src/shared/cgroup-util.c @@ -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; } diff --git a/src/shared/cgroup-util.h b/src/shared/cgroup-util.h index 3e6a3f6ab..743d902e2 100644 --- a/src/shared/cgroup-util.h +++ b/src/shared/cgroup-util.h @@ -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); diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c index f94f213f5..12dcc17dd 100644 --- a/src/test/test-cgroup-util.c +++ b/src/test/test-cgroup-util.c @@ -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; }