chiark / gitweb /
sd-bus: properly handle creds that are known but undefined for a process
authorLennart Poettering <lennart@poettering.net>
Wed, 29 Apr 2015 19:40:54 +0000 (21:40 +0200)
committerSven Eden <yamakuzure@gmx.net>
Tue, 14 Mar 2017 07:19:28 +0000 (08:19 +0100)
A number of fields do not apply to all processes, including: there a
processes without a controlling tty, without parent process, without
service, user services or session. To distuingish these cases from the
case where we simply don't have the data, always return ENXIO for them,
while returning ENODATA for the case where we really lack the
information.

Also update the credentials dumping code to show this properly. Fields
that are known but do not apply are now shown as "n/a".

Note that this also changes some of the calls in process-util.c and
cgroup-util.c to return ENXIO for these cases.

src/libelogind/sd-bus/bus-control.c
src/libelogind/sd-bus/bus-creds.c
src/libelogind/sd-bus/bus-dump.c
src/libelogind/sd-bus/bus-kernel.c
src/shared/audit.c
src/shared/audit.h
src/shared/cgroup-util.c
src/shared/terminal-util.c
src/test/test-process-util.c

index ca31807f7072eac4ee1cf25d1bec2dc72d8bdfcf..fa4c28174d47288cc61314c4e68cc10aec6b4488 100644 (file)
@@ -423,9 +423,24 @@ static int bus_populate_creds_from_items(
                                 c->mask |= SD_BUS_CREDS_TID;
                         }
 
-                        if (mask & SD_BUS_CREDS_PPID && item->pids.ppid > 0) {
-                                c->ppid = (pid_t) item->pids.ppid;
-                                c->mask |= SD_BUS_CREDS_PPID;
+                        if (mask & SD_BUS_CREDS_PPID) {
+                                if (item->pids.ppid > 0) {
+                                        c->ppid = (pid_t) item->pids.ppid;
+                                        c->mask |= SD_BUS_CREDS_PPID;
+                                } else if (item->pids.pid == 1) {
+                                        /* The structure doesn't
+                                         * really distuingish the case
+                                         * where a process has no
+                                         * parent and where we don't
+                                         * know it because it could
+                                         * not be translated due to
+                                         * namespaces. However, we
+                                         * know that PID 1 has no
+                                         * parent process, hence let's
+                                         * patch that in, manually. */
+                                        c->ppid = 0;
+                                        c->mask |= SD_BUS_CREDS_PPID;
+                                }
                         }
 
                         break;
@@ -565,12 +580,12 @@ static int bus_populate_creds_from_items(
                         break;
 
                 case KDBUS_ITEM_AUDIT:
-                        if (mask & SD_BUS_CREDS_AUDIT_SESSION_ID && (uint32_t) item->audit.sessionid != (uint32_t) -1) {
+                        if (mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
                                 c->audit_session_id = (uint32_t) item->audit.sessionid;
                                 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
                         }
 
-                        if (mask & SD_BUS_CREDS_AUDIT_LOGIN_UID && (uid_t) item->audit.loginuid != UID_INVALID) {
+                        if (mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
                                 c->audit_login_uid = (uid_t) item->audit.loginuid;
                                 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
                         }
index 1ac12a7bf7fce346374c32b82365f76c1b8e70cc..44fad0be094e07856d11f6b0b5bbacd90b9251b3 100644 (file)
@@ -302,6 +302,12 @@ _public_ int sd_bus_creds_get_ppid(sd_bus_creds *c, pid_t *ppid) {
         if (!(c->mask & SD_BUS_CREDS_PPID))
                 return -ENODATA;
 
+        /* PID 1 has no parent process. Let's distuingish the case of
+         * not knowing and not having a parent process by the returned
+         * error code. */
+        if (c->ppid == 0)
+                return -ENXIO;
+
         *ppid = c->ppid;
         return 0;
 }
@@ -360,7 +366,9 @@ _public_ int sd_bus_creds_get_exe(sd_bus_creds *c, const char **ret) {
         if (!(c->mask & SD_BUS_CREDS_EXE))
                 return -ENODATA;
 
-        assert(c->exe);
+        if (!c->exe)
+                return -ENXIO;
+
         *ret = c->exe;
         return 0;
 }
@@ -477,8 +485,8 @@ _public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) {
         if (!(c->mask & SD_BUS_CREDS_CMDLINE))
                 return -ENODATA;
 
-        assert_return(c->cmdline, -ESRCH);
-        assert(c->cmdline);
+        if (!c->cmdline)
+                return -ENXIO;
 
         if (!c->cmdline_array) {
                 c->cmdline_array = strv_parse_nulstr(c->cmdline, c->cmdline_size);
@@ -497,6 +505,9 @@ _public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessio
         if (!(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID))
                 return -ENODATA;
 
+        if (c->audit_session_id == AUDIT_SESSION_INVALID)
+                return -ENXIO;
+
         *sessionid = c->audit_session_id;
         return 0;
 }
@@ -508,6 +519,9 @@ _public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) {
         if (!(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID))
                 return -ENODATA;
 
+        if (c->audit_login_uid == UID_INVALID)
+                return -ENXIO;
+
         *uid = c->audit_login_uid;
         return 0;
 }
@@ -519,6 +533,9 @@ _public_ int sd_bus_creds_get_tty(sd_bus_creds *c, const char **ret) {
         if (!(c->mask & SD_BUS_CREDS_TTY))
                 return -ENODATA;
 
+        if (!c->tty)
+                return -ENXIO;
+
         *ret = c->tty;
         return 0;
 }
@@ -754,8 +771,10 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
                                                         if (r < 0)
                                                                 return r;
 
-                                                        c->mask |= SD_BUS_CREDS_PPID;
-                                                }
+                                                } else
+                                                        c->ppid = 0;
+
+                                                c->mask |= SD_BUS_CREDS_PPID;
                                                 continue;
                                         }
                                 }
