diff --git a/Makefile-man.am b/Makefile-man.am
index 65287371b9..ab68c81b1d 100644
--- a/Makefile-man.am
+++ b/Makefile-man.am
@@ -1937,6 +1937,7 @@ MANPAGES_ALIAS += \
man/sd_login_monitor_get_fd.3 \
man/sd_login_monitor_get_timeout.3 \
man/sd_login_monitor_unref.3 \
+ man/sd_peer_get_cgroup.3 \
man/sd_peer_get_machine_name.3 \
man/sd_peer_get_owner_uid.3 \
man/sd_peer_get_session.3 \
@@ -1944,6 +1945,7 @@ MANPAGES_ALIAS += \
man/sd_peer_get_unit.3 \
man/sd_peer_get_user_slice.3 \
man/sd_peer_get_user_unit.3 \
+ man/sd_pid_get_cgroup.3 \
man/sd_pid_get_machine_name.3 \
man/sd_pid_get_owner_uid.3 \
man/sd_pid_get_slice.3 \
@@ -1981,6 +1983,7 @@ man/sd_login_monitor_get_events.3: man/sd_login_monitor_new.3
man/sd_login_monitor_get_fd.3: man/sd_login_monitor_new.3
man/sd_login_monitor_get_timeout.3: man/sd_login_monitor_new.3
man/sd_login_monitor_unref.3: man/sd_login_monitor_new.3
+man/sd_peer_get_cgroup.3: man/sd_pid_get_session.3
man/sd_peer_get_machine_name.3: man/sd_pid_get_session.3
man/sd_peer_get_owner_uid.3: man/sd_pid_get_session.3
man/sd_peer_get_session.3: man/sd_pid_get_session.3
@@ -1988,6 +1991,7 @@ man/sd_peer_get_slice.3: man/sd_pid_get_session.3
man/sd_peer_get_unit.3: man/sd_pid_get_session.3
man/sd_peer_get_user_slice.3: man/sd_pid_get_session.3
man/sd_peer_get_user_unit.3: man/sd_pid_get_session.3
+man/sd_pid_get_cgroup.3: man/sd_pid_get_session.3
man/sd_pid_get_machine_name.3: man/sd_pid_get_session.3
man/sd_pid_get_owner_uid.3: man/sd_pid_get_session.3
man/sd_pid_get_slice.3: man/sd_pid_get_session.3
@@ -2043,6 +2047,9 @@ man/sd_login_monitor_get_timeout.html: man/sd_login_monitor_new.html
man/sd_login_monitor_unref.html: man/sd_login_monitor_new.html
$(html-alias)
+man/sd_peer_get_cgroup.html: man/sd_pid_get_session.html
+ $(html-alias)
+
man/sd_peer_get_machine_name.html: man/sd_pid_get_session.html
$(html-alias)
@@ -2064,6 +2071,9 @@ man/sd_peer_get_user_slice.html: man/sd_pid_get_session.html
man/sd_peer_get_user_unit.html: man/sd_pid_get_session.html
$(html-alias)
+man/sd_pid_get_cgroup.html: man/sd_pid_get_session.html
+ $(html-alias)
+
man/sd_pid_get_machine_name.html: man/sd_pid_get_session.html
$(html-alias)
diff --git a/man/sd_pid_get_session.xml b/man/sd_pid_get_session.xml
index 903c143f36..035effcaa9 100644
--- a/man/sd_pid_get_session.xml
+++ b/man/sd_pid_get_session.xml
@@ -50,6 +50,7 @@
sd_pid_get_machine_name
sd_pid_get_slice
sd_pid_get_user_slice
+ sd_pid_get_cgroup
sd_peer_get_session
sd_peer_get_unit
sd_peer_get_user_unit
@@ -57,6 +58,7 @@
sd_peer_get_machine_name
sd_peer_get_slice
sd_peer_get_user_slice
+ sd_peer_get_cgroup
Determine session, unit, owner of a session,
container/VM or slice of a specific PID or socket
peer
@@ -108,6 +110,12 @@
char **slice
+
+ int sd_pid_get_cgroup
+ pid_t pid
+ char **cgroup
+
+
int sd_peer_get_session
int fd
@@ -149,6 +157,12 @@
int fd
char **slice
+
+
+ int sd_peer_get_cgroup
+ int fd
+ char **cgroup
+
@@ -217,6 +231,17 @@
returns the user slice (as managed by the user's systemd instance)
of a process.
+ sd_pid_get_cgroup() returns the control
+ group path of the specified process, relative to the root of the
+ hierarchy. Returns the path without trailing slash, except for
+ processes located in the root control group, where "/" is
+ returned. To find the actual control group path in the file system
+ the returned path needs to be prefixed with
+ /sys/fs/cgroup/ (if the unified control group
+ setup is used), or
+ /sys/fs/cgroup/HIERARCHY/
+ (if the legacy multi-hierarchy control group setup is used).
+
If the pid parameter of any of these
functions is passed as 0, the operation is executed for the
calling process.
@@ -226,13 +251,14 @@
sd_peer_get_user_unit(),
sd_peer_get_owner_uid(),
sd_peer_get_machine_name(),
- sd_peer_get_slice() and
- sd_peer_get_user_slice() calls operate
- similar to their PID counterparts, but operate on a connected
- AF_UNIX socket and retrieve information about the connected peer
- process. Note that these fields are retrieved via
- /proc, and hence are not suitable for
- authorization purposes, as they are subject to races.
+ sd_peer_get_slice(),
+ sd_peer_get_user_slice() and
+ sd_peer_get_cgroup() calls operate similar to
+ their PID counterparts, but operate on a connected AF_UNIX socket
+ and retrieve information about the connected peer process. Note
+ that these fields are retrieved via /proc,
+ and hence are not suitable for authorization purposes, as they are
+ subject to races.
diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym
index 7bf1d66dde..d5ad127bcb 100644
--- a/src/libsystemd/libsystemd.sym
+++ b/src/libsystemd/libsystemd.sym
@@ -467,3 +467,9 @@ global:
sd_bus_emit_object_removed;
sd_bus_flush_close_unref;
} LIBSYSTEMD_221;
+
+LIBSYSTEMD_226 {
+global:
+ sd_pid_get_cgroup;
+ sd_peer_get_cgroup;
+} LIBSYSTEMD_222;
diff --git a/src/libsystemd/sd-login/sd-login.c b/src/libsystemd/sd-login/sd-login.c
index 180bdd09ad..55da26e9d9 100644
--- a/src/libsystemd/sd-login/sd-login.c
+++ b/src/libsystemd/sd-login/sd-login.c
@@ -101,6 +101,32 @@ _public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) {
return cg_pid_get_owner_uid(pid, uid);
}
+_public_ int sd_pid_get_cgroup(pid_t pid, char **cgroup) {
+ char *c;
+ int r;
+
+ assert_return(pid >= 0, -EINVAL);
+ assert_return(cgroup, -EINVAL);
+
+ r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &c);
+ if (r < 0)
+ return r;
+
+ /* The internal APIs return the empty string for the root
+ * cgroup, let's return the "/" in the public APIs instead, as
+ * that's easier and less ambigious for people to grok. */
+ if (isempty(c)) {
+ free(c);
+ c = strdup("/");
+ if (!c)
+ return -ENOMEM;
+
+ }
+
+ *cgroup = c;
+ return 0;
+}
+
_public_ int sd_peer_get_session(int fd, char **session) {
struct ucred ucred = {};
int r;
@@ -199,6 +225,20 @@ _public_ int sd_peer_get_user_slice(int fd, char **slice) {
return cg_pid_get_user_slice(ucred.pid, slice);
}
+_public_ int sd_peer_get_cgroup(int fd, char **cgroup) {
+ struct ucred ucred;
+ int r;
+
+ assert_return(fd >= 0, -EBADF);
+ assert_return(cgroup, -EINVAL);
+
+ r = getpeercred(fd, &ucred);
+ if (r < 0)
+ return r;
+
+ return sd_pid_get_cgroup(ucred.pid, cgroup);
+}
+
static int file_of_uid(uid_t uid, char **p) {
assert_return(uid_is_valid(uid), -EINVAL);
diff --git a/src/libsystemd/sd-login/test-login.c b/src/libsystemd/sd-login/test-login.c
index 70b0345848..f734ce9eee 100644
--- a/src/libsystemd/sd-login/test-login.c
+++ b/src/libsystemd/sd-login/test-login.c
@@ -33,7 +33,7 @@ static void test_login(void) {
_cleanup_free_ char *pp = NULL, *qq = NULL;
int r, k;
uid_t u, u2;
- char *seat, *type, *class, *display, *remote_user, *remote_host, *display_session;
+ char *seat, *type, *class, *display, *remote_user, *remote_host, *display_session, *cgroup;
char *session;
char *state;
char *session2;
@@ -50,6 +50,10 @@ static void test_login(void) {
assert_se(sd_pid_get_owner_uid(0, &u2) == 0);
printf("user = "UID_FMT"\n", u2);
+ assert_se(sd_pid_get_cgroup(0, &cgroup) == 0);
+ printf("cgroup = %s\n", cgroup);
+ free(cgroup);
+
display_session = NULL;
r = sd_uid_get_display(u2, &display_session);
assert_se(r >= 0 || r == -ENODATA);
diff --git a/src/systemd/sd-login.h b/src/systemd/sd-login.h
index 9260396d5d..39b68c3895 100644
--- a/src/systemd/sd-login.h
+++ b/src/systemd/sd-login.h
@@ -81,6 +81,10 @@ int sd_pid_get_user_slice(pid_t pid, char **slice);
* container. This will return an error for non-machine processes. */
int sd_pid_get_machine_name(pid_t pid, char **machine);
+/* Get the control group from a PID, relative to the root of the
+ * hierarchy. */
+int sd_pid_get_cgroup(pid_t pid, char **cgroup);
+
/* 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);
@@ -109,6 +113,10 @@ int sd_peer_get_user_slice(int fd, char **slice);
* of connected AF_UNIX socket */
int sd_peer_get_machine_name(int fd, char **machine);
+/* Similar to sd_pid_get_cgroup(), but retrieves data about the peer
+ * of a connected AF_UNIX socket. */
+int sd_peer_get_cgroup(pid_t pid, char **cgroup);
+
/* Get state from UID. Possible states: offline, lingering, online, active, closing */
int sd_uid_get_state(uid_t uid, char **state);