diff options
Diffstat (limited to 'src/libsystemd/sd-bus')
44 files changed, 1136 insertions, 505 deletions
diff --git a/src/libsystemd/sd-bus/bus-bloom.h b/src/libsystemd/sd-bus/bus-bloom.h index 96c82d7e8f..a9350d7f51 100644 --- a/src/libsystemd/sd-bus/bus-bloom.h +++ b/src/libsystemd/sd-bus/bus-bloom.h @@ -23,7 +23,6 @@ #include <stdbool.h> #include <stdint.h> -#include <sys/types.h> /* * Our default bloom filter has the following parameters: diff --git a/src/libsystemd/sd-bus/bus-common-errors.c b/src/libsystemd/sd-bus/bus-common-errors.c index eb60ca3628..52f8dfd3be 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.c +++ b/src/libsystemd/sd-bus/bus-common-errors.c @@ -35,9 +35,9 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = { SD_BUS_ERROR_MAP(BUS_ERROR_NOT_SUBSCRIBED, EINVAL), SD_BUS_ERROR_MAP(BUS_ERROR_ALREADY_SUBSCRIBED, EINVAL), SD_BUS_ERROR_MAP(BUS_ERROR_ONLY_BY_DEPENDENCY, EINVAL), - SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_JOBS_CONFLICTING, EDEADLOCK), - SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC, EDEADLOCK), - SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE, EDEADLOCK), + SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_JOBS_CONFLICTING, EDEADLK), + SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC, EDEADLK), + SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE, EDEADLK), SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_MASKED, EBADR), SD_BUS_ERROR_MAP(BUS_ERROR_JOB_TYPE_NOT_APPLICABLE, EBADR), SD_BUS_ERROR_MAP(BUS_ERROR_NO_ISOLATION, EPERM), @@ -60,7 +60,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = { SD_BUS_ERROR_MAP(BUS_ERROR_DEVICE_IS_TAKEN, EINVAL), SD_BUS_ERROR_MAP(BUS_ERROR_DEVICE_NOT_TAKEN, EINVAL), SD_BUS_ERROR_MAP(BUS_ERROR_OPERATION_IN_PROGRESS, EINPROGRESS), - SD_BUS_ERROR_MAP(BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, ENOTSUP), + SD_BUS_ERROR_MAP(BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, EOPNOTSUPP), SD_BUS_ERROR_MAP(BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, EALREADY), @@ -70,7 +70,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = { SD_BUS_ERROR_MAP(BUS_ERROR_INVALID_REPLY, EINVAL), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_RR, ENOENT), SD_BUS_ERROR_MAP(BUS_ERROR_NO_RESOURCES, ENOMEM), - SD_BUS_ERROR_MAP(BUS_ERROR_CNAME_LOOP, EDEADLOCK), + SD_BUS_ERROR_MAP(BUS_ERROR_CNAME_LOOP, EDEADLK), SD_BUS_ERROR_MAP(BUS_ERROR_ABORTED, ECANCELED), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_TRANSFER, ENXIO), diff --git a/src/libsystemd/sd-bus/bus-common-errors.h b/src/libsystemd/sd-bus/bus-common-errors.h index e935833bc3..b17b62ac93 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.h +++ b/src/libsystemd/sd-bus/bus-common-errors.h @@ -21,7 +21,6 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include "sd-bus.h" #include "bus-error.h" #define BUS_ERROR_NO_SUCH_UNIT "org.freedesktop.systemd1.NoSuchUnit" diff --git a/src/libsystemd/sd-bus/bus-container.c b/src/libsystemd/sd-bus/bus-container.c index d29b98a269..f157c25bba 100644 --- a/src/libsystemd/sd-bus/bus-container.c +++ b/src/libsystemd/sd-bus/bus-container.c @@ -23,7 +23,7 @@ #include <fcntl.h> #include "util.h" -#include "fileio.h" +#include "process-util.h" #include "bus-internal.h" #include "bus-socket.h" #include "bus-container.h" diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c index 06e5b4fd9a..43ddfc651d 100644 --- a/src/libsystemd/sd-bus/bus-control.c +++ b/src/libsystemd/sd-bus/bus-control.c @@ -34,7 +34,6 @@ #include "bus-bloom.h" #include "bus-util.h" #include "capability.h" -#include "cgroup-util.h" _public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) { int r; @@ -43,6 +42,9 @@ _public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) { assert_return(unique, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); + if (!bus->bus_client) + return -EINVAL; + r = bus_ensure_running(bus); if (r < 0) return r; @@ -77,7 +79,7 @@ static int bus_request_name_kernel(sd_bus *bus, const char *name, uint64_t flags if (r < 0) return -errno; - if (n->flags & KDBUS_NAME_IN_QUEUE) + if (n->return_flags & KDBUS_NAME_IN_QUEUE) return 0; return 1; @@ -131,12 +133,14 @@ static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) _public_ int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags) { assert_return(bus, -EINVAL); assert_return(name, -EINVAL); - assert_return(bus->bus_client, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL); assert_return(service_name_is_valid(name), -EINVAL); assert_return(name[0] != ':', -EINVAL); + if (!bus->bus_client) + return -EINVAL; + /* Don't allow requesting the special driver and local names */ if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local")) return -EINVAL; @@ -214,11 +218,13 @@ static int bus_release_name_dbus1(sd_bus *bus, const char *name) { _public_ int sd_bus_release_name(sd_bus *bus, const char *name) { assert_return(bus, -EINVAL); assert_return(name, -EINVAL); - assert_return(bus->bus_client, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); assert_return(service_name_is_valid(name), -EINVAL); assert_return(name[0] != ':', -EINVAL); + if (!bus->bus_client) + return -EINVAL; + /* Don't allow releasing the special driver and local names */ if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local")) return -EINVAL; @@ -375,6 +381,9 @@ _public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatabl assert_return(acquired || activatable, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); + if (!bus->bus_client) + return -EINVAL; + if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; @@ -414,6 +423,26 @@ static int bus_populate_creds_from_items( c->mask |= SD_BUS_CREDS_TID; } + 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 distinguish 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; case KDBUS_ITEM_CREDS: @@ -551,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; } @@ -584,16 +613,17 @@ static int bus_populate_creds_from_items( case KDBUS_ITEM_AUXGROUPS: if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) { - size_t n; + size_t i, n; uid_t *g; - assert_cc(sizeof(gid_t) == sizeof(uint32_t)); - - n = (item->size - offsetof(struct kdbus_item, data32)) / sizeof(uint32_t); - g = newdup(gid_t, item->data32, n); + n = (item->size - offsetof(struct kdbus_item, data64)) / sizeof(uint64_t); + g = new(gid_t, n); if (!g) return -ENOMEM; + for (i = 0; i < n; i++) + g[i] = item->data64[i]; + free(c->supplementary_gids); c->supplementary_gids = g; c->n_supplementary_gids = n; @@ -622,7 +652,7 @@ int bus_get_name_creds_kdbus( int r; if (streq(name, "org.freedesktop.DBus")) - return -ENOTSUP; + return -EOPNOTSUPP; r = bus_kernel_parse_unique_name(name, &id); if (r < 0) @@ -644,7 +674,8 @@ int bus_get_name_creds_kdbus( * the bits we want, then ask for the PID/TID so that we * can read the rest from /proc. */ if ((mask & SD_BUS_CREDS_AUGMENT) && - (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID| + (mask & (SD_BUS_CREDS_PPID| + SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID| SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID| SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE| 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| @@ -654,7 +685,7 @@ int bus_get_name_creds_kdbus( mask |= SD_BUS_CREDS_PID; cmd->size = size; - cmd->flags = attach_flags_to_kdbus(mask); + cmd->attach_flags = attach_flags_to_kdbus(mask); r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd); if (r < 0) @@ -875,11 +906,13 @@ _public_ int sd_bus_get_name_creds( assert_return(bus, -EINVAL); assert_return(name, -EINVAL); - assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -ENOTSUP); + assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP); assert_return(mask == 0 || creds, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); assert_return(service_name_is_valid(name), -EINVAL); - assert_return(bus->bus_client, -ENODATA); + + if (!bus->bus_client) + return -EINVAL; if (streq(name, "org.freedesktop.DBus.Local")) return -EINVAL; @@ -910,7 +943,8 @@ static int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds ** * to get the bits we want, then ask for the PID/TID so that we * can read the rest from /proc. */ if ((mask & SD_BUS_CREDS_AUGMENT) && - (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID| + (mask & (SD_BUS_CREDS_PPID| + SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID| SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID| SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE| 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| @@ -919,7 +953,7 @@ static int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds ** SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID))) mask |= SD_BUS_CREDS_PID; - cmd.flags = attach_flags_to_kdbus(mask); + cmd.attach_flags = attach_flags_to_kdbus(mask); r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd); if (r < 0) @@ -989,7 +1023,7 @@ static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds ** _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) { assert_return(bus, -EINVAL); - assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -ENOTSUP); + assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP); assert_return(ret, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); @@ -1393,6 +1427,9 @@ int bus_add_match_internal( assert(bus); + if (!bus->bus_client) + return -EINVAL; + if (bus->is_kernel) return bus_add_match_internal_kernel(bus, components, n_components, cookie); else @@ -1452,6 +1489,9 @@ int bus_remove_match_internal( assert(bus); + if (!bus->bus_client) + return -EINVAL; + if (bus->is_kernel) return bus_remove_match_internal_kernel(bus, cookie); else @@ -1469,6 +1509,9 @@ _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_ assert_return(!bus_pid_changed(bus), -ECHILD); assert_return(service_name_is_valid(name), -EINVAL); + if (!bus->bus_client) + return -EINVAL; + if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; diff --git a/src/libsystemd/sd-bus/bus-convenience.c b/src/libsystemd/sd-bus/bus-convenience.c index a6317e9785..28bc8d2818 100644 --- a/src/libsystemd/sd-bus/bus-convenience.c +++ b/src/libsystemd/sd-bus/bus-convenience.c @@ -462,11 +462,22 @@ _public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_b /* 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 */ + * to get it from the sender or peer. */ if (call->sender) + /* There's a sender, but the creds are + * missing. This means we are talking via + * dbus1, or are getting a message that was + * sent to us via kdbus, but was converted + * from a dbus1 message by the bus-proxy and + * thus also lacks the creds. */ return sd_bus_get_name_creds(call->bus, call->sender, mask, creds); else + /* There's no sender, hence we are on a dbus1 + * direct connection. For direct connections + * the credentials of the AF_UNIX peer matter, + * which may be queried via + * sd_bus_get_owner_creds(). */ return sd_bus_get_owner_creds(call->bus, mask, creds); } @@ -488,10 +499,18 @@ _public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) return -ENOTCONN; if (capability >= 0) { + r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS, &creds); if (r < 0) return r; + /* We cannot use augmented caps for authorization, + * since then data is acquired raceful from + * /proc. This can never actually happen, but let's + * better be safe than sorry, and do an extra check + * here. */ + assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EFFECTIVE_CAPS) == 0, -EPERM); + /* Note that not even on kdbus we might have the caps * field, due to faked identities, or namespace * translation issues. */ @@ -512,6 +531,13 @@ _public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) if (our_uid != 0 || !know_caps || capability < 0) { uid_t sender_uid; + /* We cannot use augmented uid/euid for authorization, + * since then data is acquired raceful from + * /proc. This can never actually happen, but let's + * better be safe than sorry, and do an extra check + * here. */ + assert_return((sd_bus_creds_get_augmented_mask(creds) & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID)) == 0, -EPERM); + /* Try to use the EUID, if we have it. */ r = sd_bus_creds_get_euid(creds, &sender_uid); if (r < 0) diff --git a/src/libsystemd/sd-bus/bus-creds.c b/src/libsystemd/sd-bus/bus-creds.c index ea8a619c5a..4d67619cf8 100644 --- a/src/libsystemd/sd-bus/bus-creds.c +++ b/src/libsystemd/sd-bus/bus-creds.c @@ -23,13 +23,15 @@ #include <linux/capability.h> #include "util.h" +#include "formats-util.h" +#include "process-util.h" +#include "terminal-util.h" #include "capability.h" #include "cgroup-util.h" #include "fileio.h" #include "audit.h" #include "bus-message.h" #include "bus-util.h" -#include "time-util.h" #include "strv.h" #include "bus-creds.h" #include "bus-label.h" @@ -51,7 +53,10 @@ void bus_creds_done(sd_bus_creds *c) { free(c->unit); free(c->user_unit); free(c->slice); + free(c->user_slice); free(c->unescaped_description); + free(c->supplementary_gids); + free(c->tty); free(c->well_known_names); /* note that this is an strv, but * we only free the array, not the @@ -101,7 +106,9 @@ _public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) { free(c->unique_name); free(c->cgroup_root); free(c->description); + free(c->supplementary_gids); + c->supplementary_gids = NULL; strv_free(c->well_known_names); c->well_known_names = NULL; @@ -127,6 +134,12 @@ _public_ uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c) { return c->mask; } +_public_ uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c) { + assert_return(c, 0); + + return c->augmented; +} + sd_bus_creds* bus_creds_new(void) { sd_bus_creds *c; @@ -144,7 +157,7 @@ _public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t m int r; assert_return(pid >= 0, -EINVAL); - assert_return(mask <= _SD_BUS_CREDS_ALL, -ENOTSUP); + assert_return(mask <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP); assert_return(ret, -EINVAL); if (pid == 0) @@ -227,7 +240,6 @@ _public_ int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) { return 0; } - _public_ int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid) { assert_return(c, -EINVAL); assert_return(egid, -EINVAL); @@ -284,6 +296,23 @@ _public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) { return 0; } +_public_ int sd_bus_creds_get_ppid(sd_bus_creds *c, pid_t *ppid) { + assert_return(c, -EINVAL); + assert_return(ppid, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_PPID)) + return -ENODATA; + + /* PID 1 has no parent process. Let's distinguish 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; +} + _public_ int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid) { assert_return(c, -EINVAL); assert_return(tid, -EINVAL); @@ -338,7 +367,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; } @@ -436,6 +467,33 @@ _public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) { return 0; } +_public_ int sd_bus_creds_get_user_slice(sd_bus_creds *c, const char **ret) { + int r; + + assert_return(c, -EINVAL); + assert_return(ret, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_USER_SLICE)) + return -ENODATA; + + assert(c->cgroup); + + if (!c->user_slice) { + const char *shifted; + + r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted); + if (r < 0) + return r; + + r = cg_path_get_user_slice(shifted, (char**) &c->user_slice); + if (r < 0) + return r; + } + + *ret = c->user_slice; + return 0; +} + _public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) { int r; @@ -488,8 +546,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); @@ -508,6 +566,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; } @@ -519,10 +580,27 @@ _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; } +_public_ int sd_bus_creds_get_tty(sd_bus_creds *c, const char **ret) { + assert_return(c, -EINVAL); + assert_return(ret, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_TTY)) + return -ENODATA; + + if (!c->tty) + return -ENXIO; + + *ret = c->tty; + return 0; +} + _public_ int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **unique_name) { assert_return(c, -EINVAL); assert_return(unique_name, -EINVAL); @@ -593,10 +671,11 @@ static int has_cap(sd_bus_creds *c, unsigned offset, int capability) { assert(capability >= 0); assert(c->capability); - sz = DIV_ROUND_UP(cap_last_cap(), 32U); - if ((unsigned)capability > cap_last_cap()) + if ((unsigned) capability > cap_last_cap()) return 0; + sz = DIV_ROUND_UP(cap_last_cap(), 32U); + return !!(c->capability[offset * sz + CAP_TO_INDEX(capability)] & CAP_TO_MASK(capability)); } @@ -693,32 +772,33 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) { if (!(mask & SD_BUS_CREDS_AUGMENT)) return 0; - 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 (pid > 0) { - c->pid = pid; - c->mask |= SD_BUS_CREDS_PID; - } + /* Try to retrieve TID from creds if it wasn't passed to us */ + if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID)) + tid = c->tid; + + /* Calculate what we shall and can add */ + missing = mask & ~(c->mask|SD_BUS_CREDS_PID|SD_BUS_CREDS_TID|SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_DESCRIPTION|SD_BUS_CREDS_AUGMENT); + if (missing == 0) + return 0; + + c->pid = pid; + c->mask |= SD_BUS_CREDS_PID; if (tid > 0) { c->tid = tid; c->mask |= SD_BUS_CREDS_TID; } - if (missing & (SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID | + if (missing & (SD_BUS_CREDS_PPID | + SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID | SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID | SD_BUS_CREDS_SUPPLEMENTARY_GIDS | SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS | @@ -741,6 +821,25 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) { FOREACH_LINE(line, f, return -errno) { truncate_nl(line); + if (missing & SD_BUS_CREDS_PPID) { + p = startswith(line, "PPid:"); + if (p) { + p += strspn(p, WHITESPACE); + + /* Explicitly check for PPID 0 (which is the case for PID 1) */ + if (!streq(p, "0")) { + r = parse_pid(p, &c->ppid); + if (r < 0) + return r; + + } else + c->ppid = 0; + + c->mask |= SD_BUS_CREDS_PPID; + continue; + } + } + if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) { p = startswith(line, "Uid:"); if (p) { @@ -750,10 +849,15 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) { if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4) return -EIO; - c->uid = (uid_t) uid; - c->euid = (uid_t) euid; - c->suid = (uid_t) suid; - c->fsuid = (uid_t) fsuid; + if (missing & SD_BUS_CREDS_UID) + c->uid = (uid_t) uid; + if (missing & SD_BUS_CREDS_EUID) + c->euid = (uid_t) euid; + if (missing & SD_BUS_CREDS_SUID) + c->suid = (uid_t) suid; + if (missing & SD_BUS_CREDS_FSUID) + c->fsuid = (uid_t) fsuid; + c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID); continue; } @@ -768,10 +872,15 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) { if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4) return -EIO; - c->gid = (gid_t) gid; - c->egid = (gid_t) egid; - c->sgid = (gid_t) sgid; - c->fsgid = (gid_t) fsgid; + if (missing & SD_BUS_CREDS_GID) + c->gid = (gid_t) gid; + if (missing & SD_BUS_CREDS_EGID) + c->egid = (gid_t) egid; + if (missing & SD_BUS_CREDS_SGID) + c->sgid = (gid_t) sgid; + if (missing & SD_BUS_CREDS_FSGID) + c->fsgid = (gid_t) fsgid; + c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID); continue; } @@ -879,7 +988,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 distinguish + * 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 @@ -891,17 +1010,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; } } @@ -912,34 +1032,43 @@ 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 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)) { + if (missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID)) { - r = cg_pid_get_path(NULL, pid, &c->cgroup); - if (r < 0) { - if (r != -EPERM && r != -EACCES) - return r; - } else { + if (!c->cgroup) { + r = cg_pid_get_path(NULL, pid, &c->cgroup); + if (r < 0) { + if (r != -EPERM && r != -EACCES) + return r; + } + } + + if (!c->cgroup_root) { r = cg_get_root_path(&c->cgroup_root); 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 (c->cgroup) + c->mask |= missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_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) { - if (r != -ENOTSUP && 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; @@ -947,13 +1076,43 @@ 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 != -ENOTSUP && 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; } + if (missing & SD_BUS_CREDS_TTY) { + r = get_ctty(pid, NULL, &c->tty); + 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 + * distinguish 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; } @@ -978,6 +1137,21 @@ int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) /* Copy the original data over */ + 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_PPID) { + n->ppid = c->ppid; + n->mask |= SD_BUS_CREDS_PPID; + } + if (c->mask & mask & SD_BUS_CREDS_UID) { n->uid = c->uid; n->mask |= SD_BUS_CREDS_UID; @@ -1019,24 +1193,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; - n->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS; - } - - if (c->mask & mask & SD_BUS_CREDS_PID) { - n->pid = c->pid; - n->mask |= SD_BUS_CREDS_PID; - } + 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; + } - if (c->mask & mask & SD_BUS_CREDS_TID) { - n->tid = c->tid; - n->mask |= SD_BUS_CREDS_TID; + 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; @@ -1045,6 +1217,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; @@ -1053,23 +1227,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)) { + 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_USER_SLICE|SD_BUS_CREDS_OWNER_UID)) { + assert(c->cgroup); + n->cgroup = strdup(c->cgroup); if (!n->cgroup) return -ENOMEM; @@ -1078,10 +1263,12 @@ int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) if (!n->cgroup_root) 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); + 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_USER_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)) { + assert(c->capability); + n->capability = memdup(c->capability, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4); if (!n->capability) return -ENOMEM; @@ -1090,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_SELINUX_CONTEXT) { + assert(c->label); + n->label = strdup(c->label); if (!n->label) return -ENOMEM; @@ -1105,7 +1294,19 @@ int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID; } + if (c->mask & mask & SD_BUS_CREDS_TTY) { + if (c->tty) { + n->tty = strdup(c->tty); + if (!n->tty) + return -ENOMEM; + } else + n->tty = NULL; + n->mask |= SD_BUS_CREDS_TTY; + } + 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; @@ -1113,24 +1314,31 @@ 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; n->mask |= SD_BUS_CREDS_DESCRIPTION; } + n->augmented = c->augmented & n->mask; + /* 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); + r = bus_creds_add_more(n, mask, 0, 0); if (r < 0) return r; diff --git a/src/libsystemd/sd-bus/bus-creds.h b/src/libsystemd/sd-bus/bus-creds.h index 3b337efa32..209d216123 100644 --- a/src/libsystemd/sd-bus/bus-creds.h +++ b/src/libsystemd/sd-bus/bus-creds.h @@ -24,12 +24,13 @@ #include <stdbool.h> #include "sd-bus.h" -#include "time-util.h" struct sd_bus_creds { bool allocated; unsigned n_ref; + uint64_t mask; + uint64_t augmented; uid_t uid; uid_t euid; @@ -43,6 +44,7 @@ struct sd_bus_creds { gid_t *supplementary_gids; unsigned n_supplementary_gids; + pid_t ppid; pid_t pid; pid_t tid; @@ -59,6 +61,9 @@ struct sd_bus_creds { char *unit; char *user_unit; char *slice; + char *user_slice; + + char *tty; uint32_t *capability; diff --git a/src/libsystemd/sd-bus/bus-dump.c b/src/libsystemd/sd-bus/bus-dump.c index 7181639645..9db86adb7f 100644 --- a/src/libsystemd/sd-bus/bus-dump.c +++ b/src/libsystemd/sd-bus/bus-dump.c @@ -22,9 +22,10 @@ #include "util.h" #include "capability.h" #include "strv.h" -#include "audit.h" #include "macro.h" #include "cap-list.h" +#include "formats-util.h" +#include "terminal-util.h" #include "bus-message.h" #include "bus-internal.h" @@ -330,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, z; assert(c); @@ -361,8 +360,16 @@ 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) { + 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); - if (terse && ((c->mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_TID)))) + if (terse && ((c->mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_TID|SD_BUS_CREDS_PPID|SD_BUS_CREDS_TTY)))) fputs("\n", f); if (c->mask & SD_BUS_CREDS_UID) @@ -404,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); @@ -421,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); @@ -433,32 +442,42 @@ 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; + v = sd_bus_creds_get_slice(c, &s); + if (v != -ENODATA) + fprintf(f, "%sSlice=%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; + w = sd_bus_creds_get_user_slice(c, &s); + if (w != -ENODATA) + fprintf(f, "%sUserSlice=%s%s%s", prefix, color, strna(s), suffix); + s = NULL; + z = sd_bus_creds_get_session(c, &s); + if (z != -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 || z != -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-error.c b/src/libsystemd/sd-bus/bus-error.c index 3bf0c5d3e4..dac157be16 100644 --- a/src/libsystemd/sd-bus/bus-error.c +++ b/src/libsystemd/sd-bus/bus-error.c @@ -40,7 +40,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_standard_errors[] = { SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NoReply", ETIMEDOUT), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.IOError", EIO), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.BadAddress", EADDRNOTAVAIL), - SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NotSupported", ENOTSUP), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NotSupported", EOPNOTSUPP), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.LimitsExceeded", ENOBUFS), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.AccessDenied", EACCES), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.AuthFailed", EACCES), @@ -168,7 +168,7 @@ static sd_bus_error errno_to_bus_error_const(int error) { case ECONNRESET: return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_DISCONNECTED, "Disconnected"); - case ENOTSUP: + case EOPNOTSUPP: return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NOT_SUPPORTED, "Not supported"); case EADDRNOTAVAIL: diff --git a/src/libsystemd/sd-bus/bus-gvariant.c b/src/libsystemd/sd-bus/bus-gvariant.c index 02b95cd136..2d18a4e6c1 100644 --- a/src/libsystemd/sd-bus/bus-gvariant.c +++ b/src/libsystemd/sd-bus/bus-gvariant.c @@ -19,7 +19,6 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include "util.h" #include "bus-type.h" #include "bus-gvariant.h" #include "bus-signature.h" diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h index e9f1a816aa..1351938c80 100644 --- a/src/libsystemd/sd-bus/bus-internal.h +++ b/src/libsystemd/sd-bus/bus-internal.h @@ -22,8 +22,6 @@ ***/ #include <sys/socket.h> -#include <sys/un.h> -#include <netinet/in.h> #include <pthread.h> #include "hashmap.h" @@ -211,6 +209,7 @@ struct sd_bus { bool manual_peer_interface:1; bool is_system:1; bool is_user:1; + bool allow_interactive_authorization:1; int use_memfd; diff --git a/src/libsystemd/sd-bus/bus-introspect.c b/src/libsystemd/sd-bus/bus-introspect.c index d528ab2a04..e2f4550c7e 100644 --- a/src/libsystemd/sd-bus/bus-introspect.c +++ b/src/libsystemd/sd-bus/bus-introspect.c @@ -20,7 +20,6 @@ ***/ #include "util.h" -#include "sd-bus-protocol.h" #include "bus-introspect.h" #include "bus-signature.h" #include "bus-internal.h" diff --git a/src/libsystemd/sd-bus/bus-introspect.h b/src/libsystemd/sd-bus/bus-introspect.h index 98312d123b..1914e6cb8b 100644 --- a/src/libsystemd/sd-bus/bus-introspect.h +++ b/src/libsystemd/sd-bus/bus-introspect.h @@ -21,7 +21,6 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <sys/types.h> #include <stdio.h> #include "sd-bus.h" diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c index e90ee449d9..417e4d5903 100644 --- a/src/libsystemd/sd-bus/bus-kernel.c +++ b/src/libsystemd/sd-bus/bus-kernel.c @@ -38,8 +38,8 @@ #include "strv.h" #include "memfd-util.h" #include "capability.h" -#include "cgroup-util.h" #include "fileio.h" +#include "formats-util.h" #include "bus-internal.h" #include "bus-message.h" @@ -595,6 +595,14 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { m->creds.mask |= SD_BUS_CREDS_TID & bus->creds_mask; } + 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; case KDBUS_ITEM_CREDS: @@ -681,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: @@ -749,10 +753,21 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { case KDBUS_ITEM_AUXGROUPS: if (bus->creds_mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) { - assert_cc(sizeof(gid_t) == sizeof(uint32_t)); + size_t i, n; + gid_t *g; + + n = (d->size - offsetof(struct kdbus_item, data64)) / sizeof(uint64_t); + g = new(gid_t, n); + if (!g) { + r = -ENOMEM; + goto fail; + } - m->creds.n_supplementary_gids = (d->size - offsetof(struct kdbus_item, data32)) / sizeof(uint32_t); - m->creds.supplementary_gids = (gid_t*) d->data32; + for (i = 0; i < n; i++) + g[i] = d->data64[i]; + + m->creds.supplementary_gids = g; + m->creds.n_supplementary_gids = n; m->creds.mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS; } @@ -841,9 +856,8 @@ fail: int bus_kernel_take_fd(sd_bus *b) { struct kdbus_bloom_parameter *bloom = NULL; + struct kdbus_item *items, *item; struct kdbus_cmd_hello *hello; - struct kdbus_item_list *items; - struct kdbus_item *item; _cleanup_free_ char *g = NULL; const char *name; size_t l = 0, m = 0, sz; @@ -948,8 +962,16 @@ int bus_kernel_take_fd(sd_bus *b) { } r = ioctl(b->input_fd, KDBUS_CMD_HELLO, hello); - if (r < 0) + if (r < 0) { + if (errno == ENOTTY) + /* If the ioctl is not supported we assume that the + * API version changed in a major incompatible way, + * let's indicate an API incompatibility in this + * case. */ + return -ESOCKTNOSUPPORT; + return -errno; + } if (!b->kdbus_buffer) { b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, b->input_fd, 0); @@ -963,13 +985,13 @@ int bus_kernel_take_fd(sd_bus *b) { /* The higher 32bit of the bus_flags fields are considered * 'incompatible flags'. Refuse them all for now. */ if (hello->bus_flags > 0xFFFFFFFFULL) { - r = -ENOTSUP; + r = -ESOCKTNOSUPPORT; goto fail; } /* extract bloom parameters from items */ items = (void*)((uint8_t*)b->kdbus_buffer + hello->offset); - KDBUS_ITEM_FOREACH(item, items, items) { + KDBUS_FOREACH(item, items, hello->items_size) { switch (item->type) { case KDBUS_ITEM_BLOOM_PARAMETER: bloom = &item->bloom_parameter; @@ -978,7 +1000,7 @@ int bus_kernel_take_fd(sd_bus *b) { } if (!bloom || !bloom_validate_parameters((size_t) bloom->size, (unsigned) bloom->n_hash)) { - r = -ENOTSUP; + r = -EOPNOTSUPP; goto fail; } @@ -1345,15 +1367,12 @@ int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority) { } r = ioctl(bus->input_fd, KDBUS_CMD_RECV, &recv); + if (recv.return_flags & KDBUS_RECV_RETURN_DROPPED_MSGS) + log_debug("%s: kdbus reports %" PRIu64 " dropped broadcast messages, ignoring.", strna(bus->description), (uint64_t) recv.dropped_msgs); if (r < 0) { if (errno == EAGAIN) return 0; - if (errno == EOVERFLOW) { - log_debug("%s: kdbus reports %" PRIu64 " dropped broadcast messages, ignoring.", strna(bus->description), (uint64_t) recv.dropped_msgs); - return 0; - } - return -errno; } @@ -1389,7 +1408,7 @@ int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *al assert(allocated); if (!bus || !bus->is_kernel) - return -ENOTSUP; + return -EOPNOTSUPP; assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0); @@ -1499,7 +1518,7 @@ uint64_t attach_flags_to_kdbus(uint64_t mask) { SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) m |= KDBUS_ATTACH_CREDS; - if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_TID)) + if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_TID|SD_BUS_CREDS_PPID)) m |= KDBUS_ATTACH_PIDS; if (mask & SD_BUS_CREDS_COMM) @@ -1574,7 +1593,7 @@ int bus_kernel_create_bus(const char *name, bool world, char **s) { make->size += ALIGN8(n->size); - /* The busses we create make no restrictions on what metadata + /* The buses we create make no restrictions on what metadata * peers can read from incoming messages. */ n = KDBUS_ITEM_NEXT(n); n->type = KDBUS_ITEM_ATTACH_FLAGS_RECV; @@ -1600,6 +1619,11 @@ int bus_kernel_create_bus(const char *name, bool world, char **s) { if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) { safe_close(fd); + + /* Major API change? then the ioctls got shuffled around. */ + if (errno == ENOTTY) + return -ESOCKTNOSUPPORT; + return -errno; } @@ -1746,32 +1770,6 @@ int bus_kernel_realize_attach_flags(sd_bus *bus) { return 0; } -int bus_kernel_fix_attach_mask(void) { - _cleanup_free_ char *mask = NULL; - uint64_t m = (uint64_t) -1; - char buf[2+16+2]; - int r; - - /* By default we don't want any kdbus metadata fields to be - * suppressed, hence we reset the kernel mask for it to - * (uint64_t) -1. If the module argument was overwritten by - * the kernel cmdline, we leave it as is. */ - - r = get_proc_cmdline_key("kdbus.attach_flags_mask=", &mask); - if (r < 0) - return log_warning_errno(r, "Failed to read kernel command line: %m"); - - if (r == 0) { - sprintf(buf, "0x%" PRIx64 "\n", m); - r = write_string_file("/sys/module/kdbus/parameters/attach_flags_mask", buf); - if (r < 0) - return log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r, - "Failed to write kdbus attach mask: %m"); - } - - return 0; -} - int bus_kernel_get_bus_name(sd_bus *bus, char **name) { struct kdbus_cmd_info cmd = { .size = sizeof(struct kdbus_cmd_info), diff --git a/src/libsystemd/sd-bus/bus-kernel.h b/src/libsystemd/sd-bus/bus-kernel.h index b9f31ba790..bb4dff6d82 100644 --- a/src/libsystemd/sd-bus/bus-kernel.h +++ b/src/libsystemd/sd-bus/bus-kernel.h @@ -90,8 +90,6 @@ int bus_kernel_drop_one(int fd); int bus_kernel_realize_attach_flags(sd_bus *bus); -int bus_kernel_fix_attach_mask(void); - int bus_kernel_get_bus_name(sd_bus *bus, char **name); int bus_kernel_cmd_free(sd_bus *bus, uint64_t offset); diff --git a/src/libsystemd/sd-bus/bus-match.c b/src/libsystemd/sd-bus/bus-match.c index 162f0ab608..7c5264fad4 100644 --- a/src/libsystemd/sd-bus/bus-match.c +++ b/src/libsystemd/sd-bus/bus-match.c @@ -22,7 +22,6 @@ #include "bus-internal.h" #include "bus-message.h" #include "bus-match.h" -#include "bus-error.h" #include "bus-util.h" #include "strv.h" @@ -329,7 +328,7 @@ int bus_match_run( bus->current_handler = node->leaf.callback->callback; bus->current_userdata = slot->userdata; } - r = node->leaf.callback->callback(bus, m, slot->userdata, &error_buffer); + r = node->leaf.callback->callback(m, slot->userdata, &error_buffer); if (bus) { bus->current_userdata = NULL; bus->current_handler = NULL; diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c index 2959303033..6ee209dd1b 100644 --- a/src/libsystemd/sd-bus/bus-message.c +++ b/src/libsystemd/sd-bus/bus-message.c @@ -27,7 +27,6 @@ #include "utf8.h" #include "strv.h" #include "time-util.h" -#include "cgroup-util.h" #include "memfd-util.h" #include "sd-bus.h" @@ -421,7 +420,7 @@ static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) { else { /* 64bit cookies are not supported on dbus1 */ if (cookie > 0xffffffffUL) - return -ENOTSUP; + return -EOPNOTSUPP; return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie); } @@ -441,7 +440,7 @@ int bus_message_from_header( size_t extra, sd_bus_message **ret) { - sd_bus_message *m; + _cleanup_free_ sd_bus_message *m = NULL; struct bus_header *h; size_t a, label_sz; @@ -460,15 +459,13 @@ int bus_message_from_header( return -EBADMSG; h = header; - if (h->version != 1 && - h->version != 2) + if (!IN_SET(h->version, 1, 2)) return -EBADMSG; if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID) return -EBADMSG; - if (h->endian != BUS_LITTLE_ENDIAN && - h->endian != BUS_BIG_ENDIAN) + if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN)) return -EBADMSG; /* Note that we are happy with unknown flags in the flags header! */ @@ -557,6 +554,7 @@ int bus_message_from_header( m->bus = sd_bus_ref(bus); *ret = m; + m = NULL; return 0; } @@ -634,6 +632,9 @@ static sd_bus_message *message_new(sd_bus *bus, uint8_t type) { m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m); m->bus = sd_bus_ref(bus); + if (bus->allow_interactive_authorization) + m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION; + return m; } @@ -749,7 +750,7 @@ static int message_new_reply( t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED; t->reply_cookie = BUS_MESSAGE_COOKIE(call); if (t->reply_cookie == 0) - return -ENOTSUP; + return -EOPNOTSUPP; r = message_append_reply_cookie(t, t->reply_cookie); if (r < 0) @@ -1462,7 +1463,7 @@ static int message_push_fd(sd_bus_message *m, int fd) { return -EINVAL; if (!m->allow_fds) - return -ENOTSUP; + return -EOPNOTSUPP; copy = fcntl(fd, F_DUPFD_CLOEXEC, 3); if (copy < 0) @@ -2941,7 +2942,7 @@ int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) { if (cookie > 0xffffffffULL && !BUS_MESSAGE_IS_GVARIANT(m)) - return -ENOTSUP; + return -EOPNOTSUPP; /* In vtables the return signature of method calls is listed, * let's check if they match if this is a response */ @@ -3488,8 +3489,6 @@ _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) { return r; } else { - rindex = m->rindex; - if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) { uint32_t l; bool ok; @@ -4797,7 +4796,7 @@ _public_ int sd_bus_message_read_array( assert_return(bus_type_is_trivial(type), -EINVAL); assert_return(ptr, -EINVAL); assert_return(size, -EINVAL); - assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP); + assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP); r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type)); if (r <= 0) @@ -5508,7 +5507,7 @@ int bus_message_parse_fields(sd_bus_message *m) { /* Try to read the error message, but if we can't it's a non-issue */ if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR) - sd_bus_message_read(m, "s", &m->error.message); + (void) sd_bus_message_read(m, "s", &m->error.message); return 0; } @@ -5551,6 +5550,7 @@ int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) { } int bus_message_read_strv_extend(sd_bus_message *m, char ***l) { + const char *s; int r; assert(m); @@ -5560,19 +5560,13 @@ int bus_message_read_strv_extend(sd_bus_message *m, char ***l) { if (r <= 0) return r; - for (;;) { - const char *s; - - r = sd_bus_message_read_basic(m, 's', &s); - if (r < 0) - return r; - if (r == 0) - break; - + while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) { r = strv_extend(l, s); if (r < 0) return r; } + if (r < 0) + return r; r = sd_bus_message_exit_container(m); if (r < 0) diff --git a/src/libsystemd/sd-bus/bus-message.h b/src/libsystemd/sd-bus/bus-message.h index 32955329b4..d784e603dd 100644 --- a/src/libsystemd/sd-bus/bus-message.h +++ b/src/libsystemd/sd-bus/bus-message.h @@ -27,7 +27,6 @@ #include "macro.h" #include "sd-bus.h" -#include "kdbus.h" #include "time-util.h" #include "bus-creds.h" #include "bus-protocol.h" diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c index fc6c223283..e4bbd880e5 100644 --- a/src/libsystemd/sd-bus/bus-objects.c +++ b/src/libsystemd/sd-bus/bus-objects.c @@ -277,7 +277,7 @@ static int node_callbacks_run( bus->current_slot = sd_bus_slot_ref(slot); bus->current_handler = c->callback; bus->current_userdata = slot->userdata; - r = c->callback(bus, m, slot->userdata, &error_buffer); + r = c->callback(m, slot->userdata, &error_buffer); bus->current_userdata = NULL; bus->current_handler = NULL; bus->current_slot = sd_bus_slot_unref(slot); @@ -395,7 +395,7 @@ static int method_callbacks_run( bus->current_slot = sd_bus_slot_ref(slot); bus->current_handler = c->vtable->x.method.handler; bus->current_userdata = u; - r = c->vtable->x.method.handler(bus, m, u, &error); + r = c->vtable->x.method.handler(m, u, &error); bus->current_userdata = NULL; bus->current_handler = NULL; bus->current_slot = sd_bus_slot_unref(slot); diff --git a/src/libsystemd/sd-bus/bus-signature.h b/src/libsystemd/sd-bus/bus-signature.h index 2e06e30548..c4fed0b53d 100644 --- a/src/libsystemd/sd-bus/bus-signature.h +++ b/src/libsystemd/sd-bus/bus-signature.h @@ -22,7 +22,6 @@ ***/ #include <stdbool.h> -#include <sys/types.h> bool signature_is_single(const char *s, bool allow_dict_entry); bool signature_is_pair(const char *s); diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c index 52883fa8cd..4fffc6581d 100644 --- a/src/libsystemd/sd-bus/bus-socket.c +++ b/src/libsystemd/sd-bus/bus-socket.c @@ -20,18 +20,17 @@ ***/ #include <endian.h> -#include <assert.h> #include <stdlib.h> #include <unistd.h> #include <poll.h> -#include <byteswap.h> +#include "sd-daemon.h" #include "util.h" #include "macro.h" #include "missing.h" -#include "strv.h" #include "utf8.h" -#include "sd-daemon.h" +#include "formats-util.h" +#include "signal-util.h" #include "sd-bus.h" #include "bus-socket.h" @@ -179,7 +178,7 @@ static int bus_socket_auth_verify_client(sd_bus *b) { /* We expect two response lines: "OK" and possibly * "AGREE_UNIX_FD" */ - e = memmem(b->rbuffer, b->rbuffer_size, "\r\n", 2); + e = memmem_safe(b->rbuffer, b->rbuffer_size, "\r\n", 2); if (!e) return 0; @@ -494,7 +493,7 @@ static int bus_socket_auth_verify(sd_bus *b) { static int bus_socket_read_auth(sd_bus *b) { struct msghdr mh; - struct iovec iov; + struct iovec iov = {}; size_t n; ssize_t k; int r; @@ -529,7 +528,6 @@ static int bus_socket_read_auth(sd_bus *b) { b->rbuffer = p; - zero(iov); iov.iov_base = (uint8_t*) b->rbuffer + b->rbuffer_size; iov.iov_len = n - b->rbuffer_size; @@ -609,10 +607,10 @@ void bus_socket_setup(sd_bus *b) { /* Enable SO_PASSCRED + SO_PASSEC. We try this on any * socket, just in case. */ enable = !b->bus_client; - (void)setsockopt(b->input_fd, SOL_SOCKET, SO_PASSCRED, &enable, sizeof(enable)); + (void) setsockopt(b->input_fd, SOL_SOCKET, SO_PASSCRED, &enable, sizeof(enable)); enable = !b->bus_client && (b->attach_flags & KDBUS_ATTACH_SECLABEL); - (void)setsockopt(b->input_fd, SOL_SOCKET, SO_PASSSEC, &enable, sizeof(enable)); + (void) setsockopt(b->input_fd, SOL_SOCKET, SO_PASSSEC, &enable, sizeof(enable)); /* Increase the buffers to 8 MB */ fd_inc_rcvbuf(b->input_fd, SNDBUF_SIZE); @@ -810,23 +808,21 @@ int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) { if (bus->prefer_writev) k = writev(bus->output_fd, iov, m->n_iovec); else { - struct msghdr mh; - zero(mh); + struct msghdr mh = { + .msg_iov = iov, + .msg_iovlen = m->n_iovec, + }; if (m->n_fds > 0) { struct cmsghdr *control; - control = alloca(CMSG_SPACE(sizeof(int) * m->n_fds)); - mh.msg_control = control; + mh.msg_control = control = alloca(CMSG_SPACE(sizeof(int) * m->n_fds)); + mh.msg_controllen = control->cmsg_len = CMSG_LEN(sizeof(int) * m->n_fds); control->cmsg_level = SOL_SOCKET; control->cmsg_type = SCM_RIGHTS; - mh.msg_controllen = control->cmsg_len = CMSG_LEN(sizeof(int) * m->n_fds); memcpy(CMSG_DATA(control), m->fds, sizeof(int) * m->n_fds); } - mh.msg_iov = iov; - mh.msg_iovlen = m->n_iovec; - k = sendmsg(bus->output_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL); if (k < 0 && errno == ENOTSOCK) { bus->prefer_writev = true; @@ -917,8 +913,8 @@ static int bus_socket_make_message(sd_bus *bus, size_t size) { r = bus_message_from_malloc(bus, bus->rbuffer, size, bus->fds, bus->n_fds, - !bus->bus_client && bus->ucred_valid ? &bus->ucred : NULL, - !bus->bus_client && bus->label[0] ? bus->label : NULL, + NULL, + NULL, &t); if (r < 0) { free(b); @@ -938,7 +934,7 @@ static int bus_socket_make_message(sd_bus *bus, size_t size) { int bus_socket_read_message(sd_bus *bus) { struct msghdr mh; - struct iovec iov; + struct iovec iov = {}; ssize_t k; size_t need; int r; @@ -968,7 +964,6 @@ int bus_socket_read_message(sd_bus *bus) { bus->rbuffer = b; - zero(iov); iov.iov_base = (uint8_t*) bus->rbuffer + bus->rbuffer_size; iov.iov_len = need - bus->rbuffer_size; diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c index 6be8310bbe..ec9340f8e1 100644 --- a/src/libsystemd/sd-bus/bus-track.c +++ b/src/libsystemd/sd-bus/bus-track.c @@ -20,7 +20,6 @@ ***/ #include "sd-bus.h" -#include "set.h" #include "bus-util.h" #include "bus-internal.h" #include "bus-track.h" @@ -91,6 +90,9 @@ _public_ int sd_bus_track_new( assert_return(bus, -EINVAL); assert_return(track, -EINVAL); + if (!bus->bus_client) + return -EINVAL; + t = new0(sd_bus_track, 1); if (!t) return -ENOMEM; @@ -140,12 +142,11 @@ _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) { return NULL; } -static int on_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) { +static int on_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) { sd_bus_track *track = userdata; const char *name, *old, *new; int r; - assert(bus); assert(message); assert(track); diff --git a/src/libsystemd/sd-bus/bus-type.c b/src/libsystemd/sd-bus/bus-type.c index b7914d15d3..6bc7b880a6 100644 --- a/src/libsystemd/sd-bus/bus-type.c +++ b/src/libsystemd/sd-bus/bus-type.c @@ -19,7 +19,6 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include "util.h" #include "bus-type.h" bool bus_type_is_valid(char c) { diff --git a/src/libsystemd/sd-bus/bus-type.h b/src/libsystemd/sd-bus/bus-type.h index 0e507839ca..581574ab73 100644 --- a/src/libsystemd/sd-bus/bus-type.h +++ b/src/libsystemd/sd-bus/bus-type.h @@ -25,7 +25,6 @@ #include "macro.h" #include "sd-bus.h" -#include "sd-bus-protocol.h" bool bus_type_is_valid(char c) _const_; bool bus_type_is_valid_in_signature(char c) _const_; diff --git a/src/libsystemd/sd-bus/bus-util.c b/src/libsystemd/sd-bus/bus-util.c index 52d4ebe611..99937799b3 100644 --- a/src/libsystemd/sd-bus/bus-util.c +++ b/src/libsystemd/sd-bus/bus-util.c @@ -30,21 +30,23 @@ #include "path-util.h" #include "missing.h" #include "set.h" +#include "signal-util.h" +#include "unit-name.h" #include "sd-bus.h" #include "bus-error.h" +#include "bus-label.h" #include "bus-message.h" #include "bus-util.h" #include "bus-internal.h" -static int name_owner_change_callback(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { +static int name_owner_change_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { sd_event *e = userdata; - assert(bus); assert(m); assert(e); - sd_bus_close(bus); + sd_bus_close(sd_bus_message_get_bus(m)); sd_event_exit(e, 0); return 1; @@ -132,7 +134,7 @@ int bus_event_loop_with_idle( /* Fallback for dbus1 connections: we * unregister the name and wait for the * response to come through for it */ - if (r == -ENOTSUP) { + if (r == -EOPNOTSUPP) { /* Inform the service manager that we * are going down, so that it will @@ -190,11 +192,35 @@ int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) { return has_owner; } -int bus_verify_polkit( +static int check_good_user(sd_bus_message *m, uid_t good_user) { + _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + uid_t sender_uid; + int r; + + assert(m); + + if (good_user == UID_INVALID) + return 0; + + r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_EUID, &creds); + if (r < 0) + return r; + + /* Don't trust augmented credentials for authorization */ + assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EUID) == 0, -EPERM); + + r = sd_bus_creds_get_euid(creds, &sender_uid); + if (r < 0) + return r; + + return sender_uid == good_user; +} + +int bus_test_polkit( sd_bus_message *call, int capability, const char *action, - bool interactive, + uid_t good_user, bool *_challenge, sd_bus_error *e) { @@ -203,6 +229,12 @@ int bus_verify_polkit( assert(call); assert(action); + /* Tests non-interactively! */ + + r = check_good_user(call, good_user); + if (r != 0) + return r; + r = sd_bus_query_sender_privilege(call, capability); if (r < 0) return r; @@ -211,19 +243,13 @@ int bus_verify_polkit( #ifdef ENABLE_POLKIT else { _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; - int authorized = false, challenge = false, c; + int authorized = false, challenge = false; const char *sender; sender = sd_bus_message_get_sender(call); if (!sender) return -EBADMSG; - c = sd_bus_message_get_allow_interactive_authorization(call); - if (c < 0) - return c; - if (c > 0) - interactive = true; - r = sd_bus_call_method( call->bus, "org.freedesktop.PolicyKit1", @@ -236,7 +262,7 @@ int bus_verify_polkit( "system-bus-name", 1, "name", "s", sender, action, 0, - !!interactive, + 0, ""); if (r < 0) { @@ -296,12 +322,11 @@ static void async_polkit_query_free(AsyncPolkitQuery *q) { free(q); } -static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) { +static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) { _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL; AsyncPolkitQuery *q = userdata; int r; - assert(bus); assert(reply); assert(q); @@ -314,7 +339,7 @@ static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userd goto finish; } - r = q->callback(bus, q->request, q->userdata, &error_buffer); + r = q->callback(q->request, q->userdata, &error_buffer); r = bus_maybe_reply_error(q->request, r, &error_buffer); finish: @@ -330,6 +355,7 @@ int bus_verify_polkit_async( int capability, const char *action, bool interactive, + uid_t good_user, Hashmap **registry, sd_bus_error *error) { @@ -347,6 +373,10 @@ int bus_verify_polkit_async( assert(action); assert(registry); + r = check_good_user(call, good_user); + if (r != 0) + return r; + #ifdef ENABLE_POLKIT q = hashmap_get(*registry, call); if (q) { @@ -691,6 +721,18 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) { return 1; } + case SD_BUS_TYPE_INT64: { + int64_t i; + + r = sd_bus_message_read_basic(property, type, &i); + if (r < 0) + return r; + + printf("%s=%lld\n", name, (long long) i); + + return 1; + } + case SD_BUS_TYPE_UINT32: { uint32_t u; @@ -920,7 +962,6 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_ switch (type) { case SD_BUS_TYPE_STRING: { const char *s; - char *str; char **p = userdata; r = sd_bus_message_read_basic(m, type, &s); @@ -930,14 +971,7 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_ if (isempty(s)) break; - str = strdup(s); - if (!str) { - r = -ENOMEM; - break; - } - free(*p); - *p = str; - + r = free_and_strdup(p, s); break; } @@ -1002,14 +1036,14 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_ return r; } -int bus_message_map_all_properties(sd_bus *bus, - sd_bus_message *m, - const struct bus_properties_map *map, - void *userdata) { +int bus_message_map_all_properties( + sd_bus_message *m, + const struct bus_properties_map *map, + void *userdata) { + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; int r; - assert(bus); assert(m); assert(map); @@ -1045,9 +1079,9 @@ int bus_message_map_all_properties(sd_bus *bus, v = (uint8_t *)userdata + prop->offset; if (map[i].set) - r = prop->set(bus, member, m, &error, v); + r = prop->set(sd_bus_message_get_bus(m), member, m, &error, v); else - r = map_basic(bus, member, m, &error, v); + r = map_basic(sd_bus_message_get_bus(m), member, m, &error, v); if (r < 0) return r; @@ -1064,22 +1098,24 @@ int bus_message_map_all_properties(sd_bus *bus, if (r < 0) return r; } + if (r < 0) + return r; return sd_bus_message_exit_container(m); } -int bus_message_map_properties_changed(sd_bus *bus, - sd_bus_message *m, - const struct bus_properties_map *map, - void *userdata) { +int bus_message_map_properties_changed( + sd_bus_message *m, + const struct bus_properties_map *map, + void *userdata) { + const char *member; int r, invalidated, i; - assert(bus); assert(m); assert(map); - r = bus_message_map_all_properties(bus, m, map, userdata); + r = bus_message_map_all_properties(m, map, userdata); if (r < 0) return r; @@ -1094,6 +1130,8 @@ int bus_message_map_properties_changed(sd_bus *bus, ++invalidated; break; } + if (r < 0) + return r; r = sd_bus_message_exit_container(m); if (r < 0) @@ -1102,11 +1140,13 @@ int bus_message_map_properties_changed(sd_bus *bus, return invalidated; } -int bus_map_all_properties(sd_bus *bus, - const char *destination, - const char *path, - const struct bus_properties_map *map, - void *userdata) { +int bus_map_all_properties( + sd_bus *bus, + const char *destination, + const char *path, + const struct bus_properties_map *map, + void *userdata) { + _cleanup_bus_message_unref_ sd_bus_message *m = NULL; _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; int r; @@ -1128,7 +1168,7 @@ int bus_map_all_properties(sd_bus *bus, if (r < 0) return r; - return bus_message_map_all_properties(bus, m, map, userdata); + return bus_message_map_all_properties(m, map, userdata); } int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) { @@ -1139,7 +1179,7 @@ int bus_open_transport(BusTransport transport, const char *host, bool user, sd_b assert(bus); assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL); - assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP); + assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP); switch (transport) { @@ -1174,7 +1214,7 @@ int bus_open_transport_systemd(BusTransport transport, const char *host, bool us assert(bus); assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL); - assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP); + assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP); switch (transport) { @@ -1565,24 +1605,22 @@ typedef struct BusWaitForJobs { sd_bus_slot *slot_disconnected; } BusWaitForJobs; -static int match_disconnected(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) { - assert(bus); +static int match_disconnected(sd_bus_message *m, void *userdata, sd_bus_error *error) { assert(m); log_error("Warning! D-Bus connection terminated."); - sd_bus_close(bus); + sd_bus_close(sd_bus_message_get_bus(m)); return 0; } -static int match_job_removed(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) { +static int match_job_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) { const char *path, *unit, *result; BusWaitForJobs *d = userdata; uint32_t id; char *found; int r; - assert(bus); assert(m); assert(d); @@ -1690,6 +1728,73 @@ static int bus_process_wait(sd_bus *bus) { } } +static int bus_job_get_service_result(BusWaitForJobs *d, char **result) { + _cleanup_free_ char *dbus_path = NULL; + + assert(d); + assert(d->name); + assert(result); + + dbus_path = unit_dbus_path_from_name(d->name); + if (!dbus_path) + return -ENOMEM; + + return sd_bus_get_property_string(d->bus, + "org.freedesktop.systemd1", + dbus_path, + "org.freedesktop.systemd1.Service", + "Result", + NULL, + result); +} + +static const struct { + const char *result, *explanation; +} explanations [] = { + { "resources", "a configured resource limit was exceeded" }, + { "timeout", "a timeout was exceeded" }, + { "exit-code", "the control process exited with error code" }, + { "signal", "a fatal signal was delivered to the control process" }, + { "core-dump", "a fatal signal was delivered causing the control process to dump core" }, + { "watchdog", "the service failed to send watchdog ping" }, + { "start-limit", "start of the service was attempted too often" } +}; + +static void log_job_error_with_service_result(const char* service, const char *result) { + _cleanup_free_ char *service_shell_quoted = NULL; + + assert(service); + + service_shell_quoted = shell_maybe_quote(service); + + if (!isempty(result)) { + unsigned i; + + for (i = 0; i < ELEMENTSOF(explanations); ++i) + if (streq(result, explanations[i].result)) + break; + + if (i < ELEMENTSOF(explanations)) { + log_error("Job for %s failed because %s. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n", + service, + explanations[i].explanation, + strna(service_shell_quoted)); + + goto finish; + } + } + + log_error("Job for %s failed. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n", + service, + strna(service_shell_quoted)); + +finish: + /* For some results maybe additional explanation is required */ + if (streq_ptr(result, "start-limit")) + log_info("To force a start use \"systemctl reset-failed %1$s\" followed by \"systemctl start %1$s\" again.", + strna(service_shell_quoted)); +} + static int check_wait_response(BusWaitForJobs *d, bool quiet) { int r = 0; @@ -1710,13 +1815,14 @@ static int check_wait_response(BusWaitForJobs *d, bool quiet) { log_error("Operation on or unit type of %s not supported on this system.", strna(d->name)); else if (!streq(d->result, "done") && !streq(d->result, "skipped")) { if (d->name) { - bool quotes; + int q; + _cleanup_free_ char *result = NULL; - quotes = chars_intersect(d->name, SHELL_NEED_QUOTES); + q = bus_job_get_service_result(d, &result); + if (q < 0) + log_debug_errno(q, "Failed to get Result property of service %s: %m", d->name); - log_error("Job for %s failed. See \"systemctl status %s%s%s\" and \"journalctl -xe\" for details.", - d->name, - quotes ? "'" : "", d->name, quotes ? "'" : ""); + log_job_error_with_service_result(d->name, result); } else log_error("Job failed. See \"journalctl -xe\" for details."); } @@ -1733,7 +1839,7 @@ static int check_wait_response(BusWaitForJobs *d, bool quiet) { else if (streq(d->result, "assert")) r = -EPROTO; else if (streq(d->result, "unsupported")) - r = -ENOTSUP; + r = -EOPNOTSUPP; else if (!streq(d->result, "done") && !streq(d->result, "skipped")) r = -EIO; @@ -1759,7 +1865,6 @@ int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet) { if (q < 0 && r == 0) r = q; - errno = 0; log_debug_errno(q, "Got result %s/%m for job %s", strna(d->result), strna(d->name)); } @@ -1785,7 +1890,17 @@ int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) { return set_put_strdup(d->jobs, path); } -int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet) { +int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet) { + int r; + + r = bus_wait_for_jobs_add(d, path); + if (r < 0) + return log_oom(); + + return bus_wait_for_jobs(d, quiet); +} + +int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes) { const char *type, *path, *source; int r; @@ -1800,6 +1915,10 @@ int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet) { else log_info("Removed symlink %s.", path); } + + r = unit_file_changes_add(changes, n_changes, streq(type, "symlink") ? UNIT_FILE_SYMLINK : UNIT_FILE_UNLINK, path, source); + if (r < 0) + return r; } if (r < 0) return bus_log_parse_error(r); @@ -1810,3 +1929,157 @@ int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet) { return 0; } + +/** + * bus_path_encode_unique() - encode unique object path + * @b: bus connection or NULL + * @prefix: object path prefix + * @sender_id: unique-name of client, or NULL + * @external_id: external ID to be chosen by client, or NULL + * @ret_path: storage for encoded object path pointer + * + * Whenever we provide a bus API that allows clients to create and manage + * server-side objects, we need to provide a unique name for these objects. If + * we let the server choose the name, we suffer from a race condition: If a + * client creates an object asynchronously, it cannot destroy that object until + * it received the method reply. It cannot know the name of the new object, + * thus, it cannot destroy it. Furthermore, it enforces a round-trip. + * + * Therefore, many APIs allow the client to choose the unique name for newly + * created objects. There're two problems to solve, though: + * 1) Object names are usually defined via dbus object paths, which are + * usually globally namespaced. Therefore, multiple clients must be able + * to choose unique object names without interference. + * 2) If multiple libraries share the same bus connection, they must be + * able to choose unique object names without interference. + * The first problem is solved easily by prefixing a name with the + * unique-bus-name of a connection. The server side must enforce this and + * reject any other name. The second problem is solved by providing unique + * suffixes from within sd-bus. + * + * This helper allows clients to create unique object-paths. It uses the + * template '/prefix/sender_id/external_id' and returns the new path in + * @ret_path (must be freed by the caller). + * If @sender_id is NULL, the unique-name of @b is used. If @external_id is + * NULL, this function allocates a unique suffix via @b (by requesting a new + * cookie). If both @sender_id and @external_id are given, @b can be passed as + * NULL. + * + * Returns: 0 on success, negative error code on failure. + */ +int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path) { + _cleanup_free_ char *sender_label = NULL, *external_label = NULL; + char external_buf[DECIMAL_STR_MAX(uint64_t)], *p; + int r; + + assert_return(b || (sender_id && external_id), -EINVAL); + assert_return(object_path_is_valid(prefix), -EINVAL); + assert_return(ret_path, -EINVAL); + + if (!sender_id) { + r = sd_bus_get_unique_name(b, &sender_id); + if (r < 0) + return r; + } + + if (!external_id) { + xsprintf(external_buf, "%"PRIu64, ++b->cookie); + external_id = external_buf; + } + + sender_label = bus_label_escape(sender_id); + if (!sender_label) + return -ENOMEM; + + external_label = bus_label_escape(external_id); + if (!external_label) + return -ENOMEM; + + p = strjoin(prefix, "/", sender_label, "/", external_label, NULL); + if (!p) + return -ENOMEM; + + *ret_path = p; + return 0; +} + +/** + * bus_path_decode_unique() - decode unique object path + * @path: object path to decode + * @prefix: object path prefix + * @ret_sender: output parameter for sender-id label + * @ret_external: output parameter for external-id label + * + * This does the reverse of bus_path_encode_unique() (see its description for + * details). Both trailing labels, sender-id and external-id, are unescaped and + * returned in the given output parameters (the caller must free them). + * + * Note that this function returns 0 if the path does not match the template + * (see bus_path_encode_unique()), 1 if it matched. + * + * Returns: Negative error code on failure, 0 if the given object path does not + * match the template (return parameters are set to NULL), 1 if it was + * parsed successfully (return parameters contain allocated labels). + */ +int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external) { + const char *p, *q; + char *sender, *external; + + assert(object_path_is_valid(path)); + assert(object_path_is_valid(prefix)); + assert(ret_sender); + assert(ret_external); + + p = object_path_startswith(path, prefix); + if (!p) { + *ret_sender = NULL; + *ret_external = NULL; + return 0; + } + + q = strchr(p, '/'); + if (!q) { + *ret_sender = NULL; + *ret_external = NULL; + return 0; + } + + sender = bus_label_unescape_n(p, q - p); + external = bus_label_unescape(q + 1); + if (!sender || !external) { + free(sender); + free(external); + return -ENOMEM; + } + + *ret_sender = sender; + *ret_external = external; + return 1; +} + +bool is_kdbus_wanted(void) { + _cleanup_free_ char *value = NULL; + int r; + + if (get_proc_cmdline_key("kdbus", NULL) <= 0) { + r = get_proc_cmdline_key("kdbus=", &value); + if (r <= 0 || parse_boolean(value) != 1) + return false; + } + + return true; +} + +bool is_kdbus_available(void) { + _cleanup_close_ int fd = -1; + struct kdbus_cmd cmd = { .size = sizeof(cmd), .flags = KDBUS_FLAG_NEGOTIATE }; + + if (!is_kdbus_wanted()) + return false; + + fd = open("/sys/fs/kdbus/control", O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY); + if (fd < 0) + return false; + + return ioctl(fd, KDBUS_CMD_BUS_MAKE, &cmd) >= 0; +} diff --git a/src/libsystemd/sd-bus/bus-util.h b/src/libsystemd/sd-bus/bus-util.h index e8a97cef9e..999a372cdd 100644 --- a/src/libsystemd/sd-bus/bus-util.h +++ b/src/libsystemd/sd-bus/bus-util.h @@ -24,8 +24,8 @@ #include "sd-event.h" #include "sd-bus.h" #include "hashmap.h" +#include "install.h" #include "time-util.h" -#include "util.h" typedef enum BusTransport { BUS_TRANSPORT_LOCAL, @@ -46,19 +46,9 @@ struct bus_properties_map { int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata); -int bus_message_map_all_properties(sd_bus *bus, - sd_bus_message *m, - const struct bus_properties_map *map, - void *userdata); -int bus_message_map_properties_changed(sd_bus *bus, - sd_bus_message *m, - const struct bus_properties_map *map, - void *userdata); -int bus_map_all_properties(sd_bus *bus, - const char *destination, - const char *path, - const struct bus_properties_map *map, - void *userdata); +int bus_message_map_all_properties(sd_bus_message *m, const struct bus_properties_map *map, void *userdata); +int bus_message_map_properties_changed(sd_bus_message *m, const struct bus_properties_map *map, void *userdata); +int bus_map_all_properties(sd_bus *bus, const char *destination, const char *path, const struct bus_properties_map *map, void *userdata); int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name); @@ -70,9 +60,9 @@ int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error); int bus_check_peercred(sd_bus *c); -int bus_verify_polkit(sd_bus_message *call, int capability, const char *action, bool interactive, bool *_challenge, sd_bus_error *e); +int bus_test_polkit(sd_bus_message *call, int capability, const char *action, uid_t good_user, bool *_challenge, sd_bus_error *e); -int bus_verify_polkit_async(sd_bus_message *call, int capability, const char *action, bool interactive, Hashmap **registry, sd_bus_error *error); +int bus_verify_polkit_async(sd_bus_message *call, int capability, const char *action, bool interactive, uid_t good_user, Hashmap **registry, sd_bus_error *error); void bus_verify_polkit_async_registry_free(Hashmap *registry); int bus_open_system_systemd(sd_bus **_bus); @@ -208,7 +198,14 @@ int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret); void bus_wait_for_jobs_free(BusWaitForJobs *d); int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path); int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet); +int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet); DEFINE_TRIVIAL_CLEANUP_FUNC(BusWaitForJobs*, bus_wait_for_jobs_free); -int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet); +int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes); + +int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path); +int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external); + +bool is_kdbus_wanted(void); +bool is_kdbus_available(void); diff --git a/src/libsystemd/sd-bus/busctl-introspect.h b/src/libsystemd/sd-bus/busctl-introspect.h index d6b4cf05a7..ea807d5973 100644 --- a/src/libsystemd/sd-bus/busctl-introspect.h +++ b/src/libsystemd/sd-bus/busctl-introspect.h @@ -21,7 +21,6 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <inttypes.h> #include <stdbool.h> typedef struct XMLIntrospectOps { diff --git a/src/libsystemd/sd-bus/busctl.c b/src/libsystemd/sd-bus/busctl.c index d3c1772019..39caa4e7d6 100644 --- a/src/libsystemd/sd-bus/busctl.c +++ b/src/libsystemd/sd-bus/busctl.c @@ -26,18 +26,17 @@ #include "log.h" #include "build.h" #include "pager.h" -#include "xml.h" #include "path-util.h" #include "set.h" #include "sd-bus.h" -#include "bus-message.h" #include "bus-internal.h" #include "bus-util.h" #include "bus-dump.h" #include "bus-signature.h" #include "bus-type.h" #include "busctl-introspect.h" +#include "terminal-util.h" static bool arg_no_pager = false; static bool arg_legend = true; diff --git a/src/libsystemd/sd-bus/kdbus.h b/src/libsystemd/sd-bus/kdbus.h index 1cc475eb1d..fc1d77dd7c 100644 --- a/src/libsystemd/sd-bus/kdbus.h +++ b/src/libsystemd/sd-bus/kdbus.h @@ -70,14 +70,14 @@ struct kdbus_notify_name_change { * KDBUS_ITEM_CREDS */ struct kdbus_creds { - __u32 uid; - __u32 euid; - __u32 suid; - __u32 fsuid; - __u32 gid; - __u32 egid; - __u32 sgid; - __u32 fsgid; + __u64 uid; + __u64 euid; + __u64 suid; + __u64 fsuid; + __u64 gid; + __u64 egid; + __u64 sgid; + __u64 fsgid; } __attribute__((__aligned__(8))); /** @@ -457,24 +457,16 @@ struct kdbus_item { } __attribute__((__aligned__(8))); /** - * struct kdbus_item_list - A list of items - * @size: The total size of the structure - * @items: Array of items - */ -struct kdbus_item_list { - __u64 size; - struct kdbus_item items[0]; -} __attribute__((__aligned__(8))); - -/** * enum kdbus_msg_flags - type of message * @KDBUS_MSG_EXPECT_REPLY: Expect a reply message, used for * method calls. The userspace-supplied * cookie identifies the message and the * respective reply carries the cookie * in cookie_reply - * @KDBUS_MSG_NO_AUTO_START: Do not start a service, if the addressed - * name is not currently active + * @KDBUS_MSG_NO_AUTO_START: Do not start a service if the addressed + * name is not currently active. This flag is + * not looked at by the kernel but only + * serves as hint for userspace implementations. * @KDBUS_MSG_SIGNAL: Treat this message as signal */ enum kdbus_msg_flags { @@ -507,9 +499,12 @@ enum kdbus_payload_type { * @cookie: Userspace-supplied cookie, for the connection * to identify its messages * @timeout_ns: The time to wait for a message reply from the peer. - * If there is no reply, a kernel-generated message + * If there is no reply, and the send command is + * executed asynchronously, a kernel-generated message * with an attached KDBUS_ITEM_REPLY_TIMEOUT item - * is sent to @src_id. The timeout is expected in + * is sent to @src_id. For synchronously executed send + * command, the value denotes the maximum time the call + * blocks to wait for a reply. The timeout is expected in * nanoseconds and as absolute CLOCK_MONOTONIC value. * @cookie_reply: A reply to the requesting message with the same * cookie. The requesting connection can match its @@ -602,9 +597,15 @@ enum kdbus_recv_flags { * @KDBUS_RECV_RETURN_INCOMPLETE_FDS: One or more file descriptors could not * be installed. These descriptors in * KDBUS_ITEM_FDS will carry the value -1. + * @KDBUS_RECV_RETURN_DROPPED_MSGS: There have been dropped messages since + * the last time a message was received. + * The 'dropped_msgs' counter contains the + * number of messages dropped pool + * overflows or other missed broadcasts. */ enum kdbus_recv_return_flags { KDBUS_RECV_RETURN_INCOMPLETE_FDS = 1ULL << 0, + KDBUS_RECV_RETURN_DROPPED_MSGS = 1ULL << 1, }; /** @@ -614,10 +615,12 @@ enum kdbus_recv_return_flags { * @return_flags: Command return flags, kernel → userspace * @priority: Minimum priority of the messages to de-queue. Lowest * values have the highest priority. - * @dropped_msgs: In case the KDBUS_CMD_RECV ioctl returns - * -EOVERFLOW, this field will contain the number of - * broadcast messages that have been lost since the - * last call. + * @dropped_msgs: In case there were any dropped messages since the last + * time a message was received, this will be set to the + * number of lost messages and + * KDBUS_RECV_RETURN_DROPPED_MSGS will be set in + * 'return_flags'. This can only happen if the ioctl + * returns 0 or EAGAIN. * @msg: Return storage for received message. * @items: Additional items for this command. * @@ -691,10 +694,10 @@ enum kdbus_hello_flags { * @id: The ID of this connection (kernel → userspace) * @pool_size: Size of the connection's buffer where the received * messages are placed - * @offset: Pool offset where additional items of type - * kdbus_item_list are stored. They contain information - * about the bus and the newly created connection. - * @items_size: Copy of item_list.size stored in @offset. + * @offset: Pool offset where items are returned to report + * additional information about the bus and the newly + * created connection. + * @items_size: Size of buffer returned in the pool slice at @offset. * @id128: Unique 128-bit ID of the bus (kernel → userspace) * @items: A list of items * @@ -772,11 +775,13 @@ struct kdbus_cmd_list { /** * struct kdbus_cmd_info - struct used for KDBUS_CMD_CONN_INFO ioctl * @size: The total size of the struct - * @flags: KDBUS_ATTACH_* flags, userspace → kernel + * @flags: Flags for this ioctl, userspace → kernel * @return_flags: Command return flags, kernel → userspace * @id: The 64-bit ID of the connection. If set to zero, passing * @name is required. kdbus will look up the name to * determine the ID in this case. + * @attach_flags: Set of attach flags to specify the set of information + * to receive, userspace → kernel * @offset: Returned offset in the caller's pool buffer where the * kdbus_info struct result is stored. The user must * use KDBUS_CMD_FREE to free the allocated memory. @@ -794,6 +799,7 @@ struct kdbus_cmd_info { __u64 flags; __u64 return_flags; __u64 id; + __u64 attach_flags; __u64 offset; __u64 info_size; struct kdbus_item items[0]; diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index cac9b65601..edc27aef87 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -20,19 +20,16 @@ ***/ #include <endian.h> -#include <assert.h> #include <stdlib.h> #include <unistd.h> #include <netdb.h> #include <poll.h> -#include <byteswap.h> #include <sys/mman.h> #include <pthread.h> #include "util.h" #include "macro.h" #include "strv.h" -#include "set.h" #include "missing.h" #include "def.h" #include "cgroup-util.h" @@ -45,8 +42,6 @@ #include "bus-socket.h" #include "bus-kernel.h" #include "bus-control.h" -#include "bus-introspect.h" -#include "bus-signature.h" #include "bus-objects.h" #include "bus-util.h" #include "bus-container.h" @@ -357,13 +352,30 @@ _public_ int sd_bus_set_description(sd_bus *bus, const char *description) { return free_and_strdup(&bus->description, description); } -static int hello_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) { +_public_ int sd_bus_set_allow_interactive_authorization(sd_bus *bus, int b) { + assert_return(bus, -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + bus->allow_interactive_authorization = !!b; + return 0; +} + +_public_ int sd_bus_get_allow_interactive_authorization(sd_bus *bus) { + assert_return(bus, -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + return bus->allow_interactive_authorization; +} + +static int hello_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) { const char *s; + sd_bus *bus; int r; + assert(reply); + bus = reply->bus; assert(bus); assert(bus->state == BUS_HELLO || bus->state == BUS_CLOSING); - assert(reply); r = sd_bus_message_get_errno(reply); if (r > 0) @@ -1513,15 +1525,27 @@ static int bus_seal_message(sd_bus *b, sd_bus_message *m, usec_t timeout) { } static int bus_remarshal_message(sd_bus *b, sd_bus_message **m) { + bool remarshal = false; + assert(b); - /* Do packet version and endianness already match? */ - if ((b->message_version == 0 || b->message_version == (*m)->header->version) && - (b->message_endian == 0 || b->message_endian == (*m)->header->endian)) - return 0; + /* wrong packet version */ + if (b->message_version != 0 && b->message_version != (*m)->header->version) + remarshal = true; + + /* wrong packet endianness */ + if (b->message_endian != 0 && b->message_endian != (*m)->header->endian) + remarshal = true; - /* No? Then remarshal! */ - return bus_message_remarshal(b, m); + /* TODO: kdbus-messages received from the kernel contain data which is + * not allowed to be passed to KDBUS_CMD_SEND. Therefore, we have to + * force remarshaling of the message. Technically, we could just + * recreate the kdbus message, but that is non-trivial as other parts of + * the message refer to m->kdbus already. This should be fixed! */ + if ((*m)->kdbus && (*m)->release_kdbus) + remarshal = true; + + return remarshal ? bus_message_remarshal(b, m) : 0; } int bus_seal_synthetic_message(sd_bus *b, sd_bus_message *m) { @@ -1671,8 +1695,11 @@ static int bus_send_internal(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie, _cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m); int r; - assert_return(bus, -EINVAL); assert_return(m, -EINVAL); + + if (!bus) + bus = m->bus; + assert_return(!bus_pid_changed(bus), -ECHILD); assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS); @@ -1684,7 +1711,7 @@ static int bus_send_internal(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie, if (r < 0) return r; if (r == 0) - return -ENOTSUP; + return -EOPNOTSUPP; } /* If the cookie number isn't kept, then we know that no reply @@ -1757,8 +1784,11 @@ _public_ int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *cookie) { _public_ int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destination, uint64_t *cookie) { int r; - assert_return(bus, -EINVAL); assert_return(m, -EINVAL); + + if (!bus) + bus = m->bus; + assert_return(!bus_pid_changed(bus), -ECHILD); if (!BUS_IS_OPEN(bus->state)) @@ -1814,11 +1844,14 @@ _public_ int sd_bus_call_async( _cleanup_bus_slot_unref_ sd_bus_slot *s = NULL; int r; - assert_return(bus, -EINVAL); assert_return(m, -EINVAL); assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL); assert_return(!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED), -EINVAL); assert_return(callback, -EINVAL); + + if (!bus) + bus = m->bus; + assert_return(!bus_pid_changed(bus), -ECHILD); assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS); @@ -1912,11 +1945,14 @@ _public_ int sd_bus_call( unsigned i; int r; - assert_return(bus, -EINVAL); assert_return(m, -EINVAL); assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL); assert_return(!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED), -EINVAL); assert_return(!bus_error_is_dirty(error), -EINVAL); + + if (!bus) + bus = m->bus; + assert_return(!bus_pid_changed(bus), -ECHILD); assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS); @@ -2171,7 +2207,7 @@ static int process_timeout(sd_bus *bus) { bus->current_slot = sd_bus_slot_ref(slot); bus->current_handler = c->callback; bus->current_userdata = slot->userdata; - r = c->callback(bus, m, slot->userdata, &error_buffer); + r = c->callback(m, slot->userdata, &error_buffer); bus->current_userdata = NULL; bus->current_handler = NULL; bus->current_slot = NULL; @@ -2274,7 +2310,7 @@ static int process_reply(sd_bus *bus, sd_bus_message *m) { bus->current_slot = sd_bus_slot_ref(slot); bus->current_handler = c->callback; bus->current_userdata = slot->userdata; - r = c->callback(bus, m, slot->userdata, &error_buffer); + r = c->callback(m, slot->userdata, &error_buffer); bus->current_userdata = NULL; bus->current_handler = NULL; bus->current_slot = NULL; @@ -2321,7 +2357,7 @@ static int process_filter(sd_bus *bus, sd_bus_message *m) { bus->current_slot = sd_bus_slot_ref(slot); bus->current_handler = l->callback; bus->current_userdata = slot->userdata; - r = l->callback(bus, m, slot->userdata, &error_buffer); + r = l->callback(m, slot->userdata, &error_buffer); bus->current_userdata = NULL; bus->current_handler = NULL; bus->current_slot = sd_bus_slot_unref(slot); @@ -2602,7 +2638,7 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) { bus->current_slot = sd_bus_slot_ref(slot); bus->current_handler = c->callback; bus->current_userdata = slot->userdata; - r = c->callback(bus, m, slot->userdata, &error_buffer); + r = c->callback(m, slot->userdata, &error_buffer); bus->current_userdata = NULL; bus->current_handler = NULL; bus->current_slot = NULL; @@ -3376,7 +3412,7 @@ _public_ int sd_bus_try_close(sd_bus *bus) { assert_return(!bus_pid_changed(bus), -ECHILD); if (!bus->is_kernel) - return -ENOTSUP; + return -EOPNOTSUPP; if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; @@ -3477,7 +3513,7 @@ _public_ int sd_bus_get_address(sd_bus *bus, const char **address) { return -ENODATA; } -int sd_bus_get_creds_mask(sd_bus *bus, uint64_t *mask) { +_public_ int sd_bus_get_creds_mask(sd_bus *bus, uint64_t *mask) { assert_return(bus, -EINVAL); assert_return(mask, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); @@ -3486,35 +3522,35 @@ int sd_bus_get_creds_mask(sd_bus *bus, uint64_t *mask) { return 0; } -int sd_bus_is_bus_client(sd_bus *bus) { +_public_ int sd_bus_is_bus_client(sd_bus *bus) { assert_return(bus, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); return bus->bus_client; } -int sd_bus_is_server(sd_bus *bus) { +_public_ int sd_bus_is_server(sd_bus *bus) { assert_return(bus, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); return bus->is_server; } -int sd_bus_is_anonymous(sd_bus *bus) { +_public_ int sd_bus_is_anonymous(sd_bus *bus) { assert_return(bus, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); return bus->anonymous_auth; } -int sd_bus_is_trusted(sd_bus *bus) { +_public_ int sd_bus_is_trusted(sd_bus *bus) { assert_return(bus, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); return bus->trusted; } -int sd_bus_is_monitor(sd_bus *bus) { +_public_ int sd_bus_is_monitor(sd_bus *bus) { assert_return(bus, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); diff --git a/src/libsystemd/sd-bus/test-bus-kernel-benchmark.c b/src/libsystemd/sd-bus/test-bus-benchmark.c index 35f87e91bd..d14110aa04 100644 --- a/src/libsystemd/sd-bus/test-bus-kernel-benchmark.c +++ b/src/libsystemd/sd-bus/test-bus-benchmark.c @@ -19,16 +19,13 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <ctype.h> #include <sys/wait.h> +#include "def.h" #include "util.h" -#include "log.h" #include "time-util.h" #include "sd-bus.h" -#include "bus-message.h" -#include "bus-error.h" #include "bus-kernel.h" #include "bus-internal.h" #include "bus-util.h" @@ -37,6 +34,12 @@ static usec_t arg_loop_usec = 100 * USEC_PER_MSEC; +typedef enum Type { + TYPE_KDBUS, + TYPE_LEGACY, + TYPE_DIRECT, +} Type; + static void server(sd_bus *b, size_t *result) { int r; @@ -60,7 +63,8 @@ static void server(sd_bus *b, size_t *result) { /* Make sure the mmap is mapped */ assert_se(sd_bus_message_read_array(m, 'y', &p, &sz) > 0); - assert_se(sd_bus_reply_method_return(m, NULL) >= 0); + r = sd_bus_reply_method_return(m, NULL); + assert_se(r >= 0); } else if (sd_bus_message_is_method_call(m, "benchmark.server", "Exit")) { uint64_t res; assert_se(sd_bus_message_read(m, "t", &res) > 0); @@ -68,16 +72,16 @@ static void server(sd_bus *b, size_t *result) { *result = res; return; - } else + } else if (!sd_bus_message_is_signal(m, NULL, NULL)) assert_not_reached("Unknown method"); } } -static void transaction(sd_bus *b, size_t sz) { +static void transaction(sd_bus *b, size_t sz, const char *server_name) { _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL; uint8_t *p; - assert_se(sd_bus_message_new_method_call(b, &m, ":1.1", "/", "benchmark.server", "Work") >= 0); + assert_se(sd_bus_message_new_method_call(b, &m, server_name, "/", "benchmark.server", "Work") >= 0); assert_se(sd_bus_message_append_array_space(m, 'y', sz, (void**) &p) >= 0); memset(p, 0x80, sz); @@ -85,7 +89,7 @@ static void transaction(sd_bus *b, size_t sz) { assert_se(sd_bus_call(b, m, 0, NULL, &reply) >= 0); } -static void client_bisect(const char *address) { +static void client_bisect(const char *address, const char *server_name) { _cleanup_bus_message_unref_ sd_bus_message *x = NULL; size_t lsize, rsize, csize; sd_bus *b; @@ -100,7 +104,8 @@ static void client_bisect(const char *address) { r = sd_bus_start(b); assert_se(r >= 0); - assert_se(sd_bus_call_method(b, ":1.1", "/", "benchmark.server", "Ping", NULL, NULL, NULL) >= 0); + r = sd_bus_call_method(b, server_name, "/", "benchmark.server", "Ping", NULL, NULL, NULL); + assert_se(r >= 0); lsize = 1; rsize = MAX_SIZE; @@ -125,7 +130,7 @@ static void client_bisect(const char *address) { t = now(CLOCK_MONOTONIC); for (n_copying = 0;; n_copying++) { - transaction(b, csize); + transaction(b, csize, server_name); if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec) break; } @@ -135,7 +140,7 @@ static void client_bisect(const char *address) { t = now(CLOCK_MONOTONIC); for (n_memfd = 0;; n_memfd++) { - transaction(b, csize); + transaction(b, csize, server_name); if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec) break; } @@ -151,14 +156,14 @@ static void client_bisect(const char *address) { } b->use_memfd = 1; - assert_se(sd_bus_message_new_method_call(b, &x, ":1.1", "/", "benchmark.server", "Exit") >= 0); + assert_se(sd_bus_message_new_method_call(b, &x, server_name, "/", "benchmark.server", "Exit") >= 0); assert_se(sd_bus_message_append(x, "t", csize) >= 0); assert_se(sd_bus_send(b, x, NULL) >= 0); sd_bus_unref(b); } -static void client_chart(const char *address) { +static void client_chart(Type type, const char *address, const char *server_name, int fd) { _cleanup_bus_message_unref_ sd_bus_message *x = NULL; size_t csize; sd_bus *b; @@ -167,15 +172,34 @@ static void client_chart(const char *address) { r = sd_bus_new(&b); assert_se(r >= 0); - r = sd_bus_set_address(b, address); - assert_se(r >= 0); + if (type == TYPE_DIRECT) { + r = sd_bus_set_fd(b, fd, fd); + assert_se(r >= 0); + } else { + r = sd_bus_set_address(b, address); + assert_se(r >= 0); + + r = sd_bus_set_bus_client(b, true); + assert_se(r >= 0); + } r = sd_bus_start(b); assert_se(r >= 0); - assert_se(sd_bus_call_method(b, ":1.1", "/", "benchmark.server", "Ping", NULL, NULL, NULL) >= 0); + r = sd_bus_call_method(b, server_name, "/", "benchmark.server", "Ping", NULL, NULL, NULL); + assert_se(r >= 0); - printf("SIZE\tCOPY\tMEMFD\n"); + switch (type) { + case TYPE_KDBUS: + printf("SIZE\tCOPY\tMEMFD\n"); + break; + case TYPE_LEGACY: + printf("SIZE\tLEGACY\n"); + break; + case TYPE_DIRECT: + printf("SIZE\tDIRECT\n"); + break; + } for (csize = 1; csize <= MAX_SIZE; csize *= 2) { usec_t t; @@ -183,22 +207,24 @@ static void client_chart(const char *address) { printf("%zu\t", csize); - b->use_memfd = 0; + if (type == TYPE_KDBUS) { + b->use_memfd = 0; - t = now(CLOCK_MONOTONIC); - for (n_copying = 0;; n_copying++) { - transaction(b, csize); - if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec) - break; - } + t = now(CLOCK_MONOTONIC); + for (n_copying = 0;; n_copying++) { + transaction(b, csize, server_name); + if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec) + break; + } - printf("%u\t", (unsigned) ((n_copying * USEC_PER_SEC) / arg_loop_usec)); + printf("%u\t", (unsigned) ((n_copying * USEC_PER_SEC) / arg_loop_usec)); - b->use_memfd = -1; + b->use_memfd = -1; + } t = now(CLOCK_MONOTONIC); for (n_memfd = 0;; n_memfd++) { - transaction(b, csize); + transaction(b, csize, server_name); if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec) break; } @@ -207,7 +233,7 @@ static void client_chart(const char *address) { } b->use_memfd = 1; - assert_se(sd_bus_message_new_method_call(b, &x, ":1.1", "/", "benchmark.server", "Exit") >= 0); + assert_se(sd_bus_message_new_method_call(b, &x, server_name, "/", "benchmark.server", "Exit") >= 0); assert_se(sd_bus_message_append(x, "t", csize) >= 0); assert_se(sd_bus_send(b, x, NULL) >= 0); @@ -219,9 +245,11 @@ int main(int argc, char *argv[]) { MODE_BISECT, MODE_CHART, } mode = MODE_BISECT; - int i; - _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL; + Type type = TYPE_KDBUS; + int i, pair[2] = { -1, -1 }; + _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL, *server_name = NULL; _cleanup_close_ int bus_ref = -1; + const char *unique; cpu_set_t cpuset; size_t result; sd_bus *b; @@ -232,33 +260,72 @@ int main(int argc, char *argv[]) { if (streq(argv[i], "chart")) { mode = MODE_CHART; continue; + } else if (streq(argv[i], "legacy")) { + type = TYPE_LEGACY; + continue; + } else if (streq(argv[i], "direct")) { + type = TYPE_DIRECT; + continue; } assert_se(parse_sec(argv[i], &arg_loop_usec) >= 0); } + assert_se(!MODE_BISECT || TYPE_KDBUS); + assert_se(arg_loop_usec > 0); - assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid()) >= 0); + if (type == TYPE_KDBUS) { + assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid()) >= 0); + + bus_ref = bus_kernel_create_bus(name, false, &bus_name); + if (bus_ref == -ENOENT) + exit(EXIT_TEST_SKIP); - bus_ref = bus_kernel_create_bus(name, false, &bus_name); - if (bus_ref == -ENOENT) - exit(EXIT_TEST_SKIP); + assert_se(bus_ref >= 0); - assert_se(bus_ref >= 0); + address = strappend("kernel:path=", bus_name); + assert_se(address); + } else if (type == TYPE_LEGACY) { + const char *e; - address = strappend("kernel:path=", bus_name); - assert_se(address); + e = secure_getenv("DBUS_SESSION_BUS_ADDRESS"); + assert_se(e); + + address = strdup(e); + assert_se(address); + } r = sd_bus_new(&b); assert_se(r >= 0); - r = sd_bus_set_address(b, address); - assert_se(r >= 0); + if (type == TYPE_DIRECT) { + assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) >= 0); + + r = sd_bus_set_fd(b, pair[0], pair[0]); + assert_se(r >= 0); + + r = sd_bus_set_server(b, true, SD_ID128_NULL); + assert_se(r >= 0); + } else { + r = sd_bus_set_address(b, address); + assert_se(r >= 0); + + r = sd_bus_set_bus_client(b, true); + assert_se(r >= 0); + } r = sd_bus_start(b); assert_se(r >= 0); + if (type != TYPE_DIRECT) { + r = sd_bus_get_unique_name(b, &unique); + assert_se(r >= 0); + + server_name = strdup(unique); + assert_se(server_name); + } + sync(); setpriority(PRIO_PROCESS, 0, -19); @@ -275,11 +342,11 @@ int main(int argc, char *argv[]) { switch (mode) { case MODE_BISECT: - client_bisect(address); + client_bisect(address, server_name); break; case MODE_CHART: - client_chart(address); + client_chart(type, address, server_name, pair[1]); break; } @@ -297,6 +364,7 @@ int main(int argc, char *argv[]) { assert_se(waitpid(pid, NULL, 0) == pid); + safe_close(pair[1]); sd_bus_unref(b); return 0; diff --git a/src/libsystemd/sd-bus/test-bus-chat.c b/src/libsystemd/sd-bus/test-bus-chat.c index 8625ee6d89..046e999008 100644 --- a/src/libsystemd/sd-bus/test-bus-chat.c +++ b/src/libsystemd/sd-bus/test-bus-chat.c @@ -27,24 +27,22 @@ #include "log.h" #include "util.h" #include "macro.h" +#include "formats-util.h" #include "sd-bus.h" -#include "bus-message.h" #include "bus-error.h" #include "bus-match.h" #include "bus-internal.h" #include "bus-util.h" -static int match_callback(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { +static int match_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { log_info("Match triggered! interface=%s member=%s", strna(sd_bus_message_get_interface(m)), strna(sd_bus_message_get_member(m))); return 0; } -static int object_callback(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { +static int object_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { int r; - assert_se(bus); - if (sd_bus_message_is_method_error(m, NULL)) return 0; @@ -264,11 +262,11 @@ fail: static void* client1(void*p) { _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; - sd_bus *bus = NULL; - sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_bus_close_unref_ sd_bus *bus = NULL; + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; const char *hello; int r; - int pp[2] = { -1, -1 }; + _cleanup_close_pair_ int pp[2] = { -1, -1 }; char x; r = sd_bus_open_user(&bus); @@ -347,18 +345,12 @@ finish: else sd_bus_send(bus, q, NULL); - sd_bus_flush(bus); - sd_bus_unref(bus); } - sd_bus_error_free(&error); - - safe_close_pair(pp); - return INT_TO_PTR(r); } -static int quit_callback(sd_bus *b, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { +static int quit_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { bool *x = userdata; log_error("Quit callback: %s", strerror(sd_bus_message_get_errno(m))); @@ -369,8 +361,8 @@ static int quit_callback(sd_bus *b, sd_bus_message *m, void *userdata, sd_bus_er static void* client2(void*p) { _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL; - sd_bus *bus = NULL; - sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_bus_close_unref_ sd_bus *bus = NULL; + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; bool quit = false; const char *mid; int r; @@ -399,8 +391,7 @@ static void* client2(void*p) { goto finish; } - sd_bus_message_unref(m); - m = NULL; + m = sd_bus_message_unref(m); r = sd_bus_message_new_signal( bus, @@ -419,8 +410,7 @@ static void* client2(void*p) { goto finish; } - sd_bus_message_unref(m); - m = NULL; + m = sd_bus_message_unref(m); r = sd_bus_message_new_method_call( bus, @@ -448,8 +438,7 @@ static void* client2(void*p) { log_info("Machine ID is %s.", mid); - sd_bus_message_unref(m); - m = NULL; + m = sd_bus_message_unref(m); r = sd_bus_message_new_method_call( bus, @@ -463,8 +452,7 @@ static void* client2(void*p) { goto finish; } - sd_bus_message_unref(reply); - reply = NULL; + reply = sd_bus_message_unref(reply); r = sd_bus_call(bus, m, 200 * USEC_PER_MSEC, &error, &reply); if (r < 0) @@ -472,8 +460,7 @@ static void* client2(void*p) { else log_info("Slow call succeed."); - sd_bus_message_unref(m); - m = NULL; + m = sd_bus_message_unref(m); r = sd_bus_message_new_method_call( bus, @@ -526,12 +513,9 @@ finish: goto finish; } - sd_bus_send(bus, q, NULL); - sd_bus_flush(bus); - sd_bus_unref(bus); + (void) sd_bus_send(bus, q, NULL); } - sd_bus_error_free(&error); return INT_TO_PTR(r); } diff --git a/src/libsystemd/sd-bus/test-bus-creds.c b/src/libsystemd/sd-bus/test-bus-creds.c index ff2602ba34..edd5033db2 100644 --- a/src/libsystemd/sd-bus/test-bus-creds.c +++ b/src/libsystemd/sd-bus/test-bus-creds.c @@ -22,7 +22,6 @@ #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; diff --git a/src/libsystemd/sd-bus/test-bus-error.c b/src/libsystemd/sd-bus/test-bus-error.c index 463fc81c75..5753c04b0e 100644 --- a/src/libsystemd/sd-bus/test-bus-error.c +++ b/src/libsystemd/sd-bus/test-bus-error.c @@ -35,11 +35,11 @@ static void test_error(void) { }; assert_se(!sd_bus_error_is_set(&error)); - assert_se(sd_bus_error_set(&error, SD_BUS_ERROR_NOT_SUPPORTED, "xxx") == -ENOTSUP); + assert_se(sd_bus_error_set(&error, SD_BUS_ERROR_NOT_SUPPORTED, "xxx") == -EOPNOTSUPP); assert_se(streq(error.name, SD_BUS_ERROR_NOT_SUPPORTED)); assert_se(streq(error.message, "xxx")); assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_NOT_SUPPORTED)); - assert_se(sd_bus_error_get_errno(&error) == ENOTSUP); + assert_se(sd_bus_error_get_errno(&error) == EOPNOTSUPP); assert_se(sd_bus_error_is_set(&error)); sd_bus_error_free(&error); diff --git a/src/libsystemd/sd-bus/test-bus-introspect.c b/src/libsystemd/sd-bus/test-bus-introspect.c index 67b6461f30..b2caa02870 100644 --- a/src/libsystemd/sd-bus/test-bus-introspect.c +++ b/src/libsystemd/sd-bus/test-bus-introspect.c @@ -19,7 +19,6 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include "util.h" #include "log.h" #include "bus-introspect.h" diff --git a/src/libsystemd/sd-bus/test-bus-kernel-bloom.c b/src/libsystemd/sd-bus/test-bus-kernel-bloom.c index 071b7e0cf9..b11c43bd7b 100644 --- a/src/libsystemd/sd-bus/test-bus-kernel-bloom.c +++ b/src/libsystemd/sd-bus/test-bus-kernel-bloom.c @@ -23,8 +23,6 @@ #include "log.h" #include "sd-bus.h" -#include "bus-message.h" -#include "bus-error.h" #include "bus-kernel.h" #include "bus-util.h" diff --git a/src/libsystemd/sd-bus/test-bus-kernel.c b/src/libsystemd/sd-bus/test-bus-kernel.c index 3aec568229..6506eaab2e 100644 --- a/src/libsystemd/sd-bus/test-bus-kernel.c +++ b/src/libsystemd/sd-bus/test-bus-kernel.c @@ -25,8 +25,6 @@ #include "log.h" #include "sd-bus.h" -#include "bus-message.h" -#include "bus-error.h" #include "bus-kernel.h" #include "bus-util.h" #include "bus-dump.h" @@ -45,8 +43,6 @@ int main(int argc, char *argv[]) { assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid()) >= 0); - bus_kernel_fix_attach_mask(); - bus_ref = bus_kernel_create_bus(name, false, &bus_name); if (bus_ref == -ENOENT) return EXIT_TEST_SKIP; @@ -119,7 +115,7 @@ int main(int argc, char *argv[]) { assert_se(r == -EBUSY); r = sd_bus_process_priority(b, -10, &m); - assert_se(r == -ENOMSG); + assert_se(r == 0); r = sd_bus_process(b, &m); assert_se(r > 0); diff --git a/src/libsystemd/sd-bus/test-bus-marshal.c b/src/libsystemd/sd-bus/test-bus-marshal.c index d95a03c221..f8ecadf499 100644 --- a/src/libsystemd/sd-bus/test-bus-marshal.c +++ b/src/libsystemd/sd-bus/test-bus-marshal.c @@ -19,9 +19,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <assert.h> #include <stdlib.h> -#include <byteswap.h> #include <math.h> #ifdef HAVE_GLIB @@ -41,6 +39,16 @@ #include "bus-dump.h" #include "bus-label.h" +static void test_bus_path_encode_unique(void) { + _cleanup_free_ char *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL; + + assert_se(bus_path_encode_unique(NULL, "/foo/bar", "some.sender", "a.suffix", &a) >= 0 && streq_ptr(a, "/foo/bar/some_2esender/a_2esuffix")); + assert_se(bus_path_decode_unique(a, "/foo/bar", &b, &c) > 0 && streq_ptr(b, "some.sender") && streq_ptr(c, "a.suffix")); + assert_se(bus_path_decode_unique(a, "/bar/foo", &d, &d) == 0 && !d); + assert_se(bus_path_decode_unique("/foo/bar/onlyOneSuffix", "/foo/bar", &d, &d) == 0 && !d); + assert_se(bus_path_decode_unique("/foo/bar/_/_", "/foo/bar", &d, &e) > 0 && streq_ptr(d, "") && streq_ptr(e, "")); +} + static void test_bus_path_encode(void) { _cleanup_free_ char *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL, *f = NULL; @@ -359,6 +367,7 @@ int main(int argc, char *argv[]) { test_bus_label_escape(); test_bus_path_encode(); + test_bus_path_encode_unique(); return 0; } diff --git a/src/libsystemd/sd-bus/test-bus-match.c b/src/libsystemd/sd-bus/test-bus-match.c index 76ca0b6bf3..40c67046da 100644 --- a/src/libsystemd/sd-bus/test-bus-match.c +++ b/src/libsystemd/sd-bus/test-bus-match.c @@ -20,7 +20,6 @@ ***/ #include "log.h" -#include "util.h" #include "macro.h" #include "bus-match.h" @@ -30,7 +29,7 @@ static bool mask[32]; -static int filter(sd_bus *b, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { +static int filter(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { log_info("Ran %u", PTR_TO_UINT(userdata)); assert_se(PTR_TO_UINT(userdata) < ELEMENTSOF(mask)); mask[PTR_TO_UINT(userdata)] = true; diff --git a/src/libsystemd/sd-bus/test-bus-objects.c b/src/libsystemd/sd-bus/test-bus-objects.c index acf67a52b3..52952603e4 100644 --- a/src/libsystemd/sd-bus/test-bus-objects.c +++ b/src/libsystemd/sd-bus/test-bus-objects.c @@ -19,11 +19,8 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <assert.h> #include <stdlib.h> #include <pthread.h> -#include <unistd.h> -#include <fcntl.h> #include "log.h" #include "util.h" @@ -44,7 +41,7 @@ struct context { uint32_t automatic_integer_property; }; -static int something_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) { +static int something_handler(sd_bus_message *m, void *userdata, sd_bus_error *error) { struct context *c = userdata; const char *s; char *n = NULL; @@ -70,7 +67,7 @@ static int something_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_ return 1; } -static int exit_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) { +static int exit_handler(sd_bus_message *m, void *userdata, sd_bus_error *error) { struct context *c = userdata; int r; @@ -132,10 +129,10 @@ static int value_handler(sd_bus *bus, const char *path, const char *interface, c return 1; } -static int notify_test(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) { +static int notify_test(sd_bus_message *m, void *userdata, sd_bus_error *error) { int r; - assert_se(sd_bus_emit_properties_changed(bus, m->path, "org.freedesktop.systemd.ValueTest", "Value", NULL) >= 0); + assert_se(sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), m->path, "org.freedesktop.systemd.ValueTest", "Value", NULL) >= 0); r = sd_bus_reply_method_return(m, NULL); assert_se(r >= 0); @@ -143,10 +140,10 @@ static int notify_test(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_er return 1; } -static int notify_test2(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) { +static int notify_test2(sd_bus_message *m, void *userdata, sd_bus_error *error) { int r; - assert_se(sd_bus_emit_properties_changed_strv(bus, m->path, "org.freedesktop.systemd.ValueTest", NULL) >= 0); + assert_se(sd_bus_emit_properties_changed_strv(sd_bus_message_get_bus(m), m->path, "org.freedesktop.systemd.ValueTest", NULL) >= 0); r = sd_bus_reply_method_return(m, NULL); assert_se(r >= 0); @@ -154,10 +151,10 @@ static int notify_test2(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_e return 1; } -static int emit_interfaces_added(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) { +static int emit_interfaces_added(sd_bus_message *m, void *userdata, sd_bus_error *error) { int r; - assert_se(sd_bus_emit_interfaces_added(bus, m->path, "org.freedesktop.systemd.test", NULL) >= 0); + assert_se(sd_bus_emit_interfaces_added(sd_bus_message_get_bus(m), m->path, "org.freedesktop.systemd.test", NULL) >= 0); r = sd_bus_reply_method_return(m, NULL); assert_se(r >= 0); @@ -165,10 +162,10 @@ static int emit_interfaces_added(sd_bus *bus, sd_bus_message *m, void *userdata, return 1; } -static int emit_interfaces_removed(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) { +static int emit_interfaces_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) { int r; - assert_se(sd_bus_emit_interfaces_removed(bus, m->path, "org.freedesktop.systemd.test", NULL) >= 0); + assert_se(sd_bus_emit_interfaces_removed(sd_bus_message_get_bus(m), m->path, "org.freedesktop.systemd.test", NULL) >= 0); r = sd_bus_reply_method_return(m, NULL); assert_se(r >= 0); @@ -176,10 +173,10 @@ static int emit_interfaces_removed(sd_bus *bus, sd_bus_message *m, void *userdat return 1; } -static int emit_object_added(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) { +static int emit_object_added(sd_bus_message *m, void *userdata, sd_bus_error *error) { int r; - assert_se(sd_bus_emit_object_added(bus, m->path) >= 0); + assert_se(sd_bus_emit_object_added(sd_bus_message_get_bus(m), m->path) >= 0); r = sd_bus_reply_method_return(m, NULL); assert_se(r >= 0); @@ -187,10 +184,10 @@ static int emit_object_added(sd_bus *bus, sd_bus_message *m, void *userdata, sd_ return 1; } -static int emit_object_removed(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) { +static int emit_object_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) { int r; - assert_se(sd_bus_emit_object_removed(bus, m->path) >= 0); + assert_se(sd_bus_emit_object_removed(sd_bus_message_get_bus(m), m->path) >= 0); r = sd_bus_reply_method_return(m, NULL); assert_se(r >= 0); diff --git a/src/libsystemd/sd-bus/test-bus-server.c b/src/libsystemd/sd-bus/test-bus-server.c index 5f807c3b1e..080d8eddb7 100644 --- a/src/libsystemd/sd-bus/test-bus-server.c +++ b/src/libsystemd/sd-bus/test-bus-server.c @@ -19,11 +19,8 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <assert.h> #include <stdlib.h> #include <pthread.h> -#include <unistd.h> -#include <fcntl.h> #include "log.h" #include "util.h" @@ -31,7 +28,6 @@ #include "sd-bus.h" #include "bus-internal.h" -#include "bus-message.h" #include "bus-util.h" struct context { diff --git a/src/libsystemd/sd-bus/test-bus-signature.c b/src/libsystemd/sd-bus/test-bus-signature.c index 3fc565c620..4165c9273a 100644 --- a/src/libsystemd/sd-bus/test-bus-signature.c +++ b/src/libsystemd/sd-bus/test-bus-signature.c @@ -19,8 +19,6 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <assert.h> -#include <stdlib.h> #include "log.h" #include "bus-signature.h" diff --git a/src/libsystemd/sd-bus/test-bus-zero-copy.c b/src/libsystemd/sd-bus/test-bus-zero-copy.c index a054f74bf3..2d062fc9b5 100644 --- a/src/libsystemd/sd-bus/test-bus-zero-copy.c +++ b/src/libsystemd/sd-bus/test-bus-zero-copy.c @@ -19,7 +19,6 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <fcntl.h> #include <sys/mman.h> #include "util.h" @@ -28,7 +27,6 @@ #include "sd-bus.h" #include "bus-message.h" -#include "bus-error.h" #include "bus-kernel.h" #include "bus-dump.h" @@ -39,6 +37,7 @@ int main(int argc, char *argv[]) { _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL; + const char *unique; uint8_t *p; sd_bus *a, *b; int r, bus_ref; @@ -81,7 +80,10 @@ int main(int argc, char *argv[]) { r = sd_bus_start(b); assert_se(r >= 0); - r = sd_bus_message_new_method_call(b, &m, ":1.1", "/a/path", "an.inter.face", "AMethod"); + r = sd_bus_get_unique_name(a, &unique); + assert_se(r >= 0); + + r = sd_bus_message_new_method_call(b, &m, unique, "/a/path", "an.inter.face", "AMethod"); assert_se(r >= 0); r = sd_bus_message_open_container(m, 'r', "aysay"); |