@@ -908,7 +927,17 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
 
         if (missing & SD_BUS_CREDS_EXE) {
                 r = get_process_exe(pid, &c->exe);
-                if (r < 0) {
+                if (r == -ESRCH) {
+                        /* Unfortunately we cannot really distuingish
+                         * the case here where the process does not
+                         * exist, and /proc/$PID/exe being unreadable
+                         * because $PID is a kernel thread. Hence,
+                         * assume it is a kernel thread, and rely on
+                         * that this case is caught with a later
+                         * call. */
+                        c->exe = NULL;
+                        c->mask |= SD_BUS_CREDS_EXE;
+                } else if (r < 0) {
                         if (r != -EPERM && r != -EACCES)
                                 return r;
                 } else
@@ -920,17 +949,18 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
 
                 p = procfs_file_alloca(pid, "cmdline");
                 r = read_full_file(p, &c->cmdline, &c->cmdline_size);
+                if (r == -ENOENT)
+                        return -ESRCH;
                 if (r < 0) {
-                        if (r == -ENOENT)
-                                return -ESRCH;
                         if (r != -EPERM && r != -EACCES)
                                 return r;
                 } else {
                         if (c->cmdline_size == 0) {
                                 free(c->cmdline);
                                 c->cmdline = NULL;
-                        } else
-                                c->mask |= SD_BUS_CREDS_CMDLINE;
+                        }
+
+                        c->mask |= SD_BUS_CREDS_CMDLINE;
                 }
         }
 
@@ -941,9 +971,9 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
                         return -ENOMEM;
 
                 r = read_one_line_file(p, &c->tid_comm);
+                if (r == -ENOENT)
+                        return -ESRCH;
                 if (r < 0) {
-                        if (r == -ENOENT)
-                                return -ESRCH;
                         if (r != -EPERM && r != -EACCES)
                                 return r;
                 } else
@@ -972,8 +1002,12 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
 
         if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
                 r = audit_session_from_pid(pid, &c->audit_session_id);
