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 \
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 \
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
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
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)
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)
<refname>sd_pid_get_machine_name</refname>
<refname>sd_pid_get_slice</refname>
<refname>sd_pid_get_user_slice</refname>
+ <refname>sd_pid_get_cgroup</refname>
<refname>sd_peer_get_session</refname>
<refname>sd_peer_get_unit</refname>
<refname>sd_peer_get_user_unit</refname>
<refname>sd_peer_get_machine_name</refname>
<refname>sd_peer_get_slice</refname>
<refname>sd_peer_get_user_slice</refname>
+ <refname>sd_peer_get_cgroup</refname>
<refpurpose>Determine session, unit, owner of a session,
container/VM or slice of a specific PID or socket
peer</refpurpose>
<paramdef>char **<parameter>slice</parameter></paramdef>
</funcprototype>
+ <funcprototype>
+ <funcdef>int <function>sd_pid_get_cgroup</function></funcdef>
+ <paramdef>pid_t <parameter>pid</parameter></paramdef>
+ <paramdef>char **<parameter>cgroup</parameter></paramdef>
+ </funcprototype>
+
<funcprototype>
<funcdef>int <function>sd_peer_get_session</function></funcdef>
<paramdef>int <parameter>fd</parameter></paramdef>
<paramdef>int <parameter>fd</parameter></paramdef>
<paramdef>char **<parameter>slice</parameter></paramdef>
</funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_peer_get_cgroup</function></funcdef>
+ <paramdef>int <parameter>fd</parameter></paramdef>
+ <paramdef>char **<parameter>cgroup</parameter></paramdef>
+ </funcprototype>
</funcsynopsis>
</refsynopsisdiv>
returns the user slice (as managed by the user's systemd instance)
of a process.</para>
+ <para><function>sd_pid_get_cgroup()</function> 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
+ <filename>/sys/fs/cgroup/</filename> (if the unified control group
+ setup is used), or
+ <filename>/sys/fs/cgroup/<replaceable>HIERARCHY</replaceable>/</filename>
+ (if the legacy multi-hierarchy control group setup is used).</para>
+
<para>If the <varname>pid</varname> parameter of any of these
functions is passed as 0, the operation is executed for the
calling process.</para>
<function>sd_peer_get_user_unit()</function>,
<function>sd_peer_get_owner_uid()</function>,
<function>sd_peer_get_machine_name()</function>,
- <function>sd_peer_get_slice()</function> and
- <function>sd_peer_get_user_slice()</function> 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
- <filename>/proc</filename>, and hence are not suitable for
- authorization purposes, as they are subject to races.</para>
+ <function>sd_peer_get_slice()</function>,
+ <function>sd_peer_get_user_slice()</function> and
+ <function>sd_peer_get_cgroup()</function> 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 <filename>/proc</filename>,
+ and hence are not suitable for authorization purposes, as they are
+ subject to races.</para>
</refsect1>
<refsect1>
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;
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;
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);
_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;
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);
* 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);
* 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);