summaryrefslogtreecommitdiff
path: root/src/libsystemd/sd-bus/bus-creds.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsystemd/sd-bus/bus-creds.c')
-rw-r--r--src/libsystemd/sd-bus/bus-creds.c147
1 files changed, 116 insertions, 31 deletions
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;