diff options
Diffstat (limited to 'src/libsystemd/sd-bus')
-rw-r--r-- | src/libsystemd/sd-bus/bus-control.c | 25 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/bus-creds.c | 147 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/bus-dump.c | 70 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/bus-kernel.c | 15 |
4 files changed, 183 insertions, 74 deletions
diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c index ca31807f70..fa4c28174d 100644 --- a/src/libsystemd/sd-bus/bus-control.c +++ b/src/libsystemd/sd-bus/bus-control.c @@ -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; } diff --git a/src/libsystemd/sd-bus/bus-creds.c b/src/libsystemd/sd-bus/bus-creds.c index 8d02885d3b..ed9bf5293b 100644 --- a/src/libsystemd/sd-bus/bus-creds.c +++ b/src/libsystemd/sd-bus/bus-creds.c @@ -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; } @@ -510,8 +518,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); @@ -530,6 +538,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; } @@ -541,6 +552,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; } @@ -552,6 +566,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; } @@ -787,8 +804,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; } } @@ -941,7 +960,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 @@ -953,17 +982,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; } } @@ -974,9 +1004,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 @@ -1005,8 +1035,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; @@ -1014,8 +1048,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; @@ -1023,13 +1061,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; @@ -1112,14 +1165,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; @@ -1128,6 +1189,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; @@ -1136,23 +1199,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; @@ -1165,6 +1239,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; @@ -1173,6 +1249,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; @@ -1199,6 +1277,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; @@ -1206,15 +1286,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; diff --git a/src/libsystemd/sd-bus/bus-dump.c b/src/libsystemd/sd-bus/bus-dump.c index 396bf36f8a..47a5c6b3a8 100644 --- a/src/libsystemd/sd-bus/bus-dump.c +++ b/src/libsystemd/sd-bus/bus-dump.c @@ -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) diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c index a8c04b98a9..556b5eb704 100644 --- a/src/libsystemd/sd-bus/bus-kernel.c +++ b/src/libsystemd/sd-bus/bus-kernel.c @@ -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: |