]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-login: add new sd_pid_get_cgroup() API
authorLennart Poettering <lennart@poettering.net>
Fri, 4 Sep 2015 07:54:14 +0000 (09:54 +0200)
committerLennart Poettering <lennart@poettering.net>
Sat, 5 Sep 2015 12:56:23 +0000 (14:56 +0200)
This adds a new sd_pid_get_cgroup() call to sd-login which may be used
to query the control path of a process. This is useful for programs when
making use of delegation units, in order to figure out which subtree has
been delegated.

In light of the unified control group hierarchy this is finally safe to
do, hence let's add a proper API for it, to make it easier to use this.

Makefile-man.am
man/sd_pid_get_session.xml
src/libsystemd/libsystemd.sym
src/libsystemd/sd-login/sd-login.c
src/libsystemd/sd-login/test-login.c
src/systemd/sd-login.h

index 65287371b921edfdd7596ccd95732247f15f11f0..ab68c81b1d315f7994497b349d5c619c5058c170 100644 (file)
@@ -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)
 
index 903c143f364543dc2e431e92525551ad0417a516..035effcaa90f1ded4c26aa6c3f5c66d3ac2c428e 100644 (file)
@@ -50,6 +50,7 @@
     <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>
@@ -57,6 +58,7 @@
     <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>
index 7bf1d66dde1696df669e9c78b49d7789ec877d5d..d5ad127bcbfde070c026fd2beb9a29eeb2373669 100644 (file)
@@ -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;
index 180bdd09ad2ff4e8132e5b3944e2ac57e82c6efb..55da26e9d90bf6d36b111ae1999a6bc28393b0b9 100644 (file)
@@ -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);
index 70b03458489840f357e2d28f57a72d9ee778e530..f734ce9eee5d9524e72daf6effd4e75a37fd5c01 100644 (file)
@@ -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);
index 9260396d5d5431df5ceda11bf8f2138952f86935..39b68c3895856226f2e8248bb6186429bb2619e8 100644 (file)
@@ -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);