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 if (asprintf(&n, ":1.%llu", (unsigned long long) name->id) < 0) {
272 r = strv_consume(x, n);
276 previous_id = name->id;
279 KDBUS_ITEM_FOREACH(item, name, items) {
280 if (item->type == KDBUS_ITEM_OWNED_NAME) {
281 if (service_name_is_valid(item->name.name)) {
282 r = strv_extend(x, item->name.name);
295 bus_kernel_cmd_free(bus, cmd.offset);
299 static int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activatable) {
300 _cleanup_strv_free_ char **x = NULL, **y = NULL;
304 r = kernel_get_list(bus, KDBUS_LIST_UNIQUE | KDBUS_LIST_NAMES, &x);
310 r = kernel_get_list(bus, KDBUS_LIST_ACTIVATORS, &y);
326 static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
327 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
328 _cleanup_strv_free_ char **x = NULL, **y = NULL;
332 r = sd_bus_call_method(
334 "org.freedesktop.DBus",
335 "/org/freedesktop/DBus",
336 "org.freedesktop.DBus",
344 r = sd_bus_message_read_strv(reply, &x);
348 reply = sd_bus_message_unref(reply);
352 r = sd_bus_call_method(
354 "org.freedesktop.DBus",
355 "/org/freedesktop/DBus",
356 "org.freedesktop.DBus",
357 "ListActivatableNames",
364 r = sd_bus_message_read_strv(reply, &y);
380 _public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
381 assert_return(bus, -EINVAL);
382 assert_return(acquired || activatable, -EINVAL);
383 assert_return(!bus_pid_changed(bus), -ECHILD);
385 if (!bus->bus_client)
388 if (!BUS_IS_OPEN(bus->state))
392 return bus_list_names_kernel(bus, acquired, activatable);
394 return bus_list_names_dbus1(bus, acquired, activatable);
397 static int bus_populate_creds_from_items(
399 struct kdbus_info *info,
403 struct kdbus_item *item;
411 KDBUS_ITEM_FOREACH(item, info, items) {
413 switch (item->type) {
415 case KDBUS_ITEM_PIDS:
417 if (mask & SD_BUS_CREDS_PID && item->pids.pid > 0) {
418 c->pid = (pid_t) item->pids.pid;
419 c->mask |= SD_BUS_CREDS_PID;
422 if (mask & SD_BUS_CREDS_TID && item->pids.tid > 0) {
423 c->tid = (pid_t) item->pids.tid;
424 c->mask |= SD_BUS_CREDS_TID;
427 if (mask & SD_BUS_CREDS_PPID) {
428 if (item->pids.ppid > 0) {
429 c->ppid = (pid_t) item->pids.ppid;
430 c->mask |= SD_BUS_CREDS_PPID;
431 } else if (item->pids.pid == 1) {
432 /* The structure doesn't
433 * really distinguish the case
434 * where a process has no
435 * parent and where we don't
436 * know it because it could
437 * not be translated due to
438 * namespaces. However, we
439 * know that PID 1 has no
440 * parent process, hence let's
441 * patch that in, manually. */
443 c->mask |= SD_BUS_CREDS_PPID;
449 case KDBUS_ITEM_CREDS:
451 if (mask & SD_BUS_CREDS_UID && (uid_t) item->creds.uid != UID_INVALID) {
452 c->uid = (uid_t) item->creds.uid;
453 c->mask |= SD_BUS_CREDS_UID;
456 if (mask & SD_BUS_CREDS_EUID && (uid_t) item->creds.euid != UID_INVALID) {
457 c->euid = (uid_t) item->creds.euid;
458 c->mask |= SD_BUS_CREDS_EUID;
461 if (mask & SD_BUS_CREDS_SUID && (uid_t) item->creds.suid != UID_INVALID) {
462 c->suid = (uid_t) item->creds.suid;
463 c->mask |= SD_BUS_CREDS_SUID;
466 if (mask & SD_BUS_CREDS_FSUID && (uid_t) item->creds.fsuid != UID_INVALID) {
467 c->fsuid = (uid_t) item->creds.fsuid;
468 c->mask |= SD_BUS_CREDS_FSUID;
471 if (mask & SD_BUS_CREDS_GID && (gid_t) item->creds.gid != GID_INVALID) {
472 c->gid = (gid_t) item->creds.gid;
473 c->mask |= SD_BUS_CREDS_GID;
476 if (mask & SD_BUS_CREDS_EGID && (gid_t) item->creds.egid != GID_INVALID) {
477 c->egid = (gid_t) item->creds.egid;
478 c->mask |= SD_BUS_CREDS_EGID;
481 if (mask & SD_BUS_CREDS_SGID && (gid_t) item->creds.sgid != GID_INVALID) {
482 c->sgid = (gid_t) item->creds.sgid;
483 c->mask |= SD_BUS_CREDS_SGID;
486 if (mask & SD_BUS_CREDS_FSGID && (gid_t) item->creds.fsgid != GID_INVALID) {
487 c->fsgid = (gid_t) item->creds.fsgid;
488 c->mask |= SD_BUS_CREDS_FSGID;
493 case KDBUS_ITEM_PID_COMM:
494 if (mask & SD_BUS_CREDS_COMM) {
495 r = free_and_strdup(&c->comm, item->str);
499 c->mask |= SD_BUS_CREDS_COMM;
503 case KDBUS_ITEM_TID_COMM:
504 if (mask & SD_BUS_CREDS_TID_COMM) {
505 r = free_and_strdup(&c->tid_comm, item->str);
509 c->mask |= SD_BUS_CREDS_TID_COMM;
514 if (mask & SD_BUS_CREDS_EXE) {
515 r = free_and_strdup(&c->exe, item->str);
519 c->mask |= SD_BUS_CREDS_EXE;
523 case KDBUS_ITEM_CMDLINE:
524 if (mask & SD_BUS_CREDS_CMDLINE) {
525 c->cmdline_size = item->size - offsetof(struct kdbus_item, data);
526 c->cmdline = memdup(item->data, c->cmdline_size);
530 c->mask |= SD_BUS_CREDS_CMDLINE;
534 case KDBUS_ITEM_CGROUP:
535 m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
536 SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
537 SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
540 r = free_and_strdup(&c->cgroup, item->str);
544 r = bus_get_root_path(bus);
548 r = free_and_strdup(&c->cgroup_root, bus->cgroup_root);
556 case KDBUS_ITEM_CAPS:
557 m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
558 SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
561 if (item->caps.last_cap != cap_last_cap() ||
562 item->size - offsetof(struct kdbus_item, caps.caps) < DIV_ROUND_UP(item->caps.last_cap, 32U) * 4 * 4)
565 c->capability = memdup(item->caps.caps, item->size - offsetof(struct kdbus_item, caps.caps));
573 case KDBUS_ITEM_SECLABEL:
574 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
575 r = free_and_strdup(&c->label, item->str);
579 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
583 case KDBUS_ITEM_AUDIT:
584 if (mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
585 c->audit_session_id = (uint32_t) item->audit.sessionid;
586 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
589 if (mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
590 c->audit_login_uid = (uid_t) item->audit.loginuid;
591 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
595 case KDBUS_ITEM_OWNED_NAME:
596 if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
597 r = strv_extend(&c->well_known_names, item->name.name);
601 c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
605 case KDBUS_ITEM_CONN_DESCRIPTION:
606 if (mask & SD_BUS_CREDS_DESCRIPTION) {
607 r = free_and_strdup(&c->description, item->str);
611 c->mask |= SD_BUS_CREDS_DESCRIPTION;
615 case KDBUS_ITEM_AUXGROUPS:
616 if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
620 n = (item->size - offsetof(struct kdbus_item, data64)) / sizeof(uint64_t);
625 for (i = 0; i < n; i++)
626 g[i] = item->data64[i];
628 free(c->supplementary_gids);
629 c->supplementary_gids = g;
630 c->n_supplementary_gids = n;
632 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
641 int bus_get_name_creds_kdbus(
645 bool allow_activator,
646 sd_bus_creds **creds) {
648 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
649 struct kdbus_cmd_info *cmd;
650 struct kdbus_info *conn_info;
655 if (streq(name, "org.freedesktop.DBus"))
658 r = bus_kernel_parse_unique_name(name, &id);
662 size = offsetof(struct kdbus_cmd_info, items);
663 cmd = alloca0_align(size, 8);
666 l = strlen(name) + 1;
667 size = offsetof(struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(l);
668 cmd = alloca0_align(size, 8);
669 cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
670 cmd->items[0].type = KDBUS_ITEM_NAME;
671 memcpy(cmd->items[0].str, name, l);
674 /* If augmentation is on, and the bus didn't provide us
675 * the bits we want, then ask for the PID/TID so that we
676 * can read the rest from /proc. */
677 if ((mask & SD_BUS_CREDS_AUGMENT) &&
678 (mask & (SD_BUS_CREDS_PPID|
679 SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
680 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
681 SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
682 SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
683 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|
684 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
685 SD_BUS_CREDS_SELINUX_CONTEXT|
686 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
687 mask |= SD_BUS_CREDS_PID;
690 cmd->attach_flags = attach_flags_to_kdbus(mask);
692 r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
696 conn_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
698 /* Non-activated names are considered not available */
699 if (!allow_activator && (conn_info->flags & KDBUS_HELLO_ACTIVATOR)) {
713 if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
714 if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0) {
719 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
722 /* If KDBUS_ITEM_OWNED_NAME is requested then we'll get 0 of
723 them in case the service has no names. This does not mean
724 however that the list of owned names could not be
725 acquired. Hence, let's explicitly clarify that the data is
727 c->mask |= mask & SD_BUS_CREDS_WELL_KNOWN_NAMES;
729 r = bus_populate_creds_from_items(bus, conn_info, mask, c);
733 r = bus_creds_add_more(c, mask, 0, 0);
745 bus_kernel_cmd_free(bus, cmd->offset);
749 static int bus_get_name_creds_dbus1(
753 sd_bus_creds **creds) {
755 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_unique = NULL, *reply = NULL;
756 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
757 const char *unique = NULL;
761 /* Only query the owner if the caller wants to know it or if
762 * the caller just wants to check whether a name exists */
763 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
764 r = sd_bus_call_method(
766 "org.freedesktop.DBus",
767 "/org/freedesktop/DBus",
768 "org.freedesktop.DBus",
777 r = sd_bus_message_read(reply_unique, "s", &unique);
787 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
788 c->unique_name = strdup(unique);
792 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
795 if ((mask & SD_BUS_CREDS_PID) ||
796 ((mask & SD_BUS_CREDS_AUGMENT) &&
797 (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
798 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
799 SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
800 SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
801 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|
802 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
803 SD_BUS_CREDS_SELINUX_CONTEXT|
804 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))) {
808 r = sd_bus_call_method(
810 "org.freedesktop.DBus",
811 "/org/freedesktop/DBus",
812 "org.freedesktop.DBus",
813 "GetConnectionUnixProcessID",
817 unique ? unique : name);
821 r = sd_bus_message_read(reply, "u", &u);
826 if (mask & SD_BUS_CREDS_PID) {
828 c->mask |= SD_BUS_CREDS_PID;
831 reply = sd_bus_message_unref(reply);
834 if (mask & SD_BUS_CREDS_EUID) {
837 r = sd_bus_call_method(
839 "org.freedesktop.DBus",
840 "/org/freedesktop/DBus",
841 "org.freedesktop.DBus",
842 "GetConnectionUnixUser",
846 unique ? unique : name);
850 r = sd_bus_message_read(reply, "u", &u);
855 c->mask |= SD_BUS_CREDS_EUID;
857 reply = sd_bus_message_unref(reply);
860 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
861 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
862 const void *p = NULL;
865 r = sd_bus_call_method(
867 "org.freedesktop.DBus",
868 "/org/freedesktop/DBus",
869 "org.freedesktop.DBus",
870 "GetConnectionSELinuxSecurityContext",
874 unique ? unique : name);
876 if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
879 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
883 c->label = strndup(p, sz);
887 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
891 r = bus_creds_add_more(c, mask, pid, 0);
904 _public_ int sd_bus_get_name_creds(
908 sd_bus_creds **creds) {
910 assert_return(bus, -EINVAL);
911 assert_return(name, -EINVAL);
912 assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
913 assert_return(mask == 0 || creds, -EINVAL);
914 assert_return(!bus_pid_changed(bus), -ECHILD);
915 assert_return(service_name_is_valid(name), -EINVAL);
917 if (!bus->bus_client)
920 if (streq(name, "org.freedesktop.DBus.Local"))
923 if (!BUS_IS_OPEN(bus->state))
927 return bus_get_name_creds_kdbus(bus, name, mask, false, creds);
929 return bus_get_name_creds_dbus1(bus, name, mask, creds);
932 static int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
933 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
934 struct kdbus_cmd_info cmd = {
935 .size = sizeof(struct kdbus_cmd_info),
937 struct kdbus_info *creator_info;
945 /* If augmentation is on, and the bus doesn't didn't allow us
946 * to get the bits we want, then ask for the PID/TID so that we
947 * can read the rest from /proc. */
948 if ((mask & SD_BUS_CREDS_AUGMENT) &&
949 (mask & (SD_BUS_CREDS_PPID|
950 SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
951 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
952 SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
953 SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
954 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|
955 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
956 SD_BUS_CREDS_SELINUX_CONTEXT|
957 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
958 mask |= SD_BUS_CREDS_PID;
960 cmd.attach_flags = attach_flags_to_kdbus(mask);
962 r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
966 creator_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
968 r = bus_populate_creds_from_items(bus, creator_info, mask, c);
969 bus_kernel_cmd_free(bus, cmd.offset);
973 r = bus_creds_add_more(c, mask, pid, 0);
982 static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
983 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
990 do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT);
992 /* Avoid allocating anything if we have no chance of returning useful data */
993 if (!bus->ucred_valid && !do_label)
1000 if (bus->ucred_valid) {
1001 if (bus->ucred.pid > 0) {
1002 pid = c->pid = bus->ucred.pid;
1003 c->mask |= SD_BUS_CREDS_PID & mask;
1006 if (bus->ucred.uid != UID_INVALID) {
1007 c->euid = bus->ucred.uid;
1008 c->mask |= SD_BUS_CREDS_EUID & mask;
1011 if (bus->ucred.gid != GID_INVALID) {
1012 c->egid = bus->ucred.gid;
1013 c->mask |= SD_BUS_CREDS_EGID & mask;
1018 c->label = strdup(bus->label);
1022 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1025 r = bus_creds_add_more(c, mask, pid, 0);
1034 _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
1035 assert_return(bus, -EINVAL);
1036 assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
1037 assert_return(ret, -EINVAL);
1038 assert_return(!bus_pid_changed(bus), -ECHILD);
1040 if (!BUS_IS_OPEN(bus->state))
1044 return bus_get_owner_creds_kdbus(bus, mask, ret);
1046 return bus_get_owner_creds_dbus1(bus, mask, ret);
1049 static int add_name_change_match(sd_bus *bus,
1052 const char *old_owner,
1053 const char *new_owner) {
1055 uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
1056 int is_name_id = -1, r;
1057 struct kdbus_item *item;
1061 /* If we encounter a match that could match against
1062 * NameOwnerChanged messages, then we need to create
1063 * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
1064 * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
1065 * multiple if the match is underspecified.
1067 * The NameOwnerChanged signals take three parameters with
1068 * unique or well-known names, but only some forms actually
1071 * WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD
1072 * WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE
1073 * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE
1074 * UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD
1075 * UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE
1077 * For the latter two the two unique names must be identical.
1082 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
1087 if (!isempty(old_owner)) {
1088 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
1093 if (is_name_id > 0 && old_owner_id != name_id)
1096 old_owner_id = KDBUS_MATCH_ID_ANY;
1098 if (!isempty(new_owner)) {
1099 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
1104 if (is_name_id > 0 && new_owner_id != name_id)
1107 new_owner_id = KDBUS_MATCH_ID_ANY;
1109 if (is_name_id <= 0) {
1110 struct kdbus_cmd_match *m;
1113 /* If the name argument is missing or is a well-known
1114 * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
1117 l = name ? strlen(name) + 1 : 0;
1119 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1120 offsetof(struct kdbus_item, name_change) +
1121 offsetof(struct kdbus_notify_name_change, name) +
1124 m = alloca0_align(sz, 8);
1130 offsetof(struct kdbus_item, name_change) +
1131 offsetof(struct kdbus_notify_name_change, name) +
1134 item->name_change.old_id.id = old_owner_id;
1135 item->name_change.new_id.id = new_owner_id;
1137 memcpy_safe(item->name_change.name, name, l);
1139 /* If the old name is unset or empty, then
1140 * this can match against added names */
1141 if (isempty(old_owner)) {
1142 item->type = KDBUS_ITEM_NAME_ADD;
1144 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1149 /* If the new name is unset or empty, then
1150 * this can match against removed names */
1151 if (isempty(new_owner)) {
1152 item->type = KDBUS_ITEM_NAME_REMOVE;
1154 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1159 /* The CHANGE match we need in either case, because
1160 * what is reported as a name change by the kernel
1161 * might just be an owner change between starter and
1162 * normal clients. For userspace such a change should
1163 * be considered a removal/addition, hence let's
1164 * subscribe to this unconditionally. */
1165 item->type = KDBUS_ITEM_NAME_CHANGE;
1166 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1171 if (is_name_id != 0) {
1172 struct kdbus_cmd_match *m;
1175 /* If the name argument is missing or is a unique
1176 * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
1179 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1180 offsetof(struct kdbus_item, id_change) +
1181 sizeof(struct kdbus_notify_id_change));
1183 m = alloca0_align(sz, 8);
1189 offsetof(struct kdbus_item, id_change) +
1190 sizeof(struct kdbus_notify_id_change);
1191 item->id_change.id = name_id;
1193 /* If the old name is unset or empty, then this can
1194 * match against added ids */
1195 if (isempty(old_owner)) {
1196 item->type = KDBUS_ITEM_ID_ADD;
1197 if (!isempty(new_owner))
1198 item->id_change.id = new_owner_id;
1200 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1205 /* If thew new name is unset or empty, then this can
1206 * match against removed ids */
1207 if (isempty(new_owner)) {
1208 item->type = KDBUS_ITEM_ID_REMOVE;
1209 if (!isempty(old_owner))
1210 item->id_change.id = old_owner_id;
1212 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1221 int bus_add_match_internal_kernel(
1223 struct bus_match_component *components,
1224 unsigned n_components,
1227 struct kdbus_cmd_match *m;
1228 struct kdbus_item *item;
1231 const char *sender = NULL;
1232 size_t sender_length = 0;
1233 uint64_t src_id = KDBUS_MATCH_ID_ANY, dst_id = KDBUS_MATCH_ID_ANY;
1234 bool using_bloom = false;
1236 bool matches_name_change = true;
1237 const char *name_change_arg[3] = {};
1242 /* Monitor streams don't support matches, make this a NOP */
1243 if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1246 bloom = alloca0(bus->bloom_size);
1248 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
1250 for (i = 0; i < n_components; i++) {
1251 struct bus_match_component *c = &components[i];
1255 case BUS_MATCH_SENDER:
1256 if (!streq(c->value_str, "org.freedesktop.DBus"))
1257 matches_name_change = false;
1259 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
1263 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1265 sender = c->value_str;
1266 sender_length = strlen(sender);
1267 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
1272 case BUS_MATCH_MESSAGE_TYPE:
1273 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
1274 matches_name_change = false;
1276 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
1280 case BUS_MATCH_INTERFACE:
1281 if (!streq(c->value_str, "org.freedesktop.DBus"))
1282 matches_name_change = false;
1284 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1288 case BUS_MATCH_MEMBER:
1289 if (!streq(c->value_str, "NameOwnerChanged"))
1290 matches_name_change = false;
1292 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1296 case BUS_MATCH_PATH:
1297 if (!streq(c->value_str, "/org/freedesktop/DBus"))
1298 matches_name_change = false;
1300 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1304 case BUS_MATCH_PATH_NAMESPACE:
1305 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1309 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1310 char buf[sizeof("arg")-1 + 2 + 1];
1312 if (c->type - BUS_MATCH_ARG < 3)
1313 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1315 xsprintf(buf, "arg%i", c->type - BUS_MATCH_ARG);
1316 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1321 case BUS_MATCH_ARG_HAS...BUS_MATCH_ARG_HAS_LAST: {
1322 char buf[sizeof("arg")-1 + 2 + sizeof("-has")];
1324 xsprintf(buf, "arg%i-has", c->type - BUS_MATCH_ARG_HAS);
1325 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1330 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST:
1332 * XXX: DBus spec defines arg[0..63]path= matching to be
1333 * a two-way glob. That is, if either string is a prefix
1334 * of the other, it matches.
1335 * This is really hard to realize in bloom-filters, as
1336 * we would have to create a bloom-match for each prefix
1337 * of @c->value_str. This is excessive, hence we just
1338 * ignore all those matches and accept everything from
1339 * the kernel. People should really avoid those matches.
1340 * If they're used in real-life some day, we will have
1341 * to properly support multiple-matches here.
1345 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1346 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1348 xsprintf(buf, "arg%i-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1349 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1354 case BUS_MATCH_DESTINATION:
1356 * Kernel only supports matching on destination IDs, but
1357 * not on destination names. So just skip the
1358 * destination name restriction and verify it in
1359 * user-space on retrieval.
1361 r = bus_kernel_parse_unique_name(c->value_str, &dst_id);
1365 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1367 /* if not a broadcast, it cannot be a name-change */
1368 if (r <= 0 || dst_id != KDBUS_DST_ID_BROADCAST)
1369 matches_name_change = false;
1373 case BUS_MATCH_ROOT:
1374 case BUS_MATCH_VALUE:
1375 case BUS_MATCH_LEAF:
1376 case _BUS_MATCH_NODE_TYPE_MAX:
1377 case _BUS_MATCH_NODE_TYPE_INVALID:
1378 assert_not_reached("Invalid match type?");
1383 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1385 m = alloca0_align(sz, 8);
1391 if (src_id != KDBUS_MATCH_ID_ANY) {
1392 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1393 item->type = KDBUS_ITEM_ID;
1395 item = KDBUS_ITEM_NEXT(item);
1398 if (dst_id != KDBUS_MATCH_ID_ANY) {
1399 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1400 item->type = KDBUS_ITEM_DST_ID;
1402 item = KDBUS_ITEM_NEXT(item);
1406 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1407 item->type = KDBUS_ITEM_BLOOM_MASK;
1408 memcpy(item->data64, bloom, bus->bloom_size);
1409 item = KDBUS_ITEM_NEXT(item);
1413 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1414 item->type = KDBUS_ITEM_NAME;
1415 memcpy(item->str, sender, sender_length + 1);
1418 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1422 if (matches_name_change) {
1424 /* If this match could theoretically match
1425 * NameOwnerChanged messages, we need to
1426 * install a second non-bloom filter explitly
1429 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1437 #define internal_match(bus, m) \
1438 ((bus)->hello_flags & KDBUS_HELLO_MONITOR \
1439 ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
1442 static int bus_add_match_internal_dbus1(
1444 const char *match) {
1451 e = internal_match(bus, match);
1453 return sd_bus_call_method(
1455 "org.freedesktop.DBus",
1456 "/org/freedesktop/DBus",
1457 "org.freedesktop.DBus",
1465 int bus_add_match_internal(
1468 struct bus_match_component *components,
1469 unsigned n_components,
1474 if (!bus->bus_client)
1478 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1480 return bus_add_match_internal_dbus1(bus, match);
1483 int bus_remove_match_internal_kernel(
1487 struct kdbus_cmd_match m = {
1488 .size = offsetof(struct kdbus_cmd_match, items),
1495 /* Monitor streams don't support matches, make this a NOP */
1496 if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1499 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1506 static int bus_remove_match_internal_dbus1(
1508 const char *match) {
1515 e = internal_match(bus, match);
1517 return sd_bus_call_method(
1519 "org.freedesktop.DBus",
1520 "/org/freedesktop/DBus",
1521 "org.freedesktop.DBus",
1529 int bus_remove_match_internal(
1536 if (!bus->bus_client)
1540 return bus_remove_match_internal_kernel(bus, cookie);
1542 return bus_remove_match_internal_dbus1(bus, match);
1545 #if 0 /// UNNEEDED by elogind
1546 _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1547 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
1551 assert_return(bus, -EINVAL);
1552 assert_return(name, -EINVAL);
1553 assert_return(machine, -EINVAL);
1554 assert_return(!bus_pid_changed(bus), -ECHILD);
1555 assert_return(service_name_is_valid(name), -EINVAL);
1557 if (!bus->bus_client)
1560 if (!BUS_IS_OPEN(bus->state))
1563 if (streq_ptr(name, bus->unique_name))
1564 return sd_id128_get_machine(machine);
1566 r = sd_bus_message_new_method_call(
1571 "org.freedesktop.DBus.Peer",
1576 r = sd_bus_message_set_auto_start(m, false);
1580 r = sd_bus_call(bus, m, 0, NULL, &reply);
1584 r = sd_bus_message_read(reply, "s", &mid);
1588 return sd_id128_from_string(mid, machine);