summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-09-04 09:54:14 +0200
committerSven Eden <yamakuzure@gmx.net>2017-03-14 10:19:06 +0100
commitc5bb60b5fcde6082ed7e591f94f5dee62a23e4e0 (patch)
tree92ac5249c24720df8bd9fe4c74b8de163266db66
parentabbb87ffdecf445d2bba18e1638f80c96098339e (diff)
sd-login: add new sd_pid_get_cgroup() API
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.
-rw-r--r--src/libelogind/sd-login/sd-login.c40
-rw-r--r--src/libelogind/sd-login/test-login.c6
-rw-r--r--src/libsystemd/libsystemd.sym6
-rw-r--r--src/systemd/sd-login.h8
4 files changed, 59 insertions, 1 deletions
diff --git a/src/libelogind/sd-login/sd-login.c b/src/libelogind/sd-login/sd-login.c
index 180bdd09a..55da26e9d 100644
--- a/src/libelogind/sd-login/sd-login.c
+++ b/src/libelogind/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/libelogind/sd-login/test-login.c b/src/libelogind/sd-login/test-login.c
index 70b034584..f734ce9ee 100644
--- a/src/libelogind/sd-login/test-login.c
+++ b/src/libelogind/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/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym
index 7bf1d66dd..d5ad127bc 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/systemd/sd-login.h b/src/systemd/sd-login.h
index 9260396d5..39b68c389 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);