From: Lennart Poettering Date: Thu, 30 Apr 2015 09:58:06 +0000 (+0200) Subject: sd-bus,sd-login: add api for querying the slice within the the user systemd instance... X-Git-Tag: v226.4~1^2~411 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=8a6fd3c58501b9f27036a217b00f4fd9393731f6 sd-bus,sd-login: add api for querying the slice within the the user systemd instance of a process units are organized in slice trees, not only for the system instance, but also for user systemd instances, expose this properly. --- diff --git a/src/libelogind/libelogind.sym.m4 b/src/libelogind/libelogind.sym.m4 index 098b6a0c7..8c28d7205 100644 --- a/src/libelogind/libelogind.sym.m4 +++ b/src/libelogind/libelogind.sym.m4 @@ -163,6 +163,12 @@ global: sd_pid_notify_with_fds; } LIBSYSTEMD_217; +LIBSYSTEMD_220 { +global: + sd_pid_get_user_slice; + sd_peer_get_user_slice; +} LIBSYSTEMD_219; + m4_ifdef(`ENABLE_KDBUS', LIBSYSTEMD_FUTURE { global: @@ -334,8 +340,9 @@ global: sd_bus_creds_get_cmdline; sd_bus_creds_get_cgroup; sd_bus_creds_get_unit; - sd_bus_creds_get_user_unit; sd_bus_creds_get_slice; + sd_bus_creds_get_user_unit; + sd_bus_creds_get_user_slice; sd_bus_creds_get_session; sd_bus_creds_get_owner_uid; sd_bus_creds_has_effective_cap; @@ -459,5 +466,5 @@ global: /* sd-path */ sd_path_home; sd_path_search; -} LIBSYSTEMD_217; +} LIBSYSTEMD_220; ) diff --git a/src/libelogind/sd-bus/bus-creds.c b/src/libelogind/sd-bus/bus-creds.c index 44fad0be0..1ae5a12eb 100644 --- a/src/libelogind/sd-bus/bus-creds.c +++ b/src/libelogind/sd-bus/bus-creds.c @@ -53,6 +53,7 @@ void bus_creds_done(sd_bus_creds *c) { free(c->unit); free(c->user_unit); free(c->slice); + free(c->user_slice); free(c->unescaped_description); free(c->supplementary_gids); free(c->tty); @@ -433,6 +434,33 @@ _public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) { return 0; } +_public_ int sd_bus_creds_get_user_slice(sd_bus_creds *c, const char **ret) { + int r; + + assert_return(c, -EINVAL); + assert_return(ret, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_USER_SLICE)) + return -ENODATA; + + assert(c->cgroup); + + if (!c->user_slice) { + const char *shifted; + + r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted); + if (r < 0) + return r; + + r = cg_path_get_user_slice(shifted, (char**) &c->user_slice); + if (r < 0) + return r; + } + + *ret = c->user_slice; + return 0; +} + _public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) { int r; @@ -980,7 +1008,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) { c->mask |= SD_BUS_CREDS_TID_COMM; } - if (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)) { + if (missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID)) { if (!c->cgroup) { r = cg_pid_get_path(NULL, pid, &c->cgroup); @@ -997,7 +1025,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) { } if (c->cgroup) - 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); + c->mask |= missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID); } if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) { @@ -1191,7 +1219,7 @@ int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) n->mask |= SD_BUS_CREDS_CMDLINE; } - if (c->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)) { + if (c->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_USER_SLICE|SD_BUS_CREDS_OWNER_UID)) { assert(c->cgroup); n->cgroup = strdup(c->cgroup); @@ -1202,7 +1230,7 @@ int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) 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); + 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_USER_SLICE|SD_BUS_CREDS_OWNER_UID); } if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) { diff --git a/src/libelogind/sd-bus/bus-creds.h b/src/libelogind/sd-bus/bus-creds.h index 42f76b897..209d21612 100644 --- a/src/libelogind/sd-bus/bus-creds.h +++ b/src/libelogind/sd-bus/bus-creds.h @@ -61,6 +61,7 @@ struct sd_bus_creds { char *unit; char *user_unit; char *slice; + char *user_slice; char *tty; diff --git a/src/libelogind/sd-bus/bus-dump.c b/src/libelogind/sd-bus/bus-dump.c index 47a5c6b3a..9db86adb7 100644 --- a/src/libelogind/sd-bus/bus-dump.c +++ b/src/libelogind/sd-bus/bus-dump.c @@ -335,7 +335,7 @@ int bus_creds_dump(sd_bus_creds *c, FILE *f, bool terse) { uint32_t audit_sessionid; char **cmdline = NULL, **well_known = NULL; const char *prefix, *color, *suffix, *s; - int r, q, v, w; + int r, q, v, w, z; assert(c); @@ -447,19 +447,23 @@ int bus_creds_dump(sd_bus_creds *c, FILE *f, bool terse) { if (r != -ENODATA) fprintf(f, "%sUnit=%s%s%s", prefix, color, strna(s), suffix); s = NULL; - q = sd_bus_creds_get_user_unit(c, &s); - if (q != -ENODATA) - fprintf(f, "%sUserUnit=%s%s%s", prefix, color, strna(s), suffix); - s = NULL; v = sd_bus_creds_get_slice(c, &s); if (v != -ENODATA) fprintf(f, "%sSlice=%s%s%s", prefix, color, strna(s), suffix); s = NULL; - w = sd_bus_creds_get_session(c, &s); + q = sd_bus_creds_get_user_unit(c, &s); + if (q != -ENODATA) + fprintf(f, "%sUserUnit=%s%s%s", prefix, color, strna(s), suffix); + s = NULL; + w = sd_bus_creds_get_user_slice(c, &s); if (w != -ENODATA) + fprintf(f, "%sUserSlice=%s%s%s", prefix, color, strna(s), suffix); + s = NULL; + z = sd_bus_creds_get_session(c, &s); + if (z != -ENODATA) fprintf(f, "%sSession=%s%s%s", prefix, color, strna(s), suffix); - if (terse && ((c->mask & SD_BUS_CREDS_CGROUP) || r != -ENODATA || q != -ENODATA || v != -ENODATA || w != -ENODATA)) + if (terse && ((c->mask & SD_BUS_CREDS_CGROUP) || r != -ENODATA || q != -ENODATA || v != -ENODATA || w != -ENODATA || z != -ENODATA)) fputs("\n", f); r = sd_bus_creds_get_audit_login_uid(c, &audit_loginuid); diff --git a/src/libelogind/sd-login/sd-login.c b/src/libelogind/sd-login/sd-login.c index 5cc6d69aa..8ebcbb0df 100644 --- a/src/libelogind/sd-login/sd-login.c +++ b/src/libelogind/sd-login/sd-login.c @@ -74,6 +74,14 @@ _public_ int sd_pid_get_slice(pid_t pid, char **slice) { return -ESRCH; } +_public_ int sd_pid_get_user_slice(pid_t pid, char **slice) { + + assert_return(pid >= 0, -EINVAL); + assert_return(slice, -EINVAL); + + return cg_pid_get_user_slice(pid, slice); +} + _public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) { assert_return(pid >= 0, -EINVAL); @@ -166,6 +174,20 @@ _public_ int sd_peer_get_slice(int fd, char **slice) { return -ESRCH; } +_public_ int sd_peer_get_user_slice(int fd, char **slice) { + struct ucred ucred; + int r; + + assert_return(fd >= 0, -EINVAL); + assert_return(slice, -EINVAL); + + r = getpeercred(fd, &ucred); + if (r < 0) + return r; + + return cg_pid_get_user_slice(ucred.pid, slice); +} + static int file_of_uid(uid_t uid, char **p) { assert(p); diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c index ce951174f..2654efa1c 100644 --- a/src/shared/cgroup-util.c +++ b/src/shared/cgroup-util.c @@ -1316,45 +1316,37 @@ static const char *skip_user_manager(const char *p) { return NULL; } -int cg_path_get_user_unit(const char *path, char **ret) { +static const char *skip_user_prefix(const char *path) { const char *e, *t; - char *unit; - int r; assert(path); - assert(ret); - - /* We always have to parse the path from the beginning as unit - * cgroups might have arbitrary child cgroups and we shouldn't get - * confused by those */ /* Skip slices, if there are any */ e = skip_slices(path); - /* Skip the user manager... */ + /* Skip the user manager, if it's in the path now... */ t = skip_user_manager(e); + if (t) + return t; - /* Alternatively skip the user session... */ - if (!t) - t = skip_session(e); - if (!t) - return -ENXIO; + /* Alternatively skip the user session if it is in the path... */ + return skip_session(e); +} - /* ... and skip more slices if there are any */ - e = skip_slices(t); +int cg_path_get_user_unit(const char *path, char **ret) { + const char *t; - r = cg_path_decode_unit(e, &unit); - if (r < 0) - return r; + assert(path); + assert(ret); - /* We skipped over the slices, don't accept any now */ - if (endswith(unit, ".slice")) { - free(unit); + t = skip_user_prefix(path); + if (!t) return -ENXIO; - } - *ret = unit; - return 0; + /* And from here on it looks pretty much the same as for a + * system unit, hence let's use the same parser from here + * on. */ + return cg_path_get_unit(t, ret); } int cg_pid_get_user_unit(pid_t pid, char **unit) { @@ -1486,6 +1478,9 @@ int cg_path_get_slice(const char *p, char **slice) { assert(p); assert(slice); + /* Finds the right-most slice unit from the beginning, but + * stops before we come to the first non-slice unit. */ + for (;;) { size_t n; @@ -1526,6 +1521,33 @@ int cg_pid_get_slice(pid_t pid, char **slice) { return cg_path_get_slice(cgroup, slice); } +int cg_path_get_user_slice(const char *p, char **slice) { + const char *t; + assert(p); + assert(slice); + + t = skip_user_prefix(p); + if (!t) + return -ENXIO; + + /* And now it looks pretty much the same as for a system + * slice, so let's just use the same parser from here on. */ + return cg_path_get_slice(t, slice); +} + +int cg_pid_get_user_slice(pid_t pid, char **slice) { + _cleanup_free_ char *cgroup = NULL; + int r; + + assert(slice); + + r = cg_pid_get_path_shifted(pid, NULL, &cgroup); + if (r < 0) + return r; + + return cg_path_get_user_slice(cgroup, slice); +} + char *cg_escape(const char *p) { bool need_prefix = false; diff --git a/src/shared/cgroup-util.h b/src/shared/cgroup-util.h index cc2aeeb97..20900d0c5 100644 --- a/src/shared/cgroup-util.h +++ b/src/shared/cgroup-util.h @@ -99,11 +99,13 @@ int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_ int cg_get_root_path(char **path); int cg_path_get_session(const char *path, char **session); +int cg_path_get_user_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); +int cg_pid_get_user_slice(pid_t pid, char **slice); char *cg_escape(const char *p); char *cg_unescape(const char *p) _pure_; diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h index 19f01a628..9dadae9e5 100644 --- a/src/systemd/sd-bus.h +++ b/src/systemd/sd-bus.h @@ -73,23 +73,24 @@ enum { SD_BUS_CREDS_CMDLINE = 1ULL << 15, SD_BUS_CREDS_CGROUP = 1ULL << 16, SD_BUS_CREDS_UNIT = 1ULL << 17, - SD_BUS_CREDS_USER_UNIT = 1ULL << 18, - SD_BUS_CREDS_SLICE = 1ULL << 19, - SD_BUS_CREDS_SESSION = 1ULL << 20, - SD_BUS_CREDS_OWNER_UID = 1ULL << 21, - SD_BUS_CREDS_EFFECTIVE_CAPS = 1ULL << 22, - SD_BUS_CREDS_PERMITTED_CAPS = 1ULL << 23, - SD_BUS_CREDS_INHERITABLE_CAPS = 1ULL << 24, - SD_BUS_CREDS_BOUNDING_CAPS = 1ULL << 25, - SD_BUS_CREDS_SELINUX_CONTEXT = 1ULL << 26, - SD_BUS_CREDS_AUDIT_SESSION_ID = 1ULL << 27, - SD_BUS_CREDS_AUDIT_LOGIN_UID = 1ULL << 28, - SD_BUS_CREDS_TTY = 1ULL << 29, - SD_BUS_CREDS_UNIQUE_NAME = 1ULL << 30, - SD_BUS_CREDS_WELL_KNOWN_NAMES = 1ULL << 31, - SD_BUS_CREDS_DESCRIPTION = 1ULL << 32, + SD_BUS_CREDS_SLICE = 1ULL << 18, + SD_BUS_CREDS_USER_UNIT = 1ULL << 19, + SD_BUS_CREDS_USER_SLICE = 1ULL << 20, + SD_BUS_CREDS_SESSION = 1ULL << 21, + SD_BUS_CREDS_OWNER_UID = 1ULL << 22, + SD_BUS_CREDS_EFFECTIVE_CAPS = 1ULL << 23, + SD_BUS_CREDS_PERMITTED_CAPS = 1ULL << 24, + SD_BUS_CREDS_INHERITABLE_CAPS = 1ULL << 25, + SD_BUS_CREDS_BOUNDING_CAPS = 1ULL << 26, + SD_BUS_CREDS_SELINUX_CONTEXT = 1ULL << 27, + SD_BUS_CREDS_AUDIT_SESSION_ID = 1ULL << 28, + SD_BUS_CREDS_AUDIT_LOGIN_UID = 1ULL << 29, + SD_BUS_CREDS_TTY = 1ULL << 30, + SD_BUS_CREDS_UNIQUE_NAME = 1ULL << 31, + SD_BUS_CREDS_WELL_KNOWN_NAMES = 1ULL << 32, + SD_BUS_CREDS_DESCRIPTION = 1ULL << 33, SD_BUS_CREDS_AUGMENT = 1ULL << 63, /* special flag, if on sd-bus will augment creds struct, in a potentially race-full way. */ - _SD_BUS_CREDS_ALL = (1ULL << 33) -1, + _SD_BUS_CREDS_ALL = (1ULL << 34) -1, }; enum { @@ -351,8 +352,9 @@ int sd_bus_creds_get_exe(sd_bus_creds *c, const char **exe); int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline); int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **cgroup); int sd_bus_creds_get_unit(sd_bus_creds *c, const char **unit); -int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **unit); int sd_bus_creds_get_slice(sd_bus_creds *c, const char **slice); +int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **unit); +int sd_bus_creds_get_user_slice(sd_bus_creds *c, const char **slice); int sd_bus_creds_get_session(sd_bus_creds *c, const char **session); int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid); int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability); diff --git a/src/systemd/sd-login.h b/src/systemd/sd-login.h index 24c859506..9260396d5 100644 --- a/src/systemd/sd-login.h +++ b/src/systemd/sd-login.h @@ -62,22 +62,25 @@ int sd_pid_get_session(pid_t pid, char **session); * return an error for system processes. */ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid); -/* Get systemd unit (i.e. service) name from PID, for system +/* Get systemd non-slice unit (i.e. service) name from PID, for system * services. This will return an error for non-service processes. */ int sd_pid_get_unit(pid_t pid, char **unit); -/* Get systemd unit (i.e. service) name from PID, for user +/* Get systemd non-slice unit (i.e. service) name from PID, for user * services. This will return an error for non-user-service * processes. */ int sd_pid_get_user_unit(pid_t pid, char **unit); +/* Get slice name from PID. */ +int sd_pid_get_slice(pid_t pid, char **slice); + +/* Get user slice name from PID. */ +int sd_pid_get_user_slice(pid_t pid, char **slice); + /* Get machine name from PID, for processes assigned to a VM or * container. This will return an error for non-machine processes. */ int sd_pid_get_machine_name(pid_t pid, char **machine); -/* Get slice name from PID. */ -int sd_pid_get_slice(pid_t pid, char **slice); - /* Similar to sd_pid_get_session(), but retrieves data about peer of * connected AF_UNIX socket */ int sd_peer_get_session(int fd, char **session); @@ -94,14 +97,18 @@ int sd_peer_get_unit(int fd, char **unit); * connected AF_UNIX socket */ int sd_peer_get_user_unit(int fd, char **unit); -/* Similar to sd_pid_get_machine_name(), but retrieves data about peer - * of connected AF_UNIX socket */ -int sd_peer_get_machine_name(int fd, char **machine); - /* Similar to sd_pid_get_slice(), but retrieves data about peer of * connected AF_UNIX socket */ int sd_peer_get_slice(int fd, char **slice); +/* Similar to sd_pid_get_user_slice(), but retrieves data about peer of + * connected AF_UNIX socket */ +int sd_peer_get_user_slice(int fd, char **slice); + +/* Similar to sd_pid_get_machine_name(), but retrieves data about peer + * of connected AF_UNIX socket */ +int sd_peer_get_machine_name(int fd, char **machine); + /* Get state from UID. Possible states: offline, lingering, online, active, closing */ int sd_uid_get_state(uid_t uid, char **state);