2 This file is part of systemd.
4 Copyright 2013 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 #ifdef HAVE_VALGRIND_MEMCHECK_H
21 #include <valgrind/memcheck.h>
29 #include "alloc-util.h"
30 #include "bus-bloom.h"
31 #include "bus-control.h"
32 #include "bus-internal.h"
33 #include "bus-message.h"
35 #include "capability-util.h"
36 #include "stdio-util.h"
37 #include "string-util.h"
39 #include "user-util.h"
41 _public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
44 assert_return(bus, -EINVAL);
45 assert_return(unique, -EINVAL);
46 assert_return(!bus_pid_changed(bus), -ECHILD);
51 r = bus_ensure_running(bus);
55 *unique = bus->unique_name;
59 static int bus_request_name_kernel(sd_bus *bus, const char *name, uint64_t flags) {
68 size = offsetof(struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(l);
69 n = alloca0_align(size, 8);
71 n->flags = request_name_flags_to_kdbus(flags);
73 n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
74 n->items[0].type = KDBUS_ITEM_NAME;
75 memcpy(n->items[0].str, name, l);
77 #ifdef HAVE_VALGRIND_MEMCHECK_H
78 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
81 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
85 if (n->return_flags & KDBUS_NAME_IN_QUEUE)
91 static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) {
92 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
93 uint32_t ret, param = 0;
99 if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
100 param |= BUS_NAME_ALLOW_REPLACEMENT;
101 if (flags & SD_BUS_NAME_REPLACE_EXISTING)
102 param |= BUS_NAME_REPLACE_EXISTING;
103 if (!(flags & SD_BUS_NAME_QUEUE))
104 param |= BUS_NAME_DO_NOT_QUEUE;
106 r = sd_bus_call_method(
108 "org.freedesktop.DBus",
109 "/org/freedesktop/DBus",
110 "org.freedesktop.DBus",
120 r = sd_bus_message_read(reply, "u", &ret);
124 if (ret == BUS_NAME_ALREADY_OWNER)
126 else if (ret == BUS_NAME_EXISTS)
128 else if (ret == BUS_NAME_IN_QUEUE)
130 else if (ret == BUS_NAME_PRIMARY_OWNER)
136 _public_ int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags) {
137 assert_return(bus, -EINVAL);
138 assert_return(name, -EINVAL);
139 assert_return(!bus_pid_changed(bus), -ECHILD);
140 assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL);
141 assert_return(service_name_is_valid(name), -EINVAL);
142 assert_return(name[0] != ':', -EINVAL);
144 if (!bus->bus_client)
147 /* Don't allow requesting the special driver and local names */
148 if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
151 if (!BUS_IS_OPEN(bus->state))
155 return bus_request_name_kernel(bus, name, flags);
157 return bus_request_name_dbus1(bus, name, flags);
160 static int bus_release_name_kernel(sd_bus *bus, const char *name) {
168 l = strlen(name) + 1;
169 size = offsetof(struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(l);
170 n = alloca0_align(size, 8);
173 n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
174 n->items[0].type = KDBUS_ITEM_NAME;
175 memcpy(n->items[0].str, name, l);
177 #ifdef HAVE_VALGRIND_MEMCHECK_H
178 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
180 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
187 static int bus_release_name_dbus1(sd_bus *bus, const char *name) {
188 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
195 r = sd_bus_call_method(
197 "org.freedesktop.DBus",
198 "/org/freedesktop/DBus",
199 "org.freedesktop.DBus",
208 r = sd_bus_message_read(reply, "u", &ret);
211 if (ret == BUS_NAME_NON_EXISTENT)
213 if (ret == BUS_NAME_NOT_OWNER)
215 if (ret == BUS_NAME_RELEASED)
221 _public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
222 assert_return(bus, -EINVAL);
223 assert_return(name, -EINVAL);
224 assert_return(!bus_pid_changed(bus), -ECHILD);
225 assert_return(service_name_is_valid(name), -EINVAL);
226 assert_return(name[0] != ':', -EINVAL);
228 if (!bus->bus_client)
231 /* Don't allow releasing the special driver and local names */
232 if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
235 if (!BUS_IS_OPEN(bus->state))
239 return bus_release_name_kernel(bus, name);
241 return bus_release_name_dbus1(bus, name);
244 static int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) {
245 struct kdbus_cmd_list cmd = {
249 struct kdbus_info *name_list, *name;
250 uint64_t previous_id = 0;
253 /* Caller will free half-constructed list on failure... */
255 r = ioctl(bus->input_fd, KDBUS_CMD_LIST, &cmd);
259 name_list = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
261 KDBUS_FOREACH(name, name_list, cmd.list_size) {
262 struct kdbus_item *item;
264 if ((flags & KDBUS_LIST_UNIQUE) && name->id != previous_id && !(name->flags & KDBUS_HELLO_ACTIVATOR)) {
267 #pragma GCC diagnostic push
268 #pragma GCC diagnostic ignored "-Wformat"
269 if (asprintf(&n, ":1.%llu", name->id) < 0) {
273 #pragma GCC diagnostic pop
275 r = strv_consume(x, n);
279 previous_id = name->id;
282 KDBUS_ITEM_FOREACH(item, name, items) {
283 if (item->type == KDBUS_ITEM_OWNED_NAME) {
284 if (service_name_is_valid(item->name.name)) {
285 r = strv_extend(x, item->name.name);
298 bus_kernel_cmd_free(bus, cmd.offset);
302 static int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activatable) {
303 _cleanup_strv_free_ char **x = NULL, **y = NULL;
307 r = kernel_get_list(bus, KDBUS_LIST_UNIQUE | KDBUS_LIST_NAMES, &x);
313 r = kernel_get_list(bus, KDBUS_LIST_ACTIVATORS, &y);
329 static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
330 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
331 _cleanup_strv_free_ char **x = NULL, **y = NULL;
335 r = sd_bus_call_method(
337 "org.freedesktop.DBus",
338 "/org/freedesktop/DBus",
339 "org.freedesktop.DBus",
347 r = sd_bus_message_read_strv(reply, &x);
351 reply = sd_bus_message_unref(reply);
355 r = sd_bus_call_method(
357 "org.freedesktop.DBus",
358 "/org/freedesktop/DBus",
359 "org.freedesktop.DBus",
360 "ListActivatableNames",
367 r = sd_bus_message_read_strv(reply, &y);
383 _public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
384 assert_return(bus, -EINVAL);
385 assert_return(acquired || activatable, -EINVAL);
386 assert_return(!bus_pid_changed(bus), -ECHILD);
388 if (!bus->bus_client)
391 if (!BUS_IS_OPEN(bus->state))
395 return bus_list_names_kernel(bus, acquired, activatable);
397 return bus_list_names_dbus1(bus, acquired, activatable);
400 static int bus_populate_creds_from_items(
402 struct kdbus_info *info,
406 struct kdbus_item *item;
414 KDBUS_ITEM_FOREACH(item, info, items) {
416 switch (item->type) {
418 case KDBUS_ITEM_PIDS:
420 if (mask & SD_BUS_CREDS_PID && item->pids.pid > 0) {
421 c->pid = (pid_t) item->pids.pid;
422 c->mask |= SD_BUS_CREDS_PID;
425 if (mask & SD_BUS_CREDS_TID && item->pids.tid > 0) {
426 c->tid = (pid_t) item->pids.tid;
427 c->mask |= SD_BUS_CREDS_TID;
430 if (mask & SD_BUS_CREDS_PPID) {
431 if (item->pids.ppid > 0) {
432 c->ppid = (pid_t) item->pids.ppid;
433 c->mask |= SD_BUS_CREDS_PPID;
434 } else if (item->pids.pid == 1) {
435 /* The structure doesn't
436 * really distinguish the case
437 * where a process has no
438 * parent and where we don't
439 * know it because it could
440 * not be translated due to
441 * namespaces. However, we
442 * know that PID 1 has no
443 * parent process, hence let's
444 * patch that in, manually. */
446 c->mask |= SD_BUS_CREDS_PPID;
452 case KDBUS_ITEM_CREDS:
454 if (mask & SD_BUS_CREDS_UID && (uid_t) item->creds.uid != UID_INVALID) {
455 c->uid = (uid_t) item->creds.uid;
456 c->mask |= SD_BUS_CREDS_UID;
459 if (mask & SD_BUS_CREDS_EUID && (uid_t) item->creds.euid != UID_INVALID) {
460 c->euid = (uid_t) item->creds.euid;
461 c->mask |= SD_BUS_CREDS_EUID;
464 if (mask & SD_BUS_CREDS_SUID && (uid_t) item->creds.suid != UID_INVALID) {
465 c->suid = (uid_t) item->creds.suid;
466 c->mask |= SD_BUS_CREDS_SUID;
469 if (mask & SD_BUS_CREDS_FSUID && (uid_t) item->creds.fsuid != UID_INVALID) {
470 c->fsuid = (uid_t) item->creds.fsuid;
471 c->mask |= SD_BUS_CREDS_FSUID;
474 if (mask & SD_BUS_CREDS_GID && (gid_t) item->creds.gid != GID_INVALID) {
475 c->gid = (gid_t) item->creds.gid;
476 c->mask |= SD_BUS_CREDS_GID;
479 if (mask & SD_BUS_CREDS_EGID && (gid_t) item->creds.egid != GID_INVALID) {
480 c->egid = (gid_t) item->creds.egid;
481 c->mask |= SD_BUS_CREDS_EGID;
484 if (mask & SD_BUS_CREDS_SGID && (gid_t) item->creds.sgid != GID_INVALID) {
485 c->sgid = (gid_t) item->creds.sgid;
486 c->mask |= SD_BUS_CREDS_SGID;
489 if (mask & SD_BUS_CREDS_FSGID && (gid_t) item->creds.fsgid != GID_INVALID) {
490 c->fsgid = (gid_t) item->creds.fsgid;
491 c->mask |= SD_BUS_CREDS_FSGID;
496 case KDBUS_ITEM_PID_COMM:
497 if (mask & SD_BUS_CREDS_COMM) {
498 r = free_and_strdup(&c->comm, item->str);
502 c->mask |= SD_BUS_CREDS_COMM;
506 case KDBUS_ITEM_TID_COMM:
507 if (mask & SD_BUS_CREDS_TID_COMM) {
508 r = free_and_strdup(&c->tid_comm, item->str);
512 c->mask |= SD_BUS_CREDS_TID_COMM;
517 if (mask & SD_BUS_CREDS_EXE) {
518 r = free_and_strdup(&c->exe, item->str);
522 c->mask |= SD_BUS_CREDS_EXE;
526 case KDBUS_ITEM_CMDLINE:
527 if (mask & SD_BUS_CREDS_CMDLINE) {
528 c->cmdline_size = item->size - offsetof(struct kdbus_item, data);
529 c->cmdline = memdup(item->data, c->cmdline_size);
533 c->mask |= SD_BUS_CREDS_CMDLINE;
537 case KDBUS_ITEM_CGROUP:
538 m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
539 SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
540 SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
543 r = free_and_strdup(&c->cgroup, item->str);
547 r = bus_get_root_path(bus);
551 r = free_and_strdup(&c->cgroup_root, bus->cgroup_root);
559 case KDBUS_ITEM_CAPS:
560 m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
561 SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
564 if (item->caps.last_cap != cap_last_cap() ||
565 item->size - offsetof(struct kdbus_item, caps.caps) < DIV_ROUND_UP(item->caps.last_cap, 32U) * 4 * 4)
568 c->capability = memdup(item->caps.caps, item->size - offsetof(struct kdbus_item, caps.caps));
576 case KDBUS_ITEM_SECLABEL:
577 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
578 r = free_and_strdup(&c->label, item->str);
582 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
586 case KDBUS_ITEM_AUDIT:
587 if (mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
588 c->audit_session_id = (uint32_t) item->audit.sessionid;
589 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
592 if (mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
593 c->audit_login_uid = (uid_t) item->audit.loginuid;
594 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
598 case KDBUS_ITEM_OWNED_NAME:
599 if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
600 r = strv_extend(&c->well_known_names, item->name.name);
604 c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
608 case KDBUS_ITEM_CONN_DESCRIPTION:
609 if (mask & SD_BUS_CREDS_DESCRIPTION) {
610 r = free_and_strdup(&c->description, item->str);
614 c->mask |= SD_BUS_CREDS_DESCRIPTION;
618 case KDBUS_ITEM_AUXGROUPS:
619 if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
623 n = (item->size - offsetof(struct kdbus_item, data64)) / sizeof(uint64_t);
628 for (i = 0; i < n; i++)
629 g[i] = item->data64[i];
631 free(c->supplementary_gids);
632 c->supplementary_gids = g;
633 c->n_supplementary_gids = n;
635 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
644 int bus_get_name_creds_kdbus(
648 bool allow_activator,
649 sd_bus_creds **creds) {
651 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
652 struct kdbus_cmd_info *cmd;
653 struct kdbus_info *conn_info;
658 if (streq(name, "org.freedesktop.DBus"))
661 r = bus_kernel_parse_unique_name(name, &id);
665 size = offsetof(struct kdbus_cmd_info, items);
666 cmd = alloca0_align(size, 8);
669 l = strlen(name) + 1;
670 size = offsetof(struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(l);
671 cmd = alloca0_align(size, 8);
672 cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
673 cmd->items[0].type = KDBUS_ITEM_NAME;
674 memcpy(cmd->items[0].str, name, l);
677 /* If augmentation is on, and the bus didn't provide us
678 * the bits we want, then ask for the PID/TID so that we
679 * can read the rest from /proc. */
680 if ((mask & SD_BUS_CREDS_AUGMENT) &&
681 (mask & (SD_BUS_CREDS_PPID|
682 SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
683 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
684 SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
685 SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
686 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|
687 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
688 SD_BUS_CREDS_SELINUX_CONTEXT|
689 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
690 mask |= SD_BUS_CREDS_PID;
693 cmd->attach_flags = attach_flags_to_kdbus(mask);
695 r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
699 conn_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
701 /* Non-activated names are considered not available */
702 if (!allow_activator && (conn_info->flags & KDBUS_HELLO_ACTIVATOR)) {
716 if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
717 #pragma GCC diagnostic push
718 #pragma GCC diagnostic ignored "-Wformat"
719 if (asprintf(&c->unique_name, ":1.%llu", conn_info->id) < 0) {
723 #pragma GCC diagnostic pop
725 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
728 /* If KDBUS_ITEM_OWNED_NAME is requested then we'll get 0 of
729 them in case the service has no names. This does not mean
730 however that the list of owned names could not be
731 acquired. Hence, let's explicitly clarify that the data is
733 c->mask |= mask & SD_BUS_CREDS_WELL_KNOWN_NAMES;
735 r = bus_populate_creds_from_items(bus, conn_info, mask, c);
739 r = bus_creds_add_more(c, mask, 0, 0);
751 bus_kernel_cmd_free(bus, cmd->offset);
755 static int bus_get_name_creds_dbus1(
759 sd_bus_creds **creds) {
761 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_unique = NULL, *reply = NULL;
762 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
763 const char *unique = NULL;
767 /* Only query the owner if the caller wants to know it or if
768 * the caller just wants to check whether a name exists */
769 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
770 r = sd_bus_call_method(
772 "org.freedesktop.DBus",
773 "/org/freedesktop/DBus",
774 "org.freedesktop.DBus",
783 r = sd_bus_message_read(reply_unique, "s", &unique);
793 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
794 c->unique_name = strdup(unique);
798 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
801 if ((mask & SD_BUS_CREDS_PID) ||
802 ((mask & SD_BUS_CREDS_AUGMENT) &&
803 (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
804 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
805 SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
806 SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
807 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|
808 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
809 SD_BUS_CREDS_SELINUX_CONTEXT|
810 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))) {
814 r = sd_bus_call_method(
816 "org.freedesktop.DBus",
817 "/org/freedesktop/DBus",
818 "org.freedesktop.DBus",
819 "GetConnectionUnixProcessID",
823 unique ? unique : name);
827 r = sd_bus_message_read(reply, "u", &u);
832 if (mask & SD_BUS_CREDS_PID) {
834 c->mask |= SD_BUS_CREDS_PID;
837 reply = sd_bus_message_unref(reply);
840 if (mask & SD_BUS_CREDS_EUID) {
843 r = sd_bus_call_method(
845 "org.freedesktop.DBus",
846 "/org/freedesktop/DBus",
847 "org.freedesktop.DBus",
848 "GetConnectionUnixUser",
852 unique ? unique : name);
856 r = sd_bus_message_read(reply, "u", &u);
861 c->mask |= SD_BUS_CREDS_EUID;
863 reply = sd_bus_message_unref(reply);
866 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
867 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
868 const void *p = NULL;
871 r = sd_bus_call_method(
873 "org.freedesktop.DBus",
874 "/org/freedesktop/DBus",
875 "org.freedesktop.DBus",
876 "GetConnectionSELinuxSecurityContext",
880 unique ? unique : name);
882 if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
885 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
889 c->label = strndup(p, sz);
893 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
897 r = bus_creds_add_more(c, mask, pid, 0);
910 _public_ int sd_bus_get_name_creds(
914 sd_bus_creds **creds) {
916 assert_return(bus, -EINVAL);
917 assert_return(name, -EINVAL);
918 assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
919 assert_return(mask == 0 || creds, -EINVAL);
920 assert_return(!bus_pid_changed(bus), -ECHILD);
921 assert_return(service_name_is_valid(name), -EINVAL);
923 if (!bus->bus_client)
926 if (streq(name, "org.freedesktop.DBus.Local"))
929 if (!BUS_IS_OPEN(bus->state))
933 return bus_get_name_creds_kdbus(bus, name, mask, false, creds);
935 return bus_get_name_creds_dbus1(bus, name, mask, creds);
938 static int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
939 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
940 struct kdbus_cmd_info cmd = {
941 .size = sizeof(struct kdbus_cmd_info),
943 struct kdbus_info *creator_info;
951 /* If augmentation is on, and the bus doesn't didn't allow us
952 * to get the bits we want, then ask for the PID/TID so that we
953 * can read the rest from /proc. */
954 if ((mask & SD_BUS_CREDS_AUGMENT) &&
955 (mask & (SD_BUS_CREDS_PPID|
956 SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
957 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
958 SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
959 SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
960 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|
961 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
962 SD_BUS_CREDS_SELINUX_CONTEXT|
963 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
964 mask |= SD_BUS_CREDS_PID;
966 cmd.attach_flags = attach_flags_to_kdbus(mask);
968 r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
972 creator_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
974 r = bus_populate_creds_from_items(bus, creator_info, mask, c);
975 bus_kernel_cmd_free(bus, cmd.offset);
979 r = bus_creds_add_more(c, mask, pid, 0);
988 static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
989 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
996 do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT);
998 /* Avoid allocating anything if we have no chance of returning useful data */
999 if (!bus->ucred_valid && !do_label)
1002 c = bus_creds_new();
1006 if (bus->ucred_valid) {
1007 if (bus->ucred.pid > 0) {
1008 pid = c->pid = bus->ucred.pid;
1009 c->mask |= SD_BUS_CREDS_PID & mask;
1012 if (bus->ucred.uid != UID_INVALID) {
1013 c->euid = bus->ucred.uid;
1014 c->mask |= SD_BUS_CREDS_EUID & mask;
1017 if (bus->ucred.gid != GID_INVALID) {
1018 c->egid = bus->ucred.gid;
1019 c->mask |= SD_BUS_CREDS_EGID & mask;
1024 c->label = strdup(bus->label);
1028 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1031 r = bus_creds_add_more(c, mask, pid, 0);
1040 _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
1041 assert_return(bus, -EINVAL);
1042 assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
1043 assert_return(ret, -EINVAL);
1044 assert_return(!bus_pid_changed(bus), -ECHILD);
1046 if (!BUS_IS_OPEN(bus->state))
1050 return bus_get_owner_creds_kdbus(bus, mask, ret);
1052 return bus_get_owner_creds_dbus1(bus, mask, ret);
1055 static int add_name_change_match(sd_bus *bus,
1058 const char *old_owner,
1059 const char *new_owner) {
1061 uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
1062 int is_name_id = -1, r;
1063 struct kdbus_item *item;
1067 /* If we encounter a match that could match against
1068 * NameOwnerChanged messages, then we need to create
1069 * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
1070 * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
1071 * multiple if the match is underspecified.
1073 * The NameOwnerChanged signals take three parameters with
1074 * unique or well-known names, but only some forms actually
1077 * WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD
1078 * WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE
1079 * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE
1080 * UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD
1081 * UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE
1083 * For the latter two the two unique names must be identical.
1088 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
1093 if (!isempty(old_owner)) {
1094 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
1099 if (is_name_id > 0 && old_owner_id != name_id)
1102 old_owner_id = KDBUS_MATCH_ID_ANY;
1104 if (!isempty(new_owner)) {
1105 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
1110 if (is_name_id > 0 && new_owner_id != name_id)
1113 new_owner_id = KDBUS_MATCH_ID_ANY;
1115 if (is_name_id <= 0) {
1116 struct kdbus_cmd_match *m;
1119 /* If the name argument is missing or is a well-known
1120 * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
1123 l = name ? strlen(name) + 1 : 0;
1125 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1126 offsetof(struct kdbus_item, name_change) +
1127 offsetof(struct kdbus_notify_name_change, name) +
1130 m = alloca0_align(sz, 8);
1136 offsetof(struct kdbus_item, name_change) +
1137 offsetof(struct kdbus_notify_name_change, name) +
1140 item->name_change.old_id.id = old_owner_id;
1141 item->name_change.new_id.id = new_owner_id;
1143 memcpy_safe(item->name_change.name, name, l);
1145 /* If the old name is unset or empty, then
1146 * this can match against added names */
1147 if (isempty(old_owner)) {
1148 item->type = KDBUS_ITEM_NAME_ADD;
1150 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1155 /* If the new name is unset or empty, then
1156 * this can match against removed names */
1157 if (isempty(new_owner)) {
1158 item->type = KDBUS_ITEM_NAME_REMOVE;
1160 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1165 /* The CHANGE match we need in either case, because
1166 * what is reported as a name change by the kernel
1167 * might just be an owner change between starter and
1168 * normal clients. For userspace such a change should
1169 * be considered a removal/addition, hence let's
1170 * subscribe to this unconditionally. */
1171 item->type = KDBUS_ITEM_NAME_CHANGE;
1172 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1177 if (is_name_id != 0) {
1178 struct kdbus_cmd_match *m;
1181 /* If the name argument is missing or is a unique
1182 * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
1185 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1186 offsetof(struct kdbus_item, id_change) +
1187 sizeof(struct kdbus_notify_id_change));
1189 m = alloca0_align(sz, 8);
1195 offsetof(struct kdbus_item, id_change) +
1196 sizeof(struct kdbus_notify_id_change);
1197 item->id_change.id = name_id;
1199 /* If the old name is unset or empty, then this can
1200 * match against added ids */
1201 if (isempty(old_owner)) {
1202 item->type = KDBUS_ITEM_ID_ADD;
1203 if (!isempty(new_owner))
1204 item->id_change.id = new_owner_id;
1206 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1211 /* If thew new name is unset or empty, then this can
1212 * match against removed ids */
1213 if (isempty(new_owner)) {
1214 item->type = KDBUS_ITEM_ID_REMOVE;
1215 if (!isempty(old_owner))
1216 item->id_change.id = old_owner_id;
1218 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1227 int bus_add_match_internal_kernel(
1229 struct bus_match_component *components,
1230 unsigned n_components,
1233 struct kdbus_cmd_match *m;
1234 struct kdbus_item *item;
1237 const char *sender = NULL;
1238 size_t sender_length = 0;
1239 uint64_t src_id = KDBUS_MATCH_ID_ANY, dst_id = KDBUS_MATCH_ID_ANY;
1240 bool using_bloom = false;
1242 bool matches_name_change = true;
1243 const char *name_change_arg[3] = {};
1248 /* Monitor streams don't support matches, make this a NOP */
1249 if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1252 bloom = alloca0(bus->bloom_size);
1254 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
1256 for (i = 0; i < n_components; i++) {
1257 struct bus_match_component *c = &components[i];
1261 case BUS_MATCH_SENDER:
1262 if (!streq(c->value_str, "org.freedesktop.DBus"))
1263 matches_name_change = false;
1265 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
1269 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1271 sender = c->value_str;
1272 sender_length = strlen(sender);
1273 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
1278 case BUS_MATCH_MESSAGE_TYPE:
1279 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
1280 matches_name_change = false;
1282 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
1286 case BUS_MATCH_INTERFACE:
1287 if (!streq(c->value_str, "org.freedesktop.DBus"))
1288 matches_name_change = false;
1290 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1294 case BUS_MATCH_MEMBER:
1295 if (!streq(c->value_str, "NameOwnerChanged"))
1296 matches_name_change = false;
1298 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1302 case BUS_MATCH_PATH:
1303 if (!streq(c->value_str, "/org/freedesktop/DBus"))
1304 matches_name_change = false;
1306 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1310 case BUS_MATCH_PATH_NAMESPACE:
1311 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1315 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1316 char buf[sizeof("arg")-1 + 2 + 1];
1318 if (c->type - BUS_MATCH_ARG < 3)
1319 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1321 xsprintf(buf, "arg%i", c->type - BUS_MATCH_ARG);
1322 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1327 case BUS_MATCH_ARG_HAS...BUS_MATCH_ARG_HAS_LAST: {
1328 char buf[sizeof("arg")-1 + 2 + sizeof("-has")];
1330 xsprintf(buf, "arg%i-has", c->type - BUS_MATCH_ARG_HAS);
1331 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1336 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST:
1338 * XXX: DBus spec defines arg[0..63]path= matching to be
1339 * a two-way glob. That is, if either string is a prefix
1340 * of the other, it matches.
1341 * This is really hard to realize in bloom-filters, as
1342 * we would have to create a bloom-match for each prefix
1343 * of @c->value_str. This is excessive, hence we just
1344 * ignore all those matches and accept everything from
1345 * the kernel. People should really avoid those matches.
1346 * If they're used in real-life some day, we will have
1347 * to properly support multiple-matches here.
1351 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1352 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1354 xsprintf(buf, "arg%i-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1355 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1360 case BUS_MATCH_DESTINATION:
1362 * Kernel only supports matching on destination IDs, but
1363 * not on destination names. So just skip the
1364 * destination name restriction and verify it in
1365 * user-space on retrieval.
1367 r = bus_kernel_parse_unique_name(c->value_str, &dst_id);
1371 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1373 /* if not a broadcast, it cannot be a name-change */
1374 if (r <= 0 || dst_id != KDBUS_DST_ID_BROADCAST)
1375 matches_name_change = false;
1379 case BUS_MATCH_ROOT:
1380 case BUS_MATCH_VALUE:
1381 case BUS_MATCH_LEAF:
1382 case _BUS_MATCH_NODE_TYPE_MAX:
1383 case _BUS_MATCH_NODE_TYPE_INVALID:
1384 assert_not_reached("Invalid match type?");
1389 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1391 m = alloca0_align(sz, 8);
1397 if (src_id != KDBUS_MATCH_ID_ANY) {
1398 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1399 item->type = KDBUS_ITEM_ID;
1401 item = KDBUS_ITEM_NEXT(item);
1404 if (dst_id != KDBUS_MATCH_ID_ANY) {
1405 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1406 item->type = KDBUS_ITEM_DST_ID;
1408 item = KDBUS_ITEM_NEXT(item);
1412 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1413 item->type = KDBUS_ITEM_BLOOM_MASK;
1414 memcpy(item->data64, bloom, bus->bloom_size);
1415 item = KDBUS_ITEM_NEXT(item);
1419 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1420 item->type = KDBUS_ITEM_NAME;
1421 memcpy(item->str, sender, sender_length + 1);
1424 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1428 if (matches_name_change) {
1430 /* If this match could theoretically match
1431 * NameOwnerChanged messages, we need to
1432 * install a second non-bloom filter explitly
1435 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1443 #define internal_match(bus, m) \
1444 ((bus)->hello_flags & KDBUS_HELLO_MONITOR \
1445 ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
1448 static int bus_add_match_internal_dbus1(
1450 const char *match) {
1457 e = internal_match(bus, match);
1459 return sd_bus_call_method(
1461 "org.freedesktop.DBus",
1462 "/org/freedesktop/DBus",
1463 "org.freedesktop.DBus",
1471 int bus_add_match_internal(
1474 struct bus_match_component *components,
1475 unsigned n_components,
1480 if (!bus->bus_client)
1484 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1486 return bus_add_match_internal_dbus1(bus, match);
1489 int bus_remove_match_internal_kernel(
1493 struct kdbus_cmd_match m = {
1494 .size = offsetof(struct kdbus_cmd_match, items),
1501 /* Monitor streams don't support matches, make this a NOP */
1502 if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1505 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1512 static int bus_remove_match_internal_dbus1(
1514 const char *match) {
1521 e = internal_match(bus, match);
1523 return sd_bus_call_method(
1525 "org.freedesktop.DBus",
1526 "/org/freedesktop/DBus",
1527 "org.freedesktop.DBus",
1535 int bus_remove_match_internal(
1542 if (!bus->bus_client)
1546 return bus_remove_match_internal_kernel(bus, cookie);
1548 return bus_remove_match_internal_dbus1(bus, match);
1551 #if 0 /// UNNEEDED by elogind
1552 _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1553 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
1557 assert_return(bus, -EINVAL);
1558 assert_return(name, -EINVAL);
1559 assert_return(machine, -EINVAL);
1560 assert_return(!bus_pid_changed(bus), -ECHILD);
1561 assert_return(service_name_is_valid(name), -EINVAL);
1563 if (!bus->bus_client)
1566 if (!BUS_IS_OPEN(bus->state))
1569 if (streq_ptr(name, bus->unique_name))
1570 return sd_id128_get_machine(machine);
1572 r = sd_bus_message_new_method_call(
1577 "org.freedesktop.DBus.Peer",
1582 r = sd_bus_message_set_auto_start(m, false);
1586 r = sd_bus_call(bus, m, 0, NULL, &reply);
1590 r = sd_bus_message_read(reply, "s", &mid);
1594 return sd_id128_from_string(mid, machine);