-                if (r < 0) {
-                        if (r != -EOPNOTSUPP && r != -ENXIO && r != -ENOENT && r != -EPERM && r != -EACCES)
+                if (r == -ENXIO) {
+                        /* ENXIO means: no audit session id assigned */
+                        c->audit_session_id = AUDIT_SESSION_INVALID;
+                        c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
+                } else if (r < 0) {
+                        if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
                                 return r;
                 } else
                         c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
@@ -981,8 +1015,12 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
 
         if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
                 r = audit_loginuid_from_pid(pid, &c->audit_login_uid);
-                if (r < 0) {
-                        if (r != -EOPNOTSUPP && r != -ENXIO && r != -ENOENT && r != -EPERM && r != -EACCES)
+                if (r == -ENXIO) {
+                        /* ENXIO means: no audit login uid assigned */
+                        c->audit_login_uid = UID_INVALID;
+                        c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
+                } else if (r < 0) {
+                        if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
                                 return r;
                 } else
                         c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
@@ -990,13 +1028,28 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
 
         if (missing & SD_BUS_CREDS_TTY) {
                 r = get_ctty(pid, NULL, &c->tty);
-                if (r < 0) {
+                if (r == -ENXIO) {
+                        /* ENXIO means: process has no controlling TTY */
+                        c->tty = NULL;
+                        c->mask |= SD_BUS_CREDS_TTY;
+                } else if (r < 0) {
                         if (r != -EPERM && r != -EACCES && r != -ENOENT)
                                 return r;
                 } else
                         c->mask |= SD_BUS_CREDS_TTY;
         }
 
+        /* In case only the exe path was to be read we cannot
+         * distuingish the case where the exe path was unreadable
+         * because the process was a kernel thread, or when the
+         * process didn't exist at all. Hence, let's do a final check,
+         * to be sure. */
+        if (!pid_is_alive(pid))
+                return -ESRCH;
+
+        if (tid > 0 && tid != pid && !pid_is_unwaited(tid))
+                return -ESRCH;
+
         c->augmented = missing & c->mask;
 
         return 0;
@@ -1079,14 +1132,22 @@ int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret)
         }
 
         if (c->mask & mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
-                n->supplementary_gids = newdup(gid_t, c->supplementary_gids, c->n_supplementary_gids);
-                if (!n->supplementary_gids)
-                        return -ENOMEM;
-                n->n_supplementary_gids = c->n_supplementary_gids;
+                if (c->supplementary_gids) {
+                        n->supplementary_gids = newdup(gid_t, c->supplementary_gids, c->n_supplementary_gids);
+                        if (!n->supplementary_gids)
+                                return -ENOMEM;
+                        n->n_supplementary_gids = c->n_supplementary_gids;
+                } else {
+                        n->supplementary_gids = NULL;
+                        n->n_supplementary_gids = 0;
+                }
+
                 n->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
         }
 
         if (c->mask & mask & SD_BUS_CREDS_COMM) {
+                assert(c->comm);
+
                 n->comm = strdup(c->comm);
                 if (!n->comm)
                         return -ENOMEM;
@@ -1095,6 +1156,8 @@ int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret)
         }
 
         if (c->mask & mask & SD_BUS_CREDS_TID_COMM) {
+                assert(c->tid_comm);
+
                 n->tid_comm = strdup(c->tid_comm);
                 if (!n->tid_comm)
                         return -ENOMEM;
@@ -1103,23 +1166,34 @@ int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret)
         }
 
         if (c->mask & mask & SD_BUS_CREDS_EXE) {
-                n->exe = strdup(c->exe);
-                if (!n->exe)
-                        return -ENOMEM;
+                if (c->exe) {
+                        n->exe = strdup(c->exe);
+                        if (!n->exe)
+                                return -ENOMEM;
+                } else
+                        n->exe = NULL;
 
                 n->mask |= SD_BUS_CREDS_EXE;
         }
 
         if (c->mask & mask & SD_BUS_CREDS_CMDLINE) {
-                n->cmdline = memdup(c->cmdline, c->cmdline_size);
-                if (!n->cmdline)
-                        return -ENOMEM;
+                if (c->cmdline) {
+                        n->cmdline = memdup(c->cmdline, c->cmdline_size);
+                        if (!n->cmdline)
+                                return -ENOMEM;
+
+                        n->cmdline_size = c->cmdline_size;
+                } else {
+                        n->cmdline = NULL;
+                        n->cmdline_size = 0;
+                }
 
-                n->cmdline_size = c->cmdline_size;
                 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)) {
+                assert(c->cgroup);
+
                 n->cgroup = strdup(c->cgroup);
                 if (!n->cgroup)
                         return -ENOMEM;
@@ -1132,6 +1206,8 @@ int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret)
         }
 
         if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) {
+                assert(c->capability);
+
                 n->capability = memdup(c->capability, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
                 if (!n->capability)
                         return -ENOMEM;
@@ -1140,6 +1216,8 @@ int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret)
         }
 
         if (c->mask & mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
+                assert(c->label);
+
                 n->label = strdup(c->label);
                 if (!n->label)
                         return -ENOMEM;
@@ -1166,6 +1244,8 @@ int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret)
         }
 
         if (c->mask & mask & SD_BUS_CREDS_UNIQUE_NAME) {
+                assert(c->unique_name);
+
                 n->unique_name = strdup(c->unique_name);
                 if (!n->unique_name)
                         return -ENOMEM;
@@ -1173,15 +1253,20 @@ int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret)
         }
 
         if (c->mask & mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
-                n->well_known_names = strv_copy(c->well_known_names);
-                if (!n->well_known_names)
-                        return -ENOMEM;
+                if (strv_isempty(c->well_known_names))
+                        n->well_known_names = NULL;
+                else {
+                        n->well_known_names = strv_copy(c->well_known_names);
+                        if (!n->well_known_names)
+                                return -ENOMEM;
+                }
                 n->well_known_names_driver = c->well_known_names_driver;
                 n->well_known_names_local = c->well_known_names_local;
                 n->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
         }
 
         if (c->mask & mask & SD_BUS_CREDS_DESCRIPTION) {
+                assert(c->description);
                 n->description = strdup(c->description);
                 if (!n->description)
                         return -ENOMEM;
index 396bf36f8a6afb465406a5f541c651516ee412d5..47a5c6b3a85d62fef6f4304dcc5e805bba2df435 100644 (file)
@@ -331,13 +331,11 @@ static void dump_capabilities(
 }
 
 int bus_creds_dump(sd_bus_creds *c, FILE *f, bool terse) {
-        bool audit_sessionid_is_set = false, audit_loginuid_is_set = false;
-        const char *u = NULL, *uu = NULL, *s = NULL, *sl = NULL;
         uid_t owner, audit_loginuid;
         uint32_t audit_sessionid;
         char **cmdline = NULL, **well_known = NULL;
-        const char *prefix, *color, *suffix;
-        int r;
+        const char *prefix, *color, *suffix, *s;
+        int r, q, v, w;
 
         assert(c);
 
@@ -362,8 +360,12 @@ int bus_creds_dump(sd_bus_creds *c, FILE *f, bool terse) {
                 fprintf(f, "%sPID=%s"PID_FMT"%s", prefix, color, c->pid, suffix);
         if (c->mask & SD_BUS_CREDS_TID)
                 fprintf(f, "%sTID=%s"PID_FMT"%s", prefix, color, c->tid, suffix);
-        if (c->mask & SD_BUS_CREDS_PPID)
-                fprintf(f, "%sPPID=%s"PID_FMT"%s", prefix, color, c->ppid, suffix);
+        if (c->mask & SD_BUS_CREDS_PPID) {
+                if (c->ppid == 0)
+                        fprintf(f, "%sPPID=%sn/a%s", prefix, color, suffix);
+                else
+                        fprintf(f, "%sPPID=%s"PID_FMT"%s", prefix, color, c->ppid, suffix);
+        }
         if (c->mask & SD_BUS_CREDS_TTY)
                 fprintf(f, "%sTTY=%s%s%s", prefix, color, strna(c->tty), suffix);
 
@@ -409,12 +411,13 @@ int bus_creds_dump(sd_bus_creds *c, FILE *f, bool terse) {
         if (c->mask & SD_BUS_CREDS_TID_COMM)
                 fprintf(f, "%sTIDComm=%s%s%s", prefix, color, c->tid_comm, suffix);
         if (c->mask & SD_BUS_CREDS_EXE)
-                fprintf(f, "%sExe=%s%s%s", prefix, color, c->exe, suffix);
+                fprintf(f, "%sExe=%s%s%s", prefix, color, strna(c->exe), suffix);
 
         if (terse && (c->mask & (SD_BUS_CREDS_EXE|SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM)))
                 fputs("\n", f);
 
-        if (sd_bus_creds_get_cmdline(c, &cmdline) >= 0) {
+        r = sd_bus_creds_get_cmdline(c, &cmdline);
+        if (r >= 0) {
                 char **i;
 
                 fprintf(f, "%sCommandLine=%s", prefix, color);
@@ -426,7 +429,8 @@ int bus_creds_dump(sd_bus_creds *c, FILE *f, bool terse) {
                 }
 
                 fprintf(f, "%s", suffix);
-        }
+        } else if (r != -ENODATA)
+                fprintf(f, "%sCommandLine=%sn/a%s", prefix, color, suffix);
 
         if (c->mask & SD_BUS_CREDS_SELINUX_CONTEXT)
                 fprintf(f, "%sLabel=%s%s%s", prefix, color, c->label, suffix);
@@ -438,32 +442,38 @@ int bus_creds_dump(sd_bus_creds *c, FILE *f, bool terse) {
 
         if (c->mask & SD_BUS_CREDS_CGROUP)
                 fprintf(f, "%sCGroup=%s%s%s", prefix, color, c->cgroup, suffix);
-        (void) sd_bus_creds_get_unit(c, &u);
-        if (u)
-                fprintf(f, "%sUnit=%s%s%s", prefix, color, u, suffix);
-        (void) sd_bus_creds_get_user_unit(c, &uu);
-        if (uu)
-                fprintf(f, "%sUserUnit=%s%s%s", prefix, color, uu, suffix);
-        (void) sd_bus_creds_get_slice(c, &sl);
-        if (sl)
-                fprintf(f, "%sSlice=%s%s%s", prefix, color, sl, suffix);
-        (void) sd_bus_creds_get_session(c, &s);
-        if (s)
-                fprintf(f, "%sSession=%s%s%s", prefix, color, s, suffix);
-
-        if (terse && ((c->mask & SD_BUS_CREDS_CGROUP) || u || uu || sl || s))
+        s = NULL;
+        r = sd_bus_creds_get_unit(c, &s);
+        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);
+        if (w != -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))
                 fputs("\n", f);
 
-        if (sd_bus_creds_get_audit_login_uid(c, &audit_loginuid) >= 0) {
-                audit_loginuid_is_set = true;
+        r = sd_bus_creds_get_audit_login_uid(c, &audit_loginuid);
+        if (r >= 0)
                 fprintf(f, "%sAuditLoginUID=%s"UID_FMT"%s", prefix, color, audit_loginuid, suffix);
-        }
-        if (sd_bus_creds_get_audit_session_id(c, &audit_sessionid) >= 0) {
-                audit_sessionid_is_set = true;
+        else if (r != -ENODATA)
+                fprintf(f, "%sAuditLoginUID=%sn/a%s", prefix, color, suffix);
+        q = sd_bus_creds_get_audit_session_id(c, &audit_sessionid);
+        if (q >= 0)
                 fprintf(f, "%sAuditSessionID=%s%"PRIu32"%s", prefix, color, audit_sessionid, suffix);
-        }
+        else if (q != -ENODATA)
+                fprintf(f, "%sAuditSessionID=%sn/a%s", prefix, color, suffix);
 
-        if (terse && (audit_loginuid_is_set || audit_sessionid_is_set))
+        if (terse && (r != -ENODATA || q != -ENODATA))
                 fputs("\n", f);
 
         if (c->mask & SD_BUS_CREDS_UNIQUE_NAME)
index a8c04b98a99ee992a686af72b8ce8709553b367c..556b5eb704268adcadb01deeba67ffd60d385c59 100644 (file)
@@ -598,6 +598,9 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
                         if (d->pids.ppid > 0) {
                                 m->creds.ppid = (pid_t) d->pids.ppid;
                                 m->creds.mask |= SD_BUS_CREDS_PPID & bus->creds_mask;
+                        } else if (d->pids.pid == 1) {
+                                m->creds.ppid = 0;
+                                m->creds.mask |= SD_BUS_CREDS_PPID & bus->creds_mask;
                         }
 
                         break;
@@ -686,15 +689,11 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
                         break;
 
                 case KDBUS_ITEM_AUDIT:
-                        if ((uint32_t) d->audit.sessionid != (uint32_t) -1) {
-                                m->creds.audit_session_id = (uint32_t) d->audit.sessionid;
-                                m->creds.mask |= SD_BUS_CREDS_AUDIT_SESSION_ID & bus->creds_mask;
-                        }
+                        m->creds.audit_session_id = (uint32_t) d->audit.sessionid;
+                        m->creds.mask |= SD_BUS_CREDS_AUDIT_SESSION_ID & bus->creds_mask;
 
-                        if ((uid_t) d->audit.loginuid != UID_INVALID) {
-                                m->creds.audit_login_uid = (uid_t) d->audit.loginuid;
-                                m->creds.mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID & bus->creds_mask;
-                        }
+                        m->creds.audit_login_uid = (uid_t) d->audit.loginuid;
+                        m->creds.mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID & bus->creds_mask;
                         break;
 
                 case KDBUS_ITEM_CAPS:
index 84181d3321fe0e8e92281671b086690defe35d62..54148fcf1836a40c0062a649f6ea676d77a9a2b8 100644 (file)
@@ -46,7 +46,7 @@ int audit_session_from_pid(pid_t pid, uint32_t *id) {
         if (r < 0)
                 return r;
 
-        if (u == (uint32_t) -1 || u <= 0)
+        if (u == AUDIT_SESSION_INVALID || u <= 0)
                 return -ENXIO;
 
         *id = u;
index fb5f1b513ebcfb88e9246710ba5318e0c2398a97..6de331c73e5f8b4d341a4680be9c8a35c3c31a42 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "sd-bus.h"
-#include "job.h"
+#include <stdint.h>
+#include <stdbool.h>
+#include <sys/types.h>
 
-extern const sd_bus_vtable bus_job_vtable[];
+#define AUDIT_SESSION_INVALID ((uint32_t) -1)
 
-int bus_job_method_cancel(sd_bus_message *message, void *job, sd_bus_error *error);
+int audit_session_from_pid(pid_t pid, uint32_t *id);
+int audit_loginuid_from_pid(pid_t pid, uid_t *uid);
 
-void bus_job_send_change_signal(Job *j);
-void bus_job_send_removed_signal(Job *j);
+bool use_audit(void);
index c746d606d9ff648c29cbcd530d579b5e87acd547..5c031a0528905fbf990099f10dab7663d0978591 100644 (file)
@@ -35,6 +35,7 @@
 #include "util.h"
 #include "formats-util.h"
 #include "path-util.h"
+#include "unit-name.h"
 #include "fileio.h"
 #include "special.h"
 #include "mkdir.h"
@@ -439,7 +440,7 @@ static const char *normalize_controller(const char *controller) {
         assert(controller);
 
         if (streq(controller, SYSTEMD_CGROUP_CONTROLLER))
-                return "elogind";
+                return "systemd";
         else if (startswith(controller, "name="))
                 return controller + 5;
         else
@@ -1060,9 +1061,21 @@ int cg_mangle_path(const char *path, char **result) {
 }
 
 int cg_get_root_path(char **path) {
+        char *p, *e;
+        int r;
+
         assert(path);
 
-        return cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, path);
+        r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &p);
+        if (r < 0)
+                return r;
+
+        e = endswith(p, "/" SPECIAL_SYSTEM_SLICE);
+        if (e)
+                *e = 0;
+
+        *path = p;
+        return 0;
 }
 
 int cg_shift_path(const char *cgroup, const char *root, const char **shifted) {
@@ -1125,30 +1138,201 @@ int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) {
         return 0;
 }
 
-int cg_path_get_session(const char *path, char **session) {
-        const char *e, *n, *s;
+int cg_path_decode_unit(const char *cgroup, char **unit){
+        char *e, *c, *s;
+
+        assert(cgroup);
+        assert(unit);
+
+        e = strchrnul(cgroup, '/');
+        c = strndupa(cgroup, e - cgroup);
+        c = cg_unescape(c);
+
+        if (!unit_name_is_valid(c, TEMPLATE_INVALID))
+                return -ENXIO;
+
+        s = strdup(c);
+        if (!s)
+                return -ENOMEM;
+
+        *unit = s;
+        return 0;
+}
+
+static const char *skip_slices(const char *p) {
+        /* Skips over all slice assignments */
+
+        for (;;) {
+                size_t n;
+
+                p += strspn(p, "/");
+
+                n = strcspn(p, "/");
+                if (n <= 6 || memcmp(p + n - 6, ".slice", 6) != 0)
+                        return p;
+
+                p += n;
+        }
+}
+
+int cg_path_get_unit(const char *path, char **unit) {
+        const char *e;
+
+        assert(path);
+        assert(unit);
+
+        e = skip_slices(path);
+
+        return cg_path_decode_unit(e, unit);
+}
+
+int cg_pid_get_unit(pid_t pid, char **unit) {
+        _cleanup_free_ char *cgroup = NULL;
+        int r;
+
+        assert(unit);
+
+        r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
+        if (r < 0)
+                return r;
+
+        return cg_path_get_unit(cgroup, unit);
+}
+
+/**
+ * Skip session-*.scope, but require it to be there.
+ */
+static const char *skip_session(const char *p) {
+        size_t n;
+
+        assert(p);
+
+        p += strspn(p, "/");
+
+        n = strcspn(p, "/");
+        if (n < strlen("session-x.scope") || memcmp(p, "session-", 8) != 0 || memcmp(p + n - 6, ".scope", 6) != 0)
+                return NULL;
+
+        p += n;
+        p += strspn(p, "/");
+
+        return p;
+}
+
+/**
+ * Skip user@*.service, but require it to be there.
+ */
+static const char *skip_user_manager(const char *p) {
+        size_t n;
+
+        assert(p);
+
+        p += strspn(p, "/");
+
+        n = strcspn(p, "/");
+        if (n < strlen("user@x.service") || memcmp(p, "user@", 5) != 0 || memcmp(p + n - 8, ".service", 8) != 0)
+                return NULL;
+
+        p += n;
+        p += strspn(p, "/");
+
+        return p;
+}
+
+int cg_path_get_user_unit(const char *path, char **unit) {
+        const char *e, *t;
+
+        assert(path);
+        assert(unit);
+
+        /* 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 session scope or user manager... */
+        t = skip_session(e);
+        if (!t)
+                t = skip_user_manager(e);
+        if (!t)
+                return -ENXIO;
+
+        /* ... and skip more slices if there are any */
+        e = skip_slices(t);
+
+        return cg_path_decode_unit(e, unit);
+}
+
+int cg_pid_get_user_unit(pid_t pid, char **unit) {
+        _cleanup_free_ char *cgroup = NULL;
+        int r;
+
+        assert(unit);
+
+        r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
+        if (r < 0)
+                return r;
+
+        return cg_path_get_user_unit(cgroup, unit);
+}
+
+int cg_path_get_machine_name(const char *path, char **machine) {
+        _cleanup_free_ char *u = NULL, *sl = NULL;
+        int r;
+
+        r = cg_path_get_unit(path, &u);
+        if (r < 0)
+                return r;
+
+        sl = strjoin("/run/systemd/machines/unit:", u, NULL);
+        if (!sl)
+                return -ENOMEM;
+
+        return readlink_malloc(sl, machine);
+}
 
-        /* Elogind uses a flat hierarchy, just "/SESSION".  The only
-           wrinkle is that SESSION might be escaped.  */
+int cg_pid_get_machine_name(pid_t pid, char **machine) {
+        _cleanup_free_ char *cgroup = NULL;
+        int r;
+
+        assert(machine);
+
+        r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
+        if (r < 0)
+                return r;
+
+        return cg_path_get_machine_name(cgroup, machine);
+}
+
+int cg_path_get_session(const char *path, char **session) {
+        const char *e, *n, *x, *y;
+        char *s;
 
         assert(path);
-        assert(path[0] == '/');
 
-        e = path + 1;
+        /* Skip slices, if there are any */
+        e = skip_slices(path);
+
         n = strchrnul(e, '/');
         if (e == n)
-                return -ENOENT;
+                return -ENXIO;
 
         s = strndupa(e, n - e);
         s = cg_unescape(s);
 
-        if (!s[0])
-                return -ENOENT;
+        x = startswith(s, "session-");
+        if (!x)
+                return -ENXIO;
+        y = endswith(x, ".scope");
+        if (!y || x == y)
+                return -ENXIO;
 
         if (session) {
                 char *r;
 
-                r = strdup(s);
+                r = strndup(x, y - x);
                 if (!r)
                         return -ENOMEM;
 
@@ -1169,6 +1353,97 @@ int cg_pid_get_session(pid_t pid, char **session) {
         return cg_path_get_session(cgroup, session);
 }
 
+int cg_path_get_owner_uid(const char *path, uid_t *uid) {
+        _cleanup_free_ char *slice = NULL;
+        const char *start, *end;
+        char *s;
+        uid_t u;
+        int r;
+
+        assert(path);
+
+        r = cg_path_get_slice(path, &slice);
+        if (r < 0)
+                return r;
+
+        start = startswith(slice, "user-");
+        if (!start)
+                return -ENXIO;
+        end = endswith(slice, ".slice");
+        if (!end)
+                return -ENXIO;
+
+        s = strndupa(start, end - start);
+        if (!s)
+                return -ENXIO;
+
+        if (parse_uid(s, &u) < 0)
+                return -ENXIO;
+
+        if (uid)
+                *uid = u;
+
+        return 0;
+}
+
+int cg_pid_get_owner_uid(pid_t pid, uid_t *uid) {
+        _cleanup_free_ char *cgroup = NULL;
+        int r;
+
+        r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
+        if (r < 0)
+                return r;
+
+        return cg_path_get_owner_uid(cgroup, uid);
+}
+
+int cg_path_get_slice(const char *p, char **slice) {
+        const char *e = NULL;
+        size_t m = 0;
+
+        assert(p);
+        assert(slice);
+
+        for (;;) {
+                size_t n;
+
+                p += strspn(p, "/");
+
+                n = strcspn(p, "/");
+                if (n <= 6 || memcmp(p + n - 6, ".slice", 6) != 0) {
+                        char *s;
+
+                        if (!e)
+                                return -ENXIO;
+
+                        s = strndup(e, m);
+                        if (!s)
+                                return -ENOMEM;
+
+                        *slice = s;
+                        return 0;
+                }
+
+                e = p;
+                m = n;
+
+                p += n;
+        }
+}
+
+int cg_pid_get_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_slice(cgroup, slice);
+}
+
 char *cg_escape(const char *p) {
         bool need_prefix = false;
 
@@ -1255,6 +1530,56 @@ bool cg_controller_is_valid(const char *p, bool allow_named) {
         return true;
 }
 
+int cg_slice_to_path(const char *unit, char **ret) {
+        _cleanup_free_ char *p = NULL, *s = NULL, *e = NULL;
+        const char *dash;
+
+        assert(unit);
+        assert(ret);
+
+        if (!unit_name_is_valid(unit, TEMPLATE_INVALID))
+                return -EINVAL;
+
+        if (!endswith(unit, ".slice"))
+                return -EINVAL;
+
+        p = unit_name_to_prefix(unit);
+        if (!p)
+                return -ENOMEM;
+
+        dash = strchr(p, '-');
+        while (dash) {
+                _cleanup_free_ char *escaped = NULL;
+                char n[dash - p + sizeof(".slice")];
+
+                strcpy(stpncpy(n, p, dash - p), ".slice");
+
+                if (!unit_name_is_valid(n, TEMPLATE_INVALID))
+                        return -EINVAL;
+
+                escaped = cg_escape(n);
+                if (!escaped)
+                        return -ENOMEM;
+
+                if (!strextend(&s, escaped, "/", NULL))
+                        return -ENOMEM;
+
+                dash = strchr(dash+1, '-');
+        }
+
+        e = cg_escape(unit);
+        if (!e)
+                return -ENOMEM;
+
+        if (!strextend(&s, e, NULL))
+                return -ENOMEM;
+
+        *ret = s;
+        s = NULL;
+
+        return 0;
+}
+
 int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value) {
         _cleanup_free_ char *p = NULL;
         int r;
index f5b65909939620c42729c776c0ebf33b25c592b9..042b88f2229ec2bc7143333bcdba59c0bcc1ed72 100644 (file)
@@ -1009,7 +1009,7 @@ int get_ctty_devnr(pid_t pid, dev_t *d) {
                 return -EIO;
 
         if (major(ttynr) == 0 && minor(ttynr) == 0)
-                return -ENOENT;
+                return -ENXIO;
 
         if (d)
                 *d = (dev_t) ttynr;
index 1de100cdae3b082d8e315e7806d0309c9dc0f7f8..e4e2efecd50856046b9c88ba51a7e42514f4d959 100644 (file)
@@ -44,9 +44,8 @@ static void test_get_process_comm(void) {
         if (stat("/proc/1/comm", &st) == 0) {
                 assert_se(get_process_comm(1, &a) >= 0);
                 log_info("pid1 comm: '%s'", a);
-        } else {
+        } else
                 log_warning("/proc/1/comm does not exist.");
-        }
 
         assert_se(get_process_cmdline(1, 0, true, &c) >= 0);
         log_info("pid1 cmdline: '%s'", c);
@@ -87,7 +86,7 @@ static void test_get_process_comm(void) {
         log_info("self strlen(environ): '%zu'", strlen(env));
 
         if (!detect_container(NULL))
-                assert_se(get_ctty_devnr(1, &h) == -ENOENT);
+                assert_se(get_ctty_devnr(1, &h) == -ENXIO);
 
         getenv_for_pid(1, "PATH", &i);
         log_info("pid1 $PATH: '%s'", strna(i));