diff options
Diffstat (limited to 'src/libsystemd-bus')
-rw-r--r-- | src/libsystemd-bus/bus-control.c | 154 | ||||
-rw-r--r-- | src/libsystemd-bus/bus-convenience.c | 30 | ||||
-rw-r--r-- | src/libsystemd-bus/bus-creds.c | 796 | ||||
-rw-r--r-- | src/libsystemd-bus/bus-creds.h | 67 | ||||
-rw-r--r-- | src/libsystemd-bus/bus-dump.c | 227 | ||||
-rw-r--r-- | src/libsystemd-bus/bus-dump.h | 2 | ||||
-rw-r--r-- | src/libsystemd-bus/bus-internal.h | 2 | ||||
-rw-r--r-- | src/libsystemd-bus/bus-kernel.c | 61 | ||||
-rw-r--r-- | src/libsystemd-bus/bus-message.c | 234 | ||||
-rw-r--r-- | src/libsystemd-bus/bus-message.h | 30 | ||||
-rw-r--r-- | src/libsystemd-bus/bus-util.c | 31 | ||||
-rw-r--r-- | src/libsystemd-bus/bus-util.h | 2 | ||||
-rw-r--r-- | src/libsystemd-bus/busctl.c | 44 | ||||
-rw-r--r-- | src/libsystemd-bus/libsystemd-bus.sym | 76 | ||||
-rw-r--r-- | src/libsystemd-bus/sd-bus.c | 120 | ||||
-rw-r--r-- | src/libsystemd-bus/test-bus-chat.c | 4 | ||||
-rw-r--r-- | src/libsystemd-bus/test-bus-creds.c | 46 | ||||
-rw-r--r-- | src/libsystemd-bus/test-bus-kernel.c | 18 |
18 files changed, 1393 insertions, 551 deletions
diff --git a/src/libsystemd-bus/bus-control.c b/src/libsystemd-bus/bus-control.c index f217269f79..43e2848ecc 100644 --- a/src/libsystemd-bus/bus-control.c +++ b/src/libsystemd-bus/bus-control.c @@ -260,80 +260,114 @@ _public_ int sd_bus_get_owner(sd_bus *bus, const char *name, char **owner) { return 0; } -_public_ int sd_bus_get_owner_uid(sd_bus *bus, const char *name, uid_t *uid) { +_public_ int sd_bus_get_owner_creds(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **creds) { _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; - uint32_t u; + _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL; + pid_t pid = 0; int r; - if (!bus) - return -EINVAL; - if (!name) - return -EINVAL; - if (!uid) - return -EINVAL; - if (!BUS_IS_OPEN(bus->state)) - return -ENOTCONN; - if (bus_pid_changed(bus)) - return -ECHILD; + assert_return(bus, -EINVAL); + assert_return(name, -EINVAL); + assert_return(mask <= _SD_BUS_CREDS_MAX, -ENOTSUP); + assert_return(creds, -EINVAL); + assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN); + assert_return(!bus_pid_changed(bus), -ECHILD); - r = sd_bus_call_method( - bus, - "org.freedesktop.DBus", - "/", - "org.freedesktop.DBus", - "GetConnectionUnixUser", - NULL, - &reply, - "s", - name); - if (r < 0) - return r; + c = bus_creds_new(); + if (!c) + return -ENOMEM; - r = sd_bus_message_read(reply, "u", &u); - if (r < 0) - return r; + if ((mask & SD_BUS_CREDS_PID) || + mask & ~(SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|SD_BUS_CREDS_SELINUX_CONTEXT)) { + uint32_t u; - *uid = (uid_t) u; - return 0; -} + r = sd_bus_call_method( + bus, + "org.freedesktop.DBus", + "/", + "org.freedesktop.DBus", + "GetConnectionUnixProcessID", + NULL, + &reply, + "s", + name); + if (r < 0) + return r; -_public_ int sd_bus_get_owner_pid(sd_bus *bus, const char *name, pid_t *pid) { - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; - uint32_t u; - int r; + r = sd_bus_message_read(reply, "u", &u); + if (r < 0) + return r; - if (!bus) - return -EINVAL; - if (!name) - return -EINVAL; - if (!pid) - return -EINVAL; - if (!BUS_IS_OPEN(bus->state)) - return -ENOTCONN; - if (bus_pid_changed(bus)) - return -ECHILD; + pid = u; + if (mask & SD_BUS_CREDS_PID) { + c->pid = u; + c->mask |= SD_BUS_CREDS_PID; + } - r = sd_bus_call_method( - bus, - "org.freedesktop.DBus", - "/", - "org.freedesktop.DBus", - "GetConnectionUnixProcessID", - NULL, - &reply, - "s", - name); - if (r < 0) - return r; + reply = sd_bus_message_unref(reply); + } + + if (mask & SD_BUS_CREDS_UID) { + uint32_t u; + + r = sd_bus_call_method( + bus, + "org.freedesktop.DBus", + "/", + "org.freedesktop.DBus", + "GetConnectionUnixUser", + NULL, + &reply, + "s", + name); + if (r < 0) + return r; + + r = sd_bus_message_read(reply, "u", &u); + if (r < 0) + return r; + + c->uid = u; + c->mask |= SD_BUS_CREDS_UID; + + reply = sd_bus_message_unref(reply); + } + + if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) { + const void *p; + size_t sz; + + r = sd_bus_call_method( + bus, + "org.freedesktop.DBus", + "/", + "org.freedesktop.DBus", + "GetConnectionSELinuxSecurityContext", + NULL, + &reply, + "s", + name); + if (r < 0) + return r; + + r = sd_bus_message_read_array(reply, 'y', &p, &sz); + if (r < 0) + return r; + + c->label = strndup(p, sz); + if (!c->label) + return -ENOMEM; + + c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT; + } - r = sd_bus_message_read(reply, "u", &u); + r = bus_creds_add_more(c, mask, pid, 0); if (r < 0) return r; - if (u == 0) - return -EIO; + *creds = c; + c = NULL; - *pid = (uid_t) u; return 0; } diff --git a/src/libsystemd-bus/bus-convenience.c b/src/libsystemd-bus/bus-convenience.c index e765ddb21d..e57b26bf6b 100644 --- a/src/libsystemd-bus/bus-convenience.c +++ b/src/libsystemd-bus/bus-convenience.c @@ -410,3 +410,33 @@ _public_ int sd_bus_set_property( return sd_bus_call(bus, m, 0, error, NULL); } + +_public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **creds) { + sd_bus_creds *c; + + assert_return(call, -EINVAL); + assert_return(call->sealed, -EPERM); + assert_return(call->bus && BUS_IS_OPEN(call->bus->state), -ENOTCONN); + assert_return(!bus_pid_changed(call->bus), -ECHILD); + + c = sd_bus_message_get_creds(call); + + /* All data we need? */ + if (c && (mask & ~c->mask) == 0) { + *creds = sd_bus_creds_ref(c); + return 0; + } + + /* No data passed? Or not enough data passed to retrieve the missing bits? */ + if (!c || !(c->mask & SD_BUS_CREDS_PID)) { + /* We couldn't read anything from the call, let's try + * to get it from the sender or peer */ + + if (call->sender) + return sd_bus_get_owner_creds(call->bus, call->sender, mask, creds); + else + return sd_bus_get_peer_creds(call->bus, mask, creds); + } + + return sd_bus_creds_extend(c, mask, creds); +} diff --git a/src/libsystemd-bus/bus-creds.c b/src/libsystemd-bus/bus-creds.c new file mode 100644 index 0000000000..5ca70ccafa --- /dev/null +++ b/src/libsystemd-bus/bus-creds.c @@ -0,0 +1,796 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2013 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <stdlib.h> + +#include "util.h" +#include "cgroup-util.h" +#include "fileio.h" +#include "audit.h" +#include "bus-message.h" +#include "bus-util.h" +#include "time-util.h" +#include "bus-creds.h" + +enum { + CAP_OFFSET_INHERITABLE = 0, + CAP_OFFSET_PERMITTED = 1, + CAP_OFFSET_EFFECTIVE = 2, + CAP_OFFSET_BOUNDING = 3 +}; + +void bus_creds_done(sd_bus_creds *c) { + assert(c); + + /* For internal bus cred structures that are allocated by + * something else */ + + free(c->session); + free(c->unit); + free(c->user_unit); + free(c->slice); + + free(c->cmdline_array); +} + +_public_ sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c) { + assert_return(c, NULL); + + if (c->allocated) { + assert(c->n_ref > 0); + c->n_ref++; + } else { + sd_bus_message *m; + + /* If this is an embedded creds structure, then + * forward ref counting to the message */ + m = container_of(c, sd_bus_message, creds); + sd_bus_message_ref(m); + } + + return c; +} + +_public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) { + assert_return(c, NULL); + + if (c->allocated) { + assert(c->n_ref > 0); + c->n_ref--; + + if (c->n_ref == 0) { + bus_creds_done(c); + + free(c->comm); + free(c->tid_comm); + free(c->exe); + free(c->cmdline); + free(c->cgroup); + free(c->capability); + free(c->label); + free(c); + } + } else { + sd_bus_message *m; + + m = container_of(c, sd_bus_message, creds); + sd_bus_message_unref(m); + } + + + return NULL; +} + +_public_ uint64_t sd_bus_creds_get_mask(sd_bus_creds *c) { + assert_return(c, 0); + + return c->mask; +} + +sd_bus_creds* bus_creds_new(void) { + sd_bus_creds *c; + + c = new0(sd_bus_creds, 1); + if (!c) + return NULL; + + c->allocated = true; + c->n_ref = 1; + return c; +} + +_public_ int sd_bus_creds_new_from_pid(pid_t pid, uint64_t mask, sd_bus_creds **ret) { + sd_bus_creds *c; + int r; + + assert_return(pid >= 0, -EINVAL); + assert_return(mask <= _SD_BUS_CREDS_MAX, -ENOTSUP); + assert_return(ret, -EINVAL); + + if (pid == 0) + pid = getpid(); + + c = bus_creds_new(); + if (!c) + return -ENOMEM; + + r = bus_creds_add_more(c, mask, pid, 0); + if (r < 0) { + free(c); + return r; + } + + /* Check if the process existed at all, in case we haven't + * figured that out already */ + if (kill(pid, 0) < 0 && errno == ESRCH) { + sd_bus_creds_unref(c); + return -ESRCH; + } + + *ret = c; + return 0; +} + +_public_ int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid) { + assert_return(c, -EINVAL); + assert_return(uid, -EINVAL); + assert_return(c->mask & SD_BUS_CREDS_UID, -ENODATA); + + *uid = c->uid; + return 0; +} + +_public_ int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) { + assert_return(c, -EINVAL); + assert_return(gid, -EINVAL); + assert_return(c->mask & SD_BUS_CREDS_UID, -ENODATA); + + *gid = c->gid; + return 0; +} + +_public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) { + assert_return(c, -EINVAL); + assert_return(pid, -EINVAL); + assert_return(c->mask & SD_BUS_CREDS_PID, -ENODATA); + + assert(c->pid > 0); + *pid = c->pid; + return 0; +} + +_public_ int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid) { + assert_return(c, -EINVAL); + assert_return(tid, -EINVAL); + assert_return(c->mask & SD_BUS_CREDS_TID, -ENODATA); + + assert(c->tid > 0); + *tid = c->tid; + return 0; +} + +_public_ int sd_bus_creds_get_pid_starttime(sd_bus_creds *c, uint64_t *usec) { + assert_return(c, -EINVAL); + assert_return(usec, -EINVAL); + assert_return(c->mask & SD_BUS_CREDS_PID_STARTTIME, -ENODATA); + + assert(c->pid_starttime > 0); + *usec = c->pid_starttime; + return 0; +} + +_public_ int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **ret) { + assert_return(c, -EINVAL); + assert_return(c->mask & SD_BUS_CREDS_SELINUX_CONTEXT, -ENODATA); + + assert(c->label); + *ret = c->label; + return 0; +} + +_public_ int sd_bus_creds_get_comm(sd_bus_creds *c, const char **ret) { + assert_return(c, -EINVAL); + assert_return(ret, -EINVAL); + assert_return(c->mask & SD_BUS_CREDS_COMM, -ENODATA); + + assert(c->comm); + *ret = c->comm; + return 0; +} + +_public_ int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **ret) { + assert_return(c, -EINVAL); + assert_return(ret, -EINVAL); + assert_return(c->mask & SD_BUS_CREDS_TID_COMM, -ENODATA); + + assert(c->tid_comm); + *ret = c->tid_comm; + return 0; +} + +_public_ int sd_bus_creds_get_exe(sd_bus_creds *c, const char **ret) { + assert_return(c, -EINVAL); + assert_return(ret, -EINVAL); + assert_return(c->mask & SD_BUS_CREDS_EXE, -ENODATA); + + assert(c->exe); + *ret = c->exe; + return 0; +} + +_public_ int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **ret) { + assert_return(c, -EINVAL); + assert_return(ret, -EINVAL); + assert_return(c->mask & SD_BUS_CREDS_CGROUP, -ENODATA); + + assert(c->cgroup); + *ret = c->cgroup; + return 0; +} + +_public_ int sd_bus_creds_get_unit(sd_bus_creds *c, const char **ret) { + int r; + + assert_return(c, -EINVAL); + assert_return(ret, -EINVAL); + assert_return(c->mask & SD_BUS_CREDS_UNIT, -ENODATA); + + assert(c->cgroup); + + if (!c->unit) { + r = cg_path_get_unit(c->cgroup, (char**) &c->unit); + if (r < 0) + return r; + } + + *ret = c->unit; + return 0; +} + +_public_ int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **ret) { + int r; + + assert_return(c, -EINVAL); + assert_return(ret, -EINVAL); + assert_return(c->mask & SD_BUS_CREDS_USER_UNIT, -ENODATA); + + assert(c->cgroup); + + if (!c->user_unit) { + r = cg_path_get_user_unit(c->cgroup, (char**) &c->user_unit); + if (r < 0) + return r; + } + + *ret = c->user_unit; + return 0; +} + +_public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) { + int r; + + assert_return(c, -EINVAL); + assert_return(ret, -EINVAL); + assert_return(c->mask & SD_BUS_CREDS_SLICE, -ENODATA); + + assert(c->cgroup); + + if (!c->slice) { + r = cg_path_get_slice(c->cgroup, (char**) &c->slice); + if (r < 0) + return r; + } + + *ret = c->slice; + return 0; +} + +_public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) { + int r; + + assert_return(c, -EINVAL); + assert_return(ret, -EINVAL); + assert_return(c->mask & SD_BUS_CREDS_SESSION, -ENODATA); + + assert(c->cgroup); + + if (!c->session) { + r = cg_path_get_session(c->cgroup, (char**) &c->session); + if (r < 0) + return r; + } + + *ret = c->session; + return 0; +} + +_public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) { + assert_return(c, -EINVAL); + assert_return(uid, -EINVAL); + assert_return(c->mask & SD_BUS_CREDS_OWNER_UID, -ENODATA); + + assert(c->cgroup); + + return cg_path_get_owner_uid(c->cgroup, uid); +} + +_public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) { + size_t n, i; + const char *p; + bool first; + + assert_return(c, -EINVAL); + assert_return(c->cmdline, -ESRCH); + assert_return(c->mask & SD_BUS_CREDS_CMDLINE, -ENODATA); + + assert(c->cmdline); + + for (p = c->cmdline, n = 0; p < c->cmdline + c->cmdline_length; p++) + if (*p == 0) + n++; + + *(char***) &c->cmdline_array = new(char*, n + 1); + if (!c->cmdline_array) + return -ENOMEM; + + for (p = c->cmdline, i = 0, first = true; p < c->cmdline + c->cmdline_length; p++) { + if (first) + c->cmdline_array[i++] = (char*) p; + + first = *p == 0; + } + + c->cmdline_array[i] = NULL; + *cmdline = c->cmdline_array; + + return 0; +} + +_public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid) { + assert_return(c, -EINVAL); + assert_return(sessionid, -EINVAL); + assert_return(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID, -ENODATA); + + *sessionid = c->audit_session_id; + return 0; +} + +_public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) { + assert_return(c, -EINVAL); + assert_return(uid, -EINVAL); + assert_return(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID, -ENODATA); + + *uid = c->audit_login_uid; + return 0; +} + +static int has_cap(sd_bus_creds *c, unsigned offset, int capability) { + size_t sz; + + assert(c); + assert(c->capability); + + sz = c->capability_size / 4; + if ((size_t) capability >= sz*8) + return 0; + + return !!(c->capability[offset * sz + (capability / 8)] & (1 << (capability % 8))); +} + +_public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) { + assert_return(c, -EINVAL); + assert_return(capability >= 0, -EINVAL); + assert_return(c->mask & SD_BUS_CREDS_EFFECTIVE_CAPS, -ENODATA); + + return has_cap(c, CAP_OFFSET_EFFECTIVE, capability); +} + +_public_ int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability) { + assert_return(c, -EINVAL); + assert_return(capability >= 0, -EINVAL); + assert_return(c->mask & SD_BUS_CREDS_PERMITTED_CAPS, -ENODATA); + + return has_cap(c, CAP_OFFSET_PERMITTED, capability); +} + +_public_ int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability) { + assert_return(c, -EINVAL); + assert_return(capability >= 0, -EINVAL); + assert_return(c->mask & SD_BUS_CREDS_INHERITABLE_CAPS, -ENODATA); + + return has_cap(c, CAP_OFFSET_INHERITABLE, capability); +} + +_public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) { + assert_return(c, -EINVAL); + assert_return(capability >= 0, -EINVAL); + assert_return(c->mask & SD_BUS_CREDS_BOUNDING_CAPS, -ENODATA); + + return has_cap(c, CAP_OFFSET_BOUNDING, capability); +} + +static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) { + size_t sz; + unsigned i; + + assert(c); + assert(p); + + p += strspn(p, WHITESPACE); + + sz = strlen(p); + if (sz % 2 != 0) + return -EINVAL; + + sz /= 2; + if (!c->capability) { + c->capability = new0(uint8_t, sz * 4); + if (!c->capability) + return -ENOMEM; + + c->capability_size = sz * 4; + } + + for (i = 0; i < sz; i ++) { + int x, y; + + x = unhexchar(p[i*2]); + y = unhexchar(p[i*2+1]); + + if (x < 0 || y < 0) + return -EINVAL; + + c->capability[offset * sz + (sz - i - 1)] = (uint8_t) x << 4 | (uint8_t) y; + } + + return 0; +} + +int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) { + uint64_t missing; + int r; + + assert(c); + assert(c->allocated); + + missing = mask & ~c->mask; + if (missing == 0) + return 0; + + /* Try to retrieve PID from creds if it wasn't passed to us */ + if (pid <= 0 && (c->mask & SD_BUS_CREDS_PID)) + pid = c->pid; + + if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID)) + tid = c->pid; + + /* Without pid we cannot do much... */ + if (pid <= 0) + return 0; + + if (missing & (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID | + SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS | + SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) { + + _cleanup_fclose_ FILE *f = NULL; + char line[LINE_MAX]; + const char *p; + + p = procfs_file_alloca(pid, "status"); + + f = fopen(p, "re"); + if (!f) + return errno == ENOENT ? -ESRCH : -errno; + + FOREACH_LINE(line, f, return -errno) { + truncate_nl(line); + + if (missing & SD_BUS_CREDS_UID) { + p = startswith(line, "Uid:"); + if (p) { + unsigned long uid; + + p += strspn(p, WHITESPACE); + if (sscanf(p, "%lu", &uid) != 1) + return -EIO; + + c->uid = (uid_t) uid; + c->mask |= SD_BUS_CREDS_UID; + continue; + } + } + + if (missing & SD_BUS_CREDS_GID) { + p = startswith(line, "Gid:"); + if (p) { + unsigned long gid; + + p += strspn(p, WHITESPACE); + if (sscanf(p, "%lu", &gid) != 1) + return -EIO; + + c->gid = (uid_t) gid; + c->mask |= SD_BUS_CREDS_GID; + continue; + } + } + + if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) { + p = startswith(line, "CapEff:"); + if (p) { + r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p); + if (r < 0) + return r; + + c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS; + continue; + } + } + + if (missing & SD_BUS_CREDS_PERMITTED_CAPS) { + p = startswith(line, "CapPrm:"); + if (p) { + r = parse_caps(c, CAP_OFFSET_PERMITTED, p); + if (r < 0) + return r; + + c->mask |= SD_BUS_CREDS_PERMITTED_CAPS; + continue; + } + } + + if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) { + p = startswith(line, "CapInh:"); + if (p) { + r = parse_caps(c, CAP_OFFSET_INHERITABLE, p); + if (r < 0) + return r; + + c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS; + continue; + } + } + + if (missing & SD_BUS_CREDS_BOUNDING_CAPS) { + p = startswith(line, "CapBnd:"); + if (p) { + r = parse_caps(c, CAP_OFFSET_BOUNDING, p); + if (r < 0) + return r; + + c->mask |= SD_BUS_CREDS_BOUNDING_CAPS; + continue; + } + } + } + } + + if (missing & (SD_BUS_CREDS_PID_STARTTIME)) { + unsigned long long st; + + r = get_starttime_of_pid(pid, &st); + if (r < 0) + return r; + + c->pid_starttime = ((usec_t) st * USEC_PER_SEC) / (usec_t) sysconf(_SC_CLK_TCK); + c->mask |= SD_BUS_CREDS_PID_STARTTIME; + } + + if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) { + const char *p; + + p = procfs_file_alloca(pid, "attr/current"); + r = read_one_line_file(p, &c->label); + if (r < 0 && r != -ENOENT) + return r; + else if (r >= 0) + c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT; + } + + if (missing & SD_BUS_CREDS_COMM) { + r = get_process_comm(pid, &c->comm); + if (r < 0) + return r; + + c->mask |= SD_BUS_CREDS_COMM; + } + + if (missing & SD_BUS_CREDS_EXE) { + r = get_process_exe(pid, &c->exe); + if (r < 0) + return r; + + c->mask |= SD_BUS_CREDS_EXE; + } + + if (missing & SD_BUS_CREDS_CMDLINE) { + const char *p; + + p = procfs_file_alloca(pid, "cmdline"); + r = read_full_file(p, &c->cmdline, &c->cmdline_length); + if (r < 0) + return r; + + if (c->cmdline_length == 0) { + free(c->cmdline); + c->cmdline = NULL; + } else + c->mask |= SD_BUS_CREDS_CMDLINE; + } + + if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) { + _cleanup_free_ char *p = NULL; + + if (asprintf(&p, "/proc/%lu/task/%lu/comm", (unsigned long) pid, (unsigned long) tid) < 0) + return -ENOMEM; + + r = read_one_line_file(p, &c->tid_comm); + if (r < 0) + return r == -ENOENT ? -ESRCH : r; + + c->mask |= SD_BUS_CREDS_TID_COMM; + } + + if (missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID)) { + + r = cg_pid_get_path(NULL, pid, &c->cgroup); + if (r < 0) + return r; + + c->mask |= missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID); + } + + if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) { + r = audit_session_from_pid(pid, &c->audit_session_id); + if (r < 0 && r != -ENOTSUP && r != -ENXIO && r != ENOENT) + return r; + else if (r >= 0) + c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID; + } + + if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) { + r = audit_loginuid_from_pid(pid, &c->audit_login_uid); + if (r < 0 && r != -ENOTSUP && r != -ENXIO && r != ENOENT) + return r; + else if (r >= 0) + c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID; + } + + return 0; +} + +_public_ int sd_bus_creds_extend(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) { + _cleanup_bus_creds_unref_ sd_bus_creds *n = NULL; + int r; + + assert_return(c, -EINVAL); + assert_return(ret, -EINVAL); + + if ((mask & ~c->mask) == 0) { + /* There's already all data we need. */ + + *ret = sd_bus_creds_ref(c); + return 0; + } + + n = bus_creds_new(); + if (!n) + return -ENOMEM; + + /* Copy the original data over */ + + if (c->mask & mask & SD_BUS_CREDS_UID) { + n->uid = c->uid; + n->mask |= SD_BUS_CREDS_UID; + } + + if (c->mask & mask & SD_BUS_CREDS_GID) { + n->gid = c->gid; + n->mask |= SD_BUS_CREDS_GID; + } + + if (c->mask & mask & SD_BUS_CREDS_PID) { + n->pid = c->pid; + n->mask |= SD_BUS_CREDS_PID; + } + + if (c->mask & mask & SD_BUS_CREDS_TID) { + n->tid = c->tid; + n->mask |= SD_BUS_CREDS_TID; + } + + if (c->mask & mask & SD_BUS_CREDS_PID_STARTTIME) { + n->pid_starttime = c->pid_starttime; + n->mask |= SD_BUS_CREDS_PID_STARTTIME; + } + + if (c->mask & mask & SD_BUS_CREDS_COMM) { + n->comm = strdup(c->comm); + if (!n->comm) + return -ENOMEM; + + n->mask |= SD_BUS_CREDS_COMM; + } + + if (c->mask & mask & SD_BUS_CREDS_TID_COMM) { + n->tid_comm = strdup(c->tid_comm); + if (!n->tid_comm) + return -ENOMEM; + + n->mask |= SD_BUS_CREDS_TID_COMM; + } + + if (c->mask & mask & SD_BUS_CREDS_EXE) { + n->exe = strdup(c->exe); + if (!n->exe) + return -ENOMEM; + + n->mask |= SD_BUS_CREDS_EXE; + } + + if (c->mask & mask & SD_BUS_CREDS_CMDLINE) { + n->cmdline = memdup(c->cmdline, c->cmdline_length); + if (!n->cmdline) + return -ENOMEM; + + n->cmdline_length = c->cmdline_length; + 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)) { + n->cgroup = strdup(c->cgroup); + if (!n->cgroup) + return -ENOMEM; + + n->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); + } + + if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) { + n->capability = memdup(c->capability, c->capability_size); + if (!n->capability) + return -ENOMEM; + + n->capability_size = c->capability_size; + n->mask |= c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS); + } + + if (c->mask & mask & SD_BUS_CREDS_AUDIT_SESSION_ID) { + n->audit_session_id = c->audit_session_id; + n->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID; + } + + if (c->mask & mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) { + n->audit_login_uid = c->audit_login_uid; + n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID; + } + + /* Get more data */ + + r = bus_creds_add_more(n, mask, + c->mask & SD_BUS_CREDS_PID ? c->pid : 0, + c->mask & SD_BUS_CREDS_TID ? c->tid : 0); + if (r < 0) + return r; + + *ret = n; + n = NULL; + return 0; +} diff --git a/src/libsystemd-bus/bus-creds.h b/src/libsystemd-bus/bus-creds.h new file mode 100644 index 0000000000..e2416aa501 --- /dev/null +++ b/src/libsystemd-bus/bus-creds.h @@ -0,0 +1,67 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2013 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <stdbool.h> + +#include "sd-bus.h" +#include "time-util.h" + +struct sd_bus_creds { + bool allocated; + unsigned n_ref; + uint64_t mask; + + uid_t uid; + gid_t gid; + pid_t pid; + usec_t pid_starttime; + pid_t tid; + + char *comm; + char *tid_comm; + char *exe; + + char *cmdline; + size_t cmdline_length; + char **cmdline_array; + + char *cgroup; + char *session; + char *unit; + char *user_unit; + char *slice; + + uint8_t *capability; + size_t capability_size; + + uint32_t audit_session_id; + uid_t audit_login_uid; + + char *label; +}; + +sd_bus_creds* bus_creds_new(void); + +void bus_creds_done(sd_bus_creds *c); + +int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid); diff --git a/src/libsystemd-bus/bus-dump.c b/src/libsystemd-bus/bus-dump.c index 8231cfabcd..9545e181d8 100644 --- a/src/libsystemd-bus/bus-dump.c +++ b/src/libsystemd-bus/bus-dump.c @@ -24,6 +24,7 @@ #include "util.h" #include "capability.h" #include "strv.h" +#include "audit.h" #include "bus-message.h" #include "bus-internal.h" @@ -45,13 +46,8 @@ static char *indent(unsigned level) { } int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) { - const char *u = NULL, *uu = NULL, *s = NULL; - char **cmdline = NULL; unsigned level = 1; int r; - uid_t owner, audit_loginuid; - uint32_t audit_sessionid; - bool audit_sessionid_is_set = false, audit_loginuid_is_set = false; assert(m); @@ -96,23 +92,6 @@ int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) { ansi_highlight_red(), strna(m->error.name), ansi_highlight_off(), ansi_highlight_red(), strna(m->error.message), ansi_highlight_off()); - if (m->pid != 0) - fprintf(f, " PID=%lu", (unsigned long) m->pid); - if (m->pid_starttime != 0) - fprintf(f, " PIDStartTime=%llu", (unsigned long long) m->pid_starttime); - if (m->tid != 0) - fprintf(f, " TID=%lu", (unsigned long) m->tid); - if (m->uid_valid) - fprintf(f, " UID=%lu", (unsigned long) m->uid); - r = sd_bus_message_get_owner_uid(m, &owner); - if (r >= 0) - fprintf(f, " OwnerUID=%lu", (unsigned long) owner); - if (m->gid_valid) - fprintf(f, " GID=%lu", (unsigned long) m->gid); - - if (m->pid != 0 || m->pid_starttime != 0 || m->tid != 0 || m->uid_valid || r >= 0 || m->gid_valid) - fputs("\n", f); - if (m->monotonic != 0) fprintf(f, " Monotonic=%llu", (unsigned long long) m->monotonic); if (m->realtime != 0) @@ -121,70 +100,7 @@ int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) { if (m->monotonic != 0 || m->realtime != 0) fputs("\n", f); - if (m->exe) - fprintf(f, " Exe=%s", m->exe); - if (m->comm) - fprintf(f, " Comm=%s", m->comm); - if (m->tid_comm) - fprintf(f, " TIDComm=%s", m->tid_comm); - if (m->label) - fprintf(f, " Label=%s", m->label); - - if (m->exe || m->comm || m->tid_comm || m->label) - fputs("\n", f); - - if (sd_bus_message_get_cmdline(m, &cmdline) >= 0) { - char **c; - - fputs(" CommandLine=[", f); - STRV_FOREACH(c, cmdline) { - if (c != cmdline) - fputc(' ', f); - - fputs(*c, f); - } - - fputs("]\n", f); - } - - if (m->cgroup) - fprintf(f, " CGroup=%s\n", m->cgroup); - - sd_bus_message_get_unit(m, &u); - if (u) - fprintf(f, " Unit=%s", u); - sd_bus_message_get_user_unit(m, &uu); - if (uu) - fprintf(f, " UserUnit=%s", uu); - sd_bus_message_get_session(m, &s); - if (s) - fprintf(f, " Session=%s", s); - if (sd_bus_message_get_audit_loginuid(m, &audit_loginuid) >= 0) { - audit_loginuid_is_set = true; - fprintf(f, " AuditLoginUID=%lu", (unsigned long) audit_loginuid); - } - if (sd_bus_message_get_audit_sessionid(m, &audit_sessionid) >= 0) { - audit_sessionid_is_set = true; - fprintf(f, " AuditSessionID=%lu", (unsigned long) audit_sessionid); - } - - if (u || uu || s || audit_loginuid_is_set || audit_sessionid_is_set) - fputs("\n", f); - - r = sd_bus_message_has_effective_cap(m, 0); - if (r >= 0) { - unsigned long c, last_cap; - - fprintf(f, " Capabilities=%s", r ? cap_to_name(0) : ""); - - last_cap = cap_last_cap(); - for (c = 0; c < last_cap; c++) { - r = sd_bus_message_has_effective_cap(m, c); - if (r > 0) - fprintf(f, "|%s", cap_to_name(c)); - } - fputs("\n", f); - } + bus_creds_dump(&m->creds, f); } r = sd_bus_message_rewind(m, true); @@ -333,3 +249,142 @@ int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) { fprintf(f, " };\n\n"); return 0; } + +static void dump_capabilities( + sd_bus_creds *c, + FILE *f, + const char *name, + int (*has)(sd_bus_creds *c, int capability)) { + + unsigned long i, last_cap; + unsigned n = 0; + int r; + + assert(c); + assert(f); + assert(name); + assert(has); + + i = 0; + r = has(c, i); + if (r < 0) + return; + + fprintf(f, " %s=", name); + last_cap = cap_last_cap(); + + for (;;) { + if (r > 0) { + if (n > 0) + fputc(' ', f); + if (n % 4 == 3) + fputs("\n ", f); + + fputs(cap_to_name(i), f); + n++; + } + + i++; + + if (i > last_cap) + break; + + r = has(c, i); + } + + fputs("\n", f); +} + +int bus_creds_dump(sd_bus_creds *c, FILE *f) { + 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; + int r; + + assert(c); + + if (!f) + f = stdout; + + if (c->mask & SD_BUS_CREDS_PID) + fprintf(f, " PID=%lu", (unsigned long) c->pid); + if (c->mask & SD_BUS_CREDS_PID_STARTTIME) + fprintf(f, " PIDStartTime=%llu", (unsigned long long) c->pid_starttime); + if (c->mask & SD_BUS_CREDS_TID) + fprintf(f, " TID=%lu", (unsigned long) c->tid); + if (c->mask & SD_BUS_CREDS_UID) + fprintf(f, " UID=%lu", (unsigned long) c->uid); + r = sd_bus_creds_get_owner_uid(c, &owner); + if (r >= 0) + fprintf(f, " OwnerUID=%lu", (unsigned long) owner); + if (c->mask & SD_BUS_CREDS_GID) + fprintf(f, " GID=%lu", (unsigned long) c->gid); + + if ((c->mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID|SD_BUS_CREDS_UID|SD_BUS_CREDS_GID)) || r >= 0) + fputs("\n", f); + + if (c->mask & SD_BUS_CREDS_EXE) + fprintf(f, " Exe=%s", c->exe); + if (c->mask & SD_BUS_CREDS_COMM) + fprintf(f, " Comm=%s", c->comm); + if (c->mask & SD_BUS_CREDS_TID_COMM) + fprintf(f, " TIDComm=%s", c->tid_comm); + if (c->mask & SD_BUS_CREDS_SELINUX_CONTEXT) + fprintf(f, " Label=%s", c->label); + + if (c->mask & (SD_BUS_CREDS_EXE|SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_SELINUX_CONTEXT)) + fputs("\n", f); + + if (sd_bus_creds_get_cmdline(c, &cmdline) >= 0) { + char **i; + + fputs(" CommandLine=", f); + STRV_FOREACH(i, cmdline) { + if (i != cmdline) + fputc(' ', f); + + fputs(*i, f); + } + + fputs("\n", f); + } + + if (c->mask & SD_BUS_CREDS_CGROUP) + fprintf(f, " CGroup=%s", c->cgroup); + sd_bus_creds_get_unit(c, &u); + if (u) + fprintf(f, " Unit=%s", u); + sd_bus_creds_get_user_unit(c, &uu); + if (uu) + fprintf(f, " UserUnit=%s", uu); + sd_bus_creds_get_slice(c, &sl); + if (sl) + fprintf(f, " Slice=%s", sl); + sd_bus_creds_get_session(c, &s); + if (s) + fprintf(f, " Session=%s", s); + + if ((c->mask & SD_BUS_CREDS_CGROUP) || u || uu || sl || s) + fputs("\n", f); + + if (sd_bus_creds_get_audit_login_uid(c, &audit_loginuid) >= 0) { + audit_loginuid_is_set = true; + fprintf(f, " AuditLoginUID=%lu", (unsigned long) audit_loginuid); + } + if (sd_bus_creds_get_audit_session_id(c, &audit_sessionid) >= 0) { + audit_sessionid_is_set = true; + fprintf(f, " AuditSessionID=%lu", (unsigned long) audit_sessionid); + } + + if (audit_loginuid_is_set || audit_sessionid_is_set) + fputs("\n", f); + + dump_capabilities(c, f, "EffectiveCapabilities", sd_bus_creds_has_effective_cap); + dump_capabilities(c, f, "PermittedCapabilities", sd_bus_creds_has_permitted_cap); + dump_capabilities(c, f, "InheritableCapabilities", sd_bus_creds_has_inheritable_cap); + dump_capabilities(c, f, "BoundingCapabilities", sd_bus_creds_has_bounding_cap); + + return 0; +} diff --git a/src/libsystemd-bus/bus-dump.h b/src/libsystemd-bus/bus-dump.h index 51aa6aad4a..bb1d25dc42 100644 --- a/src/libsystemd-bus/bus-dump.h +++ b/src/libsystemd-bus/bus-dump.h @@ -27,3 +27,5 @@ #include "sd-bus.h" int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header); + +int bus_creds_dump(sd_bus_creds *c, FILE *f); diff --git a/src/libsystemd-bus/bus-internal.h b/src/libsystemd-bus/bus-internal.h index 7a695c7b93..accb83849b 100644 --- a/src/libsystemd-bus/bus-internal.h +++ b/src/libsystemd-bus/bus-internal.h @@ -213,6 +213,8 @@ struct sd_bus { struct ucred ucred; char label[NAME_MAX]; + uint64_t creds_mask; + int *fds; unsigned n_fds; diff --git a/src/libsystemd-bus/bus-kernel.c b/src/libsystemd-bus/bus-kernel.c index da9474dc51..84d84df59d 100644 --- a/src/libsystemd-bus/bus-kernel.c +++ b/src/libsystemd-bus/bus-kernel.c @@ -548,31 +548,48 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_mess idx += d->memfd.size; } else if (d->type == KDBUS_MSG_SRC_CREDS) { - m->pid_starttime = d->creds.starttime / NSEC_PER_USEC; - m->uid = d->creds.uid; - m->gid = d->creds.gid; - m->pid = d->creds.pid; - m->tid = d->creds.tid; - m->uid_valid = m->gid_valid = true; + m->creds.pid_starttime = d->creds.starttime / NSEC_PER_USEC; + m->creds.uid = d->creds.uid; + m->creds.gid = d->creds.gid; + m->creds.pid = d->creds.pid; + m->creds.tid = d->creds.tid; + m->creds.mask |= (SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID) & bus->creds_mask; + } else if (d->type == KDBUS_MSG_TIMESTAMP) { m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC; m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC; - } else if (d->type == KDBUS_MSG_SRC_PID_COMM) - m->comm = d->str; - else if (d->type == KDBUS_MSG_SRC_TID_COMM) - m->tid_comm = d->str; - else if (d->type == KDBUS_MSG_SRC_EXE) - m->exe = d->str; - else if (d->type == KDBUS_MSG_SRC_CMDLINE) { - m->cmdline = d->str; - m->cmdline_length = l; - } else if (d->type == KDBUS_MSG_SRC_CGROUP) - m->cgroup = d->str; - else if (d->type == KDBUS_MSG_SRC_AUDIT) - m->audit = &d->audit; - else if (d->type == KDBUS_MSG_SRC_CAPS) { - m->capability = d->data; - m->capability_size = l; + + } else if (d->type == KDBUS_MSG_SRC_PID_COMM) { + m->creds.comm = d->str; + m->creds.mask |= SD_BUS_CREDS_COMM & bus->creds_mask; + + } else if (d->type == KDBUS_MSG_SRC_TID_COMM) { + m->creds.tid_comm = d->str; + m->creds.mask |= SD_BUS_CREDS_TID_COMM & bus->creds_mask; + + } else if (d->type == KDBUS_MSG_SRC_EXE) { + m->creds.exe = d->str; + m->creds.mask |= SD_BUS_CREDS_EXE & bus->creds_mask; + + } else if (d->type == KDBUS_MSG_SRC_CMDLINE) { + m->creds.cmdline = d->str; + m->creds.cmdline_length = l; + m->creds.mask |= SD_BUS_CREDS_CMDLINE & bus->creds_mask; + + } else if (d->type == KDBUS_MSG_SRC_CGROUP) { + m->creds.cgroup = d->str; + m->creds.mask |= (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID) & bus->creds_mask; + + } else if (d->type == KDBUS_MSG_SRC_AUDIT) { + m->creds.audit_session_id = d->audit.sessionid; + m->creds.audit_login_uid = d->audit.loginuid; + m->creds.mask |= (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID) & bus->creds_mask; + + } else if (d->type == KDBUS_MSG_SRC_CAPS) { + m->creds.capability = d->data; + m->creds.capability_size = l; + m->creds.mask |= (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS) & bus->creds_mask; + } else if (d->type == KDBUS_MSG_DST_NAME) destination = d->str; else if (d->type != KDBUS_MSG_FDS && diff --git a/src/libsystemd-bus/bus-message.c b/src/libsystemd-bus/bus-message.c index 132426f6fd..dd058e72c4 100644 --- a/src/libsystemd-bus/bus-message.c +++ b/src/libsystemd-bus/bus-message.c @@ -143,16 +143,12 @@ static void message_free(sd_bus_message *m) { if (m->iovec != m->iovec_fixed) free(m->iovec); - free(m->cmdline_array); - message_reset_containers(m); free(m->root_container.signature); free(m->peeked_signature); - free(m->unit); - free(m->user_unit); - free(m->session); + bus_creds_done(&m->creds); free(m); } @@ -358,15 +354,17 @@ int bus_message_from_header( m->n_fds = n_fds; if (ucred) { - m->uid = ucred->uid; - m->pid = ucred->pid; - m->gid = ucred->gid; - m->uid_valid = m->gid_valid = true; + m->creds.uid = ucred->uid; + m->creds.pid = ucred->pid; + m->creds.gid = ucred->gid; + m->creds.mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_GID; } if (label) { - m->label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra); - memcpy(m->label, label, label_sz + 1); + m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra); + memcpy(m->creds.label, label, label_sz + 1); + + m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT; } if (bus) @@ -811,63 +809,10 @@ _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) { return &m->error; } -_public_ int sd_bus_message_get_uid(sd_bus_message *m, uid_t *uid) { - assert_return(m, -EINVAL); - assert_return(uid, -EINVAL); - assert_return(m->uid_valid, -ESRCH); - - *uid = m->uid; - return 0; -} - -_public_ int sd_bus_message_get_gid(sd_bus_message *m, gid_t *gid) { - assert_return(m, -EINVAL); - assert_return(gid, -EINVAL); - assert_return(m->gid_valid, -ESRCH); - - *gid = m->gid; - return 0; -} - -_public_ int sd_bus_message_get_pid(sd_bus_message *m, pid_t *pid) { - assert_return(m, -EINVAL); - assert_return(pid, -EINVAL); - assert_return(m->pid > 0, -ESRCH); - - *pid = m->pid; - return 0; -} - -_public_ int sd_bus_message_get_tid(sd_bus_message *m, pid_t *tid) { - assert_return(m, -EINVAL); - assert_return(tid, -EINVAL); - assert_return(m->tid > 0, -ESRCH); - - *tid = m->tid; - return 0; -} - -_public_ int sd_bus_message_get_pid_starttime(sd_bus_message *m, uint64_t *usec) { - assert_return(m, -EINVAL); - assert_return(usec, -EINVAL); - assert_return(m->pid_starttime > 0, -ESRCH); - - *usec = m->pid_starttime; - return 0; -} - -_public_ int sd_bus_message_get_selinux_context(sd_bus_message *m, const char **ret) { - assert_return(m, -EINVAL); - assert_return(m->label, -ESRCH); - - *ret = m->label; - return 0; -} - _public_ int sd_bus_message_get_monotonic_timestamp(sd_bus_message *m, uint64_t *usec) { assert_return(m, -EINVAL); assert_return(usec, -EINVAL); - assert_return(m->monotonic > 0, -ESRCH); + assert_return(m->monotonic > 0, -ENODATA); *usec = m->monotonic; return 0; @@ -876,166 +821,19 @@ _public_ int sd_bus_message_get_monotonic_timestamp(sd_bus_message *m, uint64_t _public_ int sd_bus_message_get_realtime_timestamp(sd_bus_message *m, uint64_t *usec) { assert_return(m, -EINVAL); assert_return(usec, -EINVAL); - assert_return(m->realtime > 0, -ESRCH); + assert_return(m->realtime > 0, -ENODATA); *usec = m->realtime; return 0; } -_public_ int sd_bus_message_get_comm(sd_bus_message *m, const char **ret) { - assert_return(m, -EINVAL); - assert_return(ret, -EINVAL); - assert_return(m->comm, -ESRCH); - - *ret = m->comm; - return 0; -} - -_public_ int sd_bus_message_get_tid_comm(sd_bus_message *m, const char **ret) { - assert_return(m, -EINVAL); - assert_return(ret, -EINVAL); - assert_return(m->tid_comm, -ESRCH); - - *ret = m->tid_comm; - return 0; -} - -_public_ int sd_bus_message_get_exe(sd_bus_message *m, const char **ret) { - assert_return(m, -EINVAL); - assert_return(ret, -EINVAL); - assert_return(m->exe, -ESRCH); - - *ret = m->exe; - return 0; -} - -_public_ int sd_bus_message_get_cgroup(sd_bus_message *m, const char **ret) { - assert_return(m, -EINVAL); - assert_return(ret, -EINVAL); - assert_return(m->cgroup, -ESRCH); - - *ret = m->cgroup; - return 0; -} - -_public_ int sd_bus_message_get_unit(sd_bus_message *m, const char **ret) { - int r; - - assert_return(m, -EINVAL); - assert_return(ret, -EINVAL); - assert_return(m->cgroup, -ESRCH); - - if (!m->unit) { - r = cg_path_get_unit(m->cgroup, &m->unit); - if (r < 0) - return r; - } - - *ret = m->unit; - return 0; -} - -_public_ int sd_bus_message_get_user_unit(sd_bus_message *m, const char **ret) { - int r; - - assert_return(m, -EINVAL); - assert_return(ret, -EINVAL); - assert_return(m->cgroup, -ESRCH); - - if (!m->user_unit) { - r = cg_path_get_user_unit(m->cgroup, &m->user_unit); - if (r < 0) - return r; - } - - *ret = m->user_unit; - return 0; -} - -_public_ int sd_bus_message_get_session(sd_bus_message *m, const char **ret) { - int r; - - assert_return(m, -EINVAL); - assert_return(ret, -EINVAL); - assert_return(m->cgroup, -ESRCH); - - if (!m->session) { - r = cg_path_get_session(m->cgroup, &m->session); - if (r < 0) - return r; - } - - *ret = m->session; - return 0; -} - -_public_ int sd_bus_message_get_owner_uid(sd_bus_message *m, uid_t *uid) { - assert_return(m, -EINVAL); - assert_return(uid, -EINVAL); - assert_return(m->cgroup, -ESRCH); - - return cg_path_get_owner_uid(m->cgroup, uid); -} - -_public_ int sd_bus_message_get_cmdline(sd_bus_message *m, char ***cmdline) { - size_t n, i; - const char *p; - bool first; - - assert_return(m, -EINVAL); - assert_return(m->cmdline, -ESRCH); - - for (p = m->cmdline, n = 0; p < m->cmdline + m->cmdline_length; p++) - if (*p == 0) - n++; - - m->cmdline_array = new(char*, n + 1); - if (!m->cmdline_array) - return -ENOMEM; - - for (p = m->cmdline, i = 0, first = true; p < m->cmdline + m->cmdline_length; p++) { - if (first) - m->cmdline_array[i++] = (char*) p; - - first = *p == 0; - } - - m->cmdline_array[i] = NULL; - *cmdline = m->cmdline_array; - - return 0; -} - -_public_ int sd_bus_message_get_audit_sessionid(sd_bus_message *m, uint32_t *sessionid) { - assert_return(m, -EINVAL); - assert_return(sessionid, -EINVAL); - assert_return(m->audit, -ESRCH); - - *sessionid = m->audit->sessionid; - return 0; -} - -_public_ int sd_bus_message_get_audit_loginuid(sd_bus_message *m, uid_t *uid) { - assert_return(m, -EINVAL); - assert_return(uid, -EINVAL); - assert_return(m->audit, -ESRCH); - - *uid = m->audit->loginuid; - return 0; -} - -_public_ int sd_bus_message_has_effective_cap(sd_bus_message *m, int capability) { - unsigned sz; - - assert_return(m, -EINVAL); - assert_return(capability < 0, -EINVAL); - assert_return(!m->capability, -ESRCH); +_public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) { + assert_return(m, NULL); - sz = m->capability_size / 4; - if ((unsigned) capability >= sz*8) - return 0; + if (m->creds.mask == 0) + return NULL; - return !!(m->capability[2 * sz + (capability / 8)] & (1 << (capability % 8))); + return &m->creds; } _public_ int sd_bus_message_is_signal(sd_bus_message *m, diff --git a/src/libsystemd-bus/bus-message.h b/src/libsystemd-bus/bus-message.h index 8c0ba86213..72a79f792b 100644 --- a/src/libsystemd-bus/bus-message.h +++ b/src/libsystemd-bus/bus-message.h @@ -29,6 +29,7 @@ #include "sd-bus.h" #include "kdbus.h" #include "time-util.h" +#include "bus-creds.h" struct bus_container { char enclosing; @@ -78,19 +79,14 @@ struct sd_bus_message { sd_bus_error error; - uid_t uid; - gid_t gid; - pid_t pid; - pid_t tid; - usec_t pid_starttime; + sd_bus_creds creds; + usec_t monotonic; usec_t realtime; bool sealed:1; bool dont_send:1; bool allow_fds:1; - bool uid_valid:1; - bool gid_valid:1; bool free_header:1; bool free_kdbus:1; bool free_fds:1; @@ -102,8 +98,6 @@ struct sd_bus_message { struct bus_body_part *body_end; unsigned n_body_parts; - char *label; - size_t rindex; struct bus_body_part *cached_rindex_part; size_t cached_rindex_part_begin; @@ -126,24 +120,6 @@ struct sd_bus_message { char sender_buffer[3 + DECIMAL_STR_MAX(uint64_t) + 1]; char destination_buffer[3 + DECIMAL_STR_MAX(uint64_t) + 1]; - - const char *exe; - const char *comm; - const char *tid_comm; - const char *cgroup; - - const char *cmdline; - size_t cmdline_length; - char **cmdline_array; - - char *session; - char *unit; - char *user_unit; - - struct kdbus_audit *audit; - - uint8_t *capability; - size_t capability_size; }; #define BUS_MESSAGE_NEED_BSWAP(m) ((m)->header->endian != SD_BUS_NATIVE_ENDIAN) diff --git a/src/libsystemd-bus/bus-util.c b/src/libsystemd-bus/bus-util.c index 7a21975092..5069aaaaba 100644 --- a/src/libsystemd-bus/bus-util.c +++ b/src/libsystemd-bus/bus-util.c @@ -20,6 +20,7 @@ ***/ #include <sys/socket.h> +#include <sys/capability.h> #include "util.h" #include "strv.h" @@ -137,7 +138,7 @@ int bus_verify_polkit( bool *_challenge, sd_bus_error *e) { - const char *sender; + _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; uid_t uid; int r; @@ -145,11 +146,11 @@ int bus_verify_polkit( assert(m); assert(action); - sender = sd_bus_message_get_sender(m); - if (!sender) - return -EBADMSG; + r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds); + if (r < 0) + return r; - r = sd_bus_get_owner_uid(bus, sender, &uid); + r = sd_bus_creds_get_uid(creds, &uid); if (r < 0) return r; @@ -160,6 +161,11 @@ int bus_verify_polkit( else { _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; int authorized = false, challenge = false; + const char *sender; + + sender = sd_bus_message_get_sender(m); + if (!sender) + return -EBADMSG; r = sd_bus_call_method( bus, @@ -271,8 +277,9 @@ int bus_verify_polkit_async( #ifdef ENABLE_POLKIT _cleanup_bus_message_unref_ sd_bus_message *pk = NULL; AsyncPolkitQuery *q; -#endif const char *sender; +#endif + _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; uid_t uid; int r; @@ -319,17 +326,21 @@ int bus_verify_polkit_async( } #endif - sender = sd_bus_message_get_sender(m); - if (!sender) - return -EBADMSG; + r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds); + if (r < 0) + return r; - r = sd_bus_get_owner_uid(bus, sender, &uid); + r = sd_bus_creds_get_uid(creds, &uid); if (r < 0) return r; if (uid == 0) return 1; + #ifdef ENABLE_POLKIT + sender = sd_bus_message_get_sender(m); + if (!sender) + return -EBADMSG; r = hashmap_ensure_allocated(registry, trivial_hash_func, trivial_compare_func); if (r < 0) diff --git a/src/libsystemd-bus/bus-util.h b/src/libsystemd-bus/bus-util.h index 38d468edad..9d4923794d 100644 --- a/src/libsystemd-bus/bus-util.h +++ b/src/libsystemd-bus/bus-util.h @@ -137,9 +137,11 @@ int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u); DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus*, sd_bus_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message*, sd_bus_message_unref); +DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_creds*, sd_bus_creds_unref); #define _cleanup_bus_unref_ _cleanup_(sd_bus_unrefp) #define _cleanup_bus_message_unref_ _cleanup_(sd_bus_message_unrefp) +#define _cleanup_bus_creds_unref_ _cleanup_(sd_bus_creds_unrefp) #define _cleanup_bus_error_free_ _cleanup_(sd_bus_error_free) #define BUS_DEFINE_PROPERTY_GET_ENUM(function, name, type) \ diff --git a/src/libsystemd-bus/busctl.c b/src/libsystemd-bus/busctl.c index 4204adb5bc..24db48a7e6 100644 --- a/src/libsystemd-bus/busctl.c +++ b/src/libsystemd-bus/busctl.c @@ -75,41 +75,47 @@ static int list_bus_names(sd_bus *bus, char **argv) { (int) max_i, "NAME", 10, "PID", 15, "PROCESS", 16, "USER", 20, "CONNECTION"); STRV_FOREACH(i, l) { + _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; _cleanup_free_ char *owner = NULL; sd_id128_t mid; - pid_t pid; - uid_t uid; if (arg_no_unique && (*i)[0] == ':') continue; printf("%-*s", (int) max_i, *i); - r = sd_bus_get_owner_pid(bus, *i, &pid); + r = sd_bus_get_owner_creds(bus, *i, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM, &creds); if (r >= 0) { - _cleanup_free_ char *comm = NULL; + pid_t pid; + uid_t uid; - printf(" %10lu", (unsigned long) pid); + r = sd_bus_creds_get_pid(creds, &pid); + if (r >= 0) { + const char *comm = NULL; - get_process_comm(pid, &comm); - printf(" %-15s", strna(comm)); - } else - printf(" - - "); + sd_bus_creds_get_comm(creds, &comm); - r = sd_bus_get_owner_uid(bus, *i, &uid); - if (r >= 0) { - _cleanup_free_ char *u = NULL; + printf(" %10lu %-15s", (unsigned long) pid, strna(comm)); + } else + printf(" - - "); - u = uid_to_name(uid); - if (!u) - return log_oom(); + r = sd_bus_creds_get_uid(creds, &uid); + if (r >= 0) { + _cleanup_free_ char *u = NULL; - if (strlen(u) > 16) - u[16] = 0; + u = uid_to_name(uid); + if (!u) + return log_oom(); - printf(" %-16s", u); + if (strlen(u) > 16) + u[16] = 0; + + printf(" %-16s", u); + } else + printf(" - "); } else - printf(" - "); + printf(" - - - "); + r = sd_bus_get_owner(bus, *i, &owner); if (r >= 0) diff --git a/src/libsystemd-bus/libsystemd-bus.sym b/src/libsystemd-bus/libsystemd-bus.sym index 9cf06c44dd..435c794b14 100644 --- a/src/libsystemd-bus/libsystemd-bus.sym +++ b/src/libsystemd-bus/libsystemd-bus.sym @@ -28,13 +28,6 @@ global: sd_bus_negotiate_fds; sd_bus_negotiate_attach_timestamp; sd_bus_negotiate_attach_creds; - sd_bus_negotiate_attach_comm; - sd_bus_negotiate_attach_exe; - sd_bus_negotiate_attach_cmdline; - sd_bus_negotiate_attach_cgroup; - sd_bus_negotiate_attach_caps; - sd_bus_negotiate_attach_selinux_context; - sd_bus_negotiate_attach_audit; sd_bus_start; sd_bus_close; sd_bus_ref; @@ -42,6 +35,7 @@ global: sd_bus_is_open; sd_bus_can_send; sd_bus_get_server_id; + sd_bus_get_peer_creds; sd_bus_send; sd_bus_send_to; sd_bus_get_fd; @@ -82,6 +76,7 @@ global: sd_bus_message_new_method_errnof; sd_bus_message_ref; sd_bus_message_unref; + sd_bus_message_get_bus; sd_bus_message_get_type; sd_bus_message_get_serial; sd_bus_message_get_reply_serial; @@ -95,27 +90,9 @@ global: sd_bus_message_get_sender; sd_bus_message_get_error; sd_bus_message_get_errno; - sd_bus_message_get_bus; sd_bus_message_get_monotonic_timestamp; sd_bus_message_get_realtime_timestamp; - sd_bus_message_get_uid; - sd_bus_message_get_gid; - sd_bus_message_get_pid; - sd_bus_message_get_tid; - sd_bus_message_get_pid_starttime; - sd_bus_message_get_selinux_context; - sd_bus_message_get_comm; - sd_bus_message_get_tid_comm; - sd_bus_message_get_exe; - sd_bus_message_get_cgroup; - sd_bus_message_get_cmdline; - sd_bus_message_get_unit; - sd_bus_message_get_user_unit; - sd_bus_message_get_session; - sd_bus_message_get_owner_uid; - sd_bus_message_get_audit_sessionid; - sd_bus_message_get_audit_loginuid; - sd_bus_message_has_effective_cap; + sd_bus_message_get_creds; sd_bus_message_is_signal; sd_bus_message_is_method_call; sd_bus_message_is_method_error; @@ -147,6 +124,15 @@ global: sd_bus_message_at_end; sd_bus_message_rewind; + /* Bus management */ + sd_bus_get_unique_name; + sd_bus_request_name; + sd_bus_release_name; + sd_bus_list_names; + sd_bus_get_owner; + sd_bus_get_owner_creds; + sd_bus_get_owner_machine_id; + /* Convenience calls */ sd_bus_call_method; sd_bus_get_property; @@ -166,16 +152,36 @@ global: sd_bus_emit_interfaces_added; sd_bus_emit_interfaces_removed_strv; sd_bus_emit_interfaces_removed; + sd_bus_query_sender_creds; - /* Bus management */ - sd_bus_get_unique_name; - sd_bus_request_name; - sd_bus_release_name; - sd_bus_list_names; - sd_bus_get_owner; - sd_bus_get_owner_uid; - sd_bus_get_owner_pid; - sd_bus_get_owner_machine_id; + /* Credentials */ + sd_bus_creds_new_from_pid; + sd_bus_creds_ref; + sd_bus_creds_unref; + sd_bus_creds_extend; + sd_bus_creds_get_mask; + sd_bus_creds_get_uid; + sd_bus_creds_get_gid; + sd_bus_creds_get_pid; + sd_bus_creds_get_pid_starttime; + sd_bus_creds_get_tid; + sd_bus_creds_get_comm; + sd_bus_creds_get_tid_comm; + sd_bus_creds_get_exe; + sd_bus_creds_get_cmdline; + sd_bus_creds_get_cgroup; + sd_bus_creds_get_unit; + sd_bus_creds_get_user_unit; + sd_bus_creds_get_slice; + sd_bus_creds_get_session; + sd_bus_creds_get_owner_uid; + sd_bus_creds_has_effective_cap; + sd_bus_creds_has_permitted_cap; + sd_bus_creds_has_inheritable_cap; + sd_bus_creds_has_bounding_cap; + sd_bus_creds_get_selinux_context; + sd_bus_creds_get_audit_session_id; + sd_bus_creds_get_audit_login_uid; /* Error structures */ sd_bus_error_free; diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c index 49a2abc73b..97a8c683bb 100644 --- a/src/libsystemd-bus/sd-bus.c +++ b/src/libsystemd-bus/sd-bus.c @@ -283,75 +283,38 @@ _public_ int sd_bus_negotiate_attach_timestamp(sd_bus *bus, int b) { return 0; } -_public_ int sd_bus_negotiate_attach_creds(sd_bus *bus, int b) { +_public_ int sd_bus_negotiate_attach_creds(sd_bus *bus, uint64_t mask) { assert_return(bus, -EINVAL); + assert_return(mask <= _SD_BUS_CREDS_MAX, -EINVAL); assert_return(bus->state == BUS_UNSET, -EPERM); assert_return(!bus_pid_changed(bus), -ECHILD); - SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CREDS, b); - return 0; -} + SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CREDS, + !!(mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID))); -_public_ int sd_bus_negotiate_attach_comm(sd_bus *bus, int b) { - assert_return(bus, -EINVAL); - assert_return(bus->state == BUS_UNSET, -EPERM); - assert_return(!bus_pid_changed(bus), -ECHILD); + SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_COMM, + !!(mask & (SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM))); - SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_COMM, b); - return 0; -} + SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_EXE, + !!(mask & SD_BUS_CREDS_EXE)); -_public_ int sd_bus_negotiate_attach_exe(sd_bus *bus, int b) { - assert_return(bus, -EINVAL); - assert_return(bus->state == BUS_UNSET, -EPERM); - assert_return(!bus_pid_changed(bus), -ECHILD); + SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CMDLINE, + !!(mask & SD_BUS_CREDS_CMDLINE)); - SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_EXE, b); - return 0; -} + SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CGROUP, + !!(mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID))); -_public_ int sd_bus_negotiate_attach_cmdline(sd_bus *bus, int b) { - assert_return(bus, -EINVAL); - assert_return(bus->state == BUS_UNSET, -EPERM); - assert_return(!bus_pid_changed(bus), -ECHILD); + SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CAPS, + !!(mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS))); - SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CMDLINE, b); - return 0; -} + SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_SECLABEL, + !!(mask & SD_BUS_CREDS_SELINUX_CONTEXT)); -_public_ int sd_bus_negotiate_attach_cgroup(sd_bus *bus, int b) { - assert_return(bus, -EINVAL); - assert_return(bus->state == BUS_UNSET, -EPERM); - assert_return(!bus_pid_changed(bus), -ECHILD); - - SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CGROUP, b); - return 0; -} - -_public_ int sd_bus_negotiate_attach_caps(sd_bus *bus, int b) { - assert_return(bus, -EINVAL); - assert_return(bus->state == BUS_UNSET, -EPERM); - assert_return(!bus_pid_changed(bus), -ECHILD); - - SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CAPS, b); - return 0; -} + SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_AUDIT, + !!(mask & (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID))); -_public_ int sd_bus_negotiate_attach_selinux_context(sd_bus *bus, int b) { - assert_return(bus, -EINVAL); - assert_return(bus->state == BUS_UNSET, -EPERM); - assert_return(!bus_pid_changed(bus), -ECHILD); + bus->creds_mask = mask; - SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_SECLABEL, b); - return 0; -} - -_public_ int sd_bus_negotiate_attach_audit(sd_bus *bus, int b) { - assert_return(bus, -EINVAL); - assert_return(bus->state == BUS_UNSET, -EPERM); - assert_return(!bus_pid_changed(bus), -ECHILD); - - SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_AUDIT, b); return 0; } @@ -2812,3 +2775,48 @@ _public_ char *sd_bus_label_unescape(const char *f) { return r; } + +_public_ int sd_bus_get_peer_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) { + sd_bus_creds *c; + pid_t pid = 0; + int r; + + assert_return(bus, -EINVAL); + assert_return(mask <= _SD_BUS_CREDS_MAX, -ENOTSUP); + assert_return(ret, -EINVAL); + assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN); + assert_return(!bus_pid_changed(bus), -ECHILD); + assert_return(!bus->is_kernel, -ENOTSUP); + + if (!bus->ucred_valid && !isempty(bus->label)) + return -ENODATA; + + c = bus_creds_new(); + if (!c) + return -ENOMEM; + + if (bus->ucred_valid) { + pid = c->pid = bus->ucred.pid; + c->uid = bus->ucred.uid; + c->gid = bus->ucred.gid; + + c->mask |= ((SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_GID) & mask) & bus->creds_mask; + } + + if (!isempty(bus->label) && (mask & SD_BUS_CREDS_SELINUX_CONTEXT)) { + c->label = strdup(bus->label); + if (!c->label) { + sd_bus_creds_unref(c); + return -ENOMEM; + } + + c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT | bus->creds_mask; + } + + r = bus_creds_add_more(c, mask, pid, 0); + if (r < 0) + return r; + + *ret = c; + return 0; +} diff --git a/src/libsystemd-bus/test-bus-chat.c b/src/libsystemd-bus/test-bus-chat.c index 66a5df9b57..021379f0b0 100644 --- a/src/libsystemd-bus/test-bus-chat.c +++ b/src/libsystemd-bus/test-bus-chat.c @@ -158,8 +158,8 @@ static int server(sd_bus *bus) { if (!m) continue; - sd_bus_message_get_pid(m, &pid); - sd_bus_message_get_selinux_context(m, &label); + sd_bus_creds_get_pid(sd_bus_message_get_creds(m), &pid); + sd_bus_creds_get_selinux_context(sd_bus_message_get_creds(m), &label); log_info("Got message! member=%s pid=%lu label=%s", strna(sd_bus_message_get_member(m)), (unsigned long) pid, diff --git a/src/libsystemd-bus/test-bus-creds.c b/src/libsystemd-bus/test-bus-creds.c new file mode 100644 index 0000000000..0a9b2ca466 --- /dev/null +++ b/src/libsystemd-bus/test-bus-creds.c @@ -0,0 +1,46 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2013 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include "sd-bus.h" +#include "bus-dump.h" +#include "bus-util.h" +#include "util.h" + +int main(int argc, char *argv[]) { + _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + int r; + + r = sd_bus_creds_new_from_pid(0, _SD_BUS_CREDS_MAX, &creds); + assert_se(r >= 0); + + bus_creds_dump(creds, NULL); + + creds = sd_bus_creds_unref(creds); + + r = sd_bus_creds_new_from_pid(1, _SD_BUS_CREDS_MAX, &creds); + if (r != -EACCES) { + assert_se(r >= 0); + putchar('\n'); + bus_creds_dump(creds, NULL); + } + + return 0; +} diff --git a/src/libsystemd-bus/test-bus-kernel.c b/src/libsystemd-bus/test-bus-kernel.c index 44d2fa7247..f970ca5ca4 100644 --- a/src/libsystemd-bus/test-bus-kernel.c +++ b/src/libsystemd-bus/test-bus-kernel.c @@ -63,24 +63,10 @@ int main(int argc, char *argv[]) { assert_se(r >= 0); assert_se(sd_bus_negotiate_attach_timestamp(a, 1) >= 0); - assert_se(sd_bus_negotiate_attach_creds(a, 1) >= 0); - assert_se(sd_bus_negotiate_attach_comm(a, 1) >= 0); - assert_se(sd_bus_negotiate_attach_exe(a, 1) >= 0); - assert_se(sd_bus_negotiate_attach_cmdline(a, 1) >= 0); - assert_se(sd_bus_negotiate_attach_cgroup(a, 1) >= 0); - assert_se(sd_bus_negotiate_attach_caps(a, 1) >= 0); - assert_se(sd_bus_negotiate_attach_selinux_context(a, 1) >= 0); - assert_se(sd_bus_negotiate_attach_audit(a, 1) >= 0); + assert_se(sd_bus_negotiate_attach_creds(a, _SD_BUS_CREDS_MAX) >= 0); assert_se(sd_bus_negotiate_attach_timestamp(b, 1) >= 0); - assert_se(sd_bus_negotiate_attach_creds(b, 1) >= 0); - assert_se(sd_bus_negotiate_attach_comm(b, 1) >= 0); - assert_se(sd_bus_negotiate_attach_exe(b, 1) >= 0); - assert_se(sd_bus_negotiate_attach_cmdline(b, 1) >= 0); - assert_se(sd_bus_negotiate_attach_cgroup(b, 1) >= 0); - assert_se(sd_bus_negotiate_attach_caps(b, 1) >= 0); - assert_se(sd_bus_negotiate_attach_selinux_context(b, 1) >= 0); - assert_se(sd_bus_negotiate_attach_audit(b, 1) >= 0); + assert_se(sd_bus_negotiate_attach_creds(b, _SD_BUS_CREDS_MAX) >= 0); r = sd_bus_start(a); assert_se(r >= 0); |