1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #ifdef HAVE_VALGRIND_MEMCHECK_H
23 #include <valgrind/memcheck.h>
31 #include "bus-internal.h"
32 #include "bus-message.h"
33 #include "bus-control.h"
34 #include "bus-bloom.h"
36 #include "cgroup-util.h"
38 _public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
41 assert_return(bus, -EINVAL);
42 assert_return(unique, -EINVAL);
43 assert_return(!bus_pid_changed(bus), -ECHILD);
45 r = bus_ensure_running(bus);
49 *unique = bus->unique_name;
53 static int bus_request_name_kernel(sd_bus *bus, const char *name, uint64_t flags) {
54 struct kdbus_cmd_name *n;
62 size = offsetof(struct kdbus_cmd_name, items) + KDBUS_ITEM_SIZE(l);
63 n = alloca0_align(size, 8);
65 n->flags = request_name_flags_to_kdbus(flags);
67 n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
68 n->items[0].type = KDBUS_ITEM_NAME;
69 memcpy(n->items[0].str, name, l);
71 #ifdef HAVE_VALGRIND_MEMCHECK_H
72 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
75 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
79 if (n->flags & KDBUS_NAME_IN_QUEUE)
85 static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) {
86 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
87 uint32_t ret, param = 0;
93 if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
94 param |= BUS_NAME_ALLOW_REPLACEMENT;
95 if (flags & SD_BUS_NAME_REPLACE_EXISTING)
96 param |= BUS_NAME_REPLACE_EXISTING;
97 if (!(flags & SD_BUS_NAME_QUEUE))
98 param |= BUS_NAME_DO_NOT_QUEUE;
100 r = sd_bus_call_method(
102 "org.freedesktop.DBus",
103 "/org/freedesktop/DBus",
104 "org.freedesktop.DBus",
114 r = sd_bus_message_read(reply, "u", &ret);
118 if (ret == BUS_NAME_ALREADY_OWNER)
120 else if (ret == BUS_NAME_EXISTS)
122 else if (ret == BUS_NAME_IN_QUEUE)
124 else if (ret == BUS_NAME_PRIMARY_OWNER)
130 _public_ int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags) {
131 assert_return(bus, -EINVAL);
132 assert_return(name, -EINVAL);
133 assert_return(bus->bus_client, -EINVAL);
134 assert_return(!bus_pid_changed(bus), -ECHILD);
135 assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL);
136 assert_return(service_name_is_valid(name), -EINVAL);
137 assert_return(name[0] != ':', -EINVAL);
139 if (!BUS_IS_OPEN(bus->state))
143 return bus_request_name_kernel(bus, name, flags);
145 return bus_request_name_dbus1(bus, name, flags);
148 static int bus_release_name_kernel(sd_bus *bus, const char *name) {
149 struct kdbus_cmd_name *n;
156 l = strlen(name) + 1;
157 size = offsetof(struct kdbus_cmd_name, items) + KDBUS_ITEM_SIZE(l);
158 n = alloca0_align(size, 8);
161 n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
162 n->items[0].type = KDBUS_ITEM_NAME;
163 memcpy(n->items[0].str, name, l);
165 #ifdef HAVE_VALGRIND_MEMCHECK_H
166 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
168 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
175 static int bus_release_name_dbus1(sd_bus *bus, const char *name) {
176 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
183 r = sd_bus_call_method(
185 "org.freedesktop.DBus",
186 "/org/freedesktop/DBus",
187 "org.freedesktop.DBus",
196 r = sd_bus_message_read(reply, "u", &ret);
199 if (ret == BUS_NAME_NON_EXISTENT)
201 if (ret == BUS_NAME_NOT_OWNER)
203 if (ret == BUS_NAME_RELEASED)
209 _public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
210 assert_return(bus, -EINVAL);
211 assert_return(name, -EINVAL);
212 assert_return(bus->bus_client, -EINVAL);
213 assert_return(!bus_pid_changed(bus), -ECHILD);
214 assert_return(service_name_is_valid(name), -EINVAL);
215 assert_return(name[0] != ':', -EINVAL);
217 if (!BUS_IS_OPEN(bus->state))
221 return bus_release_name_kernel(bus, name);
223 return bus_release_name_dbus1(bus, name);
226 static int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) {
227 struct kdbus_cmd_name_list cmd = {};
228 struct kdbus_name_list *name_list;
229 struct kdbus_name_info *name;
230 uint64_t previous_id = 0;
233 /* Caller will free half-constructed list on failure... */
237 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
241 name_list = (struct kdbus_name_list *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
243 KDBUS_ITEM_FOREACH(name, name_list, names) {
245 struct kdbus_item *item;
246 const char *entry_name = NULL;
248 if ((flags & KDBUS_NAME_LIST_UNIQUE) && name->owner_id != previous_id) {
251 if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) {
256 r = strv_consume(x, n);
260 previous_id = name->owner_id;
263 KDBUS_ITEM_FOREACH(item, name, items)
264 if (item->type == KDBUS_ITEM_OWNED_NAME)
265 entry_name = item->name.name;
267 if (entry_name && service_name_is_valid(entry_name)) {
268 r = strv_extend(x, entry_name);
279 bus_kernel_cmd_free(bus, cmd.offset);
283 static int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activatable) {
284 _cleanup_strv_free_ char **x = NULL, **y = NULL;
288 r = kernel_get_list(bus, KDBUS_NAME_LIST_UNIQUE | KDBUS_NAME_LIST_NAMES, &x);
294 r = kernel_get_list(bus, KDBUS_NAME_LIST_ACTIVATORS, &y);
310 static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
311 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
312 _cleanup_strv_free_ char **x = NULL, **y = NULL;
316 r = sd_bus_call_method(
318 "org.freedesktop.DBus",
319 "/org/freedesktop/DBus",
320 "org.freedesktop.DBus",
328 r = sd_bus_message_read_strv(reply, &x);
332 reply = sd_bus_message_unref(reply);
336 r = sd_bus_call_method(
338 "org.freedesktop.DBus",
339 "/org/freedesktop/DBus",
340 "org.freedesktop.DBus",
341 "ListActivatableNames",
348 r = sd_bus_message_read_strv(reply, &y);
364 _public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
365 assert_return(bus, -EINVAL);
366 assert_return(acquired || activatable, -EINVAL);
367 assert_return(!bus_pid_changed(bus), -ECHILD);
369 if (!BUS_IS_OPEN(bus->state))
373 return bus_list_names_kernel(bus, acquired, activatable);
375 return bus_list_names_dbus1(bus, acquired, activatable);
378 static int bus_populate_creds_from_items(
380 struct kdbus_info *info,
384 struct kdbus_item *item;
392 KDBUS_ITEM_FOREACH(item, info, items) {
394 switch (item->type) {
396 case KDBUS_ITEM_PIDS:
398 if (mask & SD_BUS_CREDS_PID && item->pids.pid > 0) {
399 c->pid = (pid_t) item->pids.pid;
400 c->mask |= SD_BUS_CREDS_PID;
403 if (mask & SD_BUS_CREDS_TID && item->pids.tid > 0) {
404 c->tid = (pid_t) item->pids.tid;
405 c->mask |= SD_BUS_CREDS_TID;
408 if (mask & SD_BUS_CREDS_PID_STARTTIME && item->pids.starttime > 0) {
409 c->pid_starttime = item->pids.starttime;
410 c->mask |= SD_BUS_CREDS_PID_STARTTIME;
415 case KDBUS_ITEM_CREDS:
417 if (mask & SD_BUS_CREDS_UID && (uid_t) item->creds.uid != UID_INVALID) {
418 c->uid = (uid_t) item->creds.uid;
419 c->mask |= SD_BUS_CREDS_UID;
422 if (mask & SD_BUS_CREDS_EUID && (uid_t) item->creds.euid != UID_INVALID) {
423 c->euid = (uid_t) item->creds.euid;
424 c->mask |= SD_BUS_CREDS_EUID;
427 if (mask & SD_BUS_CREDS_SUID && (uid_t) item->creds.suid != UID_INVALID) {
428 c->suid = (uid_t) item->creds.suid;
429 c->mask |= SD_BUS_CREDS_SUID;
432 if (mask & SD_BUS_CREDS_FSUID && (uid_t) item->creds.fsuid != UID_INVALID) {
433 c->fsuid = (uid_t) item->creds.fsuid;
434 c->mask |= SD_BUS_CREDS_FSUID;
437 if (mask & SD_BUS_CREDS_GID && (gid_t) item->creds.gid != GID_INVALID) {
438 c->gid = (gid_t) item->creds.gid;
439 c->mask |= SD_BUS_CREDS_GID;
442 if (mask & SD_BUS_CREDS_EGID && (gid_t) item->creds.egid != GID_INVALID) {
443 c->egid = (gid_t) item->creds.egid;
444 c->mask |= SD_BUS_CREDS_EGID;
447 if (mask & SD_BUS_CREDS_SGID && (gid_t) item->creds.sgid != GID_INVALID) {
448 c->sgid = (gid_t) item->creds.sgid;
449 c->mask |= SD_BUS_CREDS_SGID;
452 if (mask & SD_BUS_CREDS_FSGID && (gid_t) item->creds.fsgid != GID_INVALID) {
453 c->fsgid = (gid_t) item->creds.fsgid;
454 c->mask |= SD_BUS_CREDS_FSGID;
459 case KDBUS_ITEM_PID_COMM:
460 if (mask & SD_BUS_CREDS_COMM) {
461 r = free_and_strdup(&c->comm, item->str);
465 c->mask |= SD_BUS_CREDS_COMM;
469 case KDBUS_ITEM_TID_COMM:
470 if (mask & SD_BUS_CREDS_TID_COMM) {
471 r = free_and_strdup(&c->tid_comm, item->str);
475 c->mask |= SD_BUS_CREDS_TID_COMM;
480 if (mask & SD_BUS_CREDS_EXE) {
481 r = free_and_strdup(&c->exe, item->str);
485 c->mask |= SD_BUS_CREDS_EXE;
489 case KDBUS_ITEM_CMDLINE:
490 if (mask & SD_BUS_CREDS_CMDLINE) {
491 c->cmdline_size = item->size - offsetof(struct kdbus_item, data);
492 c->cmdline = memdup(item->data, c->cmdline_size);
496 c->mask |= SD_BUS_CREDS_CMDLINE;
500 case KDBUS_ITEM_CGROUP:
501 m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
502 SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
503 SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
506 r = free_and_strdup(&c->cgroup, item->str);
510 r = bus_get_root_path(bus);
514 r = free_and_strdup(&c->cgroup_root, bus->cgroup_root);
522 case KDBUS_ITEM_CAPS:
523 m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
524 SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
527 c->capability_size = item->size - offsetof(struct kdbus_item, caps.caps);
528 c->capability = memdup(item->caps.caps, c->capability_size);
536 case KDBUS_ITEM_SECLABEL:
537 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
538 r = free_and_strdup(&c->label, item->str);
542 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
546 case KDBUS_ITEM_AUDIT:
547 if (mask & SD_BUS_CREDS_AUDIT_SESSION_ID && (uint32_t) item->audit.sessionid != (uint32_t) -1) {
548 c->audit_session_id = (uint32_t) item->audit.sessionid;
549 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
552 if (mask & SD_BUS_CREDS_AUDIT_LOGIN_UID && (uid_t) item->audit.loginuid != UID_INVALID) {
553 c->audit_login_uid = (uid_t) item->audit.loginuid;
554 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
558 case KDBUS_ITEM_OWNED_NAME:
559 if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
560 r = strv_extend(&c->well_known_names, item->name.name);
564 c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
568 case KDBUS_ITEM_CONN_DESCRIPTION:
569 if (mask & SD_BUS_CREDS_DESCRIPTION) {
570 r = free_and_strdup(&c->description, item->str);
574 c->mask |= SD_BUS_CREDS_DESCRIPTION;
578 case KDBUS_ITEM_AUXGROUPS:
579 if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
583 assert_cc(sizeof(gid_t) == sizeof(uint32_t));
585 n = (item->size - offsetof(struct kdbus_item, data32)) / sizeof(uint32_t);
586 g = newdup(gid_t, item->data32, n);
590 free(c->supplementary_gids);
591 c->supplementary_gids = g;
592 c->n_supplementary_gids = n;
594 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
603 int bus_get_name_creds_kdbus(
607 bool allow_activator,
608 sd_bus_creds **creds) {
610 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
611 struct kdbus_cmd_info *cmd;
612 struct kdbus_info *conn_info;
617 r = bus_kernel_parse_unique_name(name, &id);
621 size = offsetof(struct kdbus_cmd_info, items);
622 cmd = alloca0_align(size, 8);
625 l = strlen(name) + 1;
626 size = offsetof(struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(l);
627 cmd = alloca0_align(size, 8);
628 cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
629 cmd->items[0].type = KDBUS_ITEM_NAME;
630 memcpy(cmd->items[0].str, name, l);
634 cmd->flags = attach_flags_to_kdbus(mask);
636 /* If augmentation is on, and the bus doesn't didn't allow us
637 * to get the bits we want, then ask for the PID/TID so that we
638 * can read the rest from /proc. */
639 if ((mask & SD_BUS_CREDS_AUGMENT) &&
640 (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
641 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
642 SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
643 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|
644 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
645 SD_BUS_CREDS_SELINUX_CONTEXT|
646 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
647 cmd->flags |= KDBUS_ATTACH_PIDS;
649 r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
653 conn_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
655 /* Non-activated names are considered not available */
656 if (!allow_activator && (conn_info->flags & KDBUS_HELLO_ACTIVATOR)) {
670 if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
671 if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0) {
676 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
679 /* If KDBUS_ITEM_OWNED_NAME is requested then we'll get 0 of
680 them in case the service has no names. This does not mean
681 however that the list of owned names could not be
682 acquired. Hence, let's explicitly clarify that the data is
684 c->mask |= mask & SD_BUS_CREDS_WELL_KNOWN_NAMES;
686 r = bus_populate_creds_from_items(bus, conn_info, mask, c);
690 r = bus_creds_add_more(c, mask, 0, 0);
702 bus_kernel_cmd_free(bus, cmd->offset);
706 static int bus_get_name_creds_dbus1(
710 sd_bus_creds **creds) {
712 _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
713 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
714 const char *unique = NULL;
718 /* Only query the owner if the caller wants to know it or if
719 * the caller just wants to check whether a name exists */
720 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
721 r = sd_bus_call_method(
723 "org.freedesktop.DBus",
724 "/org/freedesktop/DBus",
725 "org.freedesktop.DBus",
734 r = sd_bus_message_read(reply_unique, "s", &unique);
744 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
745 c->unique_name = strdup(unique);
749 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
752 if ((mask & SD_BUS_CREDS_PID) ||
753 ((mask & SD_BUS_CREDS_AUGMENT) &&
754 (mask & (SD_BUS_CREDS_PID_STARTTIME|
755 SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
756 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
757 SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
758 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|
759 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
760 SD_BUS_CREDS_SELINUX_CONTEXT|
761 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))) {
765 r = sd_bus_call_method(
767 "org.freedesktop.DBus",
768 "/org/freedesktop/DBus",
769 "org.freedesktop.DBus",
770 "GetConnectionUnixProcessID",
774 unique ? unique : name);
778 r = sd_bus_message_read(reply, "u", &u);
783 if (mask & SD_BUS_CREDS_PID) {
785 c->mask |= SD_BUS_CREDS_PID;
788 reply = sd_bus_message_unref(reply);
791 if (mask & SD_BUS_CREDS_UID) {
794 r = sd_bus_call_method(
796 "org.freedesktop.DBus",
797 "/org/freedesktop/DBus",
798 "org.freedesktop.DBus",
799 "GetConnectionUnixUser",
803 unique ? unique : name);
807 r = sd_bus_message_read(reply, "u", &u);
812 c->mask |= SD_BUS_CREDS_UID;
814 reply = sd_bus_message_unref(reply);
817 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
818 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
819 const void *p = NULL;
822 r = sd_bus_call_method(
824 "org.freedesktop.DBus",
825 "/org/freedesktop/DBus",
826 "org.freedesktop.DBus",
827 "GetConnectionSELinuxSecurityContext",
831 unique ? unique : name);
833 if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
836 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
840 c->label = strndup(p, sz);
844 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
848 r = bus_creds_add_more(c, mask, pid, 0);
861 _public_ int sd_bus_get_name_creds(
865 sd_bus_creds **creds) {
867 assert_return(bus, -EINVAL);
868 assert_return(name, -EINVAL);
869 assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -ENOTSUP);
870 assert_return(mask == 0 || creds, -EINVAL);
871 assert_return(!bus_pid_changed(bus), -ECHILD);
872 assert_return(service_name_is_valid(name), -EINVAL);
873 assert_return(bus->bus_client, -ENODATA);
875 if (!BUS_IS_OPEN(bus->state))
879 return bus_get_name_creds_kdbus(bus, name, mask, false, creds);
881 return bus_get_name_creds_dbus1(bus, name, mask, creds);
884 static int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
885 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
886 struct kdbus_cmd_info cmd = {
887 .size = sizeof(struct kdbus_cmd_info)
889 struct kdbus_info *creator_info;
897 cmd.flags = attach_flags_to_kdbus(mask);
899 /* If augmentation is on, and the bus doesn't didn't allow us
900 * to get the bits we want, then ask for the PID/TID so that we
901 * can read the rest from /proc. */
902 if ((mask & SD_BUS_CREDS_AUGMENT) &&
903 (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
904 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
905 SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
906 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|
907 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
908 SD_BUS_CREDS_SELINUX_CONTEXT|
909 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
910 cmd.flags |= KDBUS_ATTACH_PIDS;
912 r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
916 creator_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
918 r = bus_populate_creds_from_items(bus, creator_info, mask, c);
919 bus_kernel_cmd_free(bus, cmd.offset);
923 r = bus_creds_add_more(c, mask, pid, 0);
932 static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
933 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
937 if (!bus->ucred_valid && !isempty(bus->label))
944 if (bus->ucred_valid) {
945 if (bus->ucred.pid > 0) {
946 pid = c->pid = bus->ucred.pid;
947 c->mask |= SD_BUS_CREDS_PID & mask;
950 if (bus->ucred.uid != UID_INVALID) {
951 c->uid = bus->ucred.uid;
952 c->mask |= SD_BUS_CREDS_UID & mask;
955 if (bus->ucred.gid != GID_INVALID) {
956 c->gid = bus->ucred.gid;
957 c->mask |= SD_BUS_CREDS_GID & mask;
961 if (!isempty(bus->label) && (mask & SD_BUS_CREDS_SELINUX_CONTEXT)) {
962 c->label = strdup(bus->label);
966 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
969 r = bus_creds_add_more(c, mask, pid, 0);
978 _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
979 assert_return(bus, -EINVAL);
980 assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -ENOTSUP);
981 assert_return(ret, -EINVAL);
982 assert_return(!bus_pid_changed(bus), -ECHILD);
984 if (!BUS_IS_OPEN(bus->state))
988 return bus_get_owner_creds_kdbus(bus, mask, ret);
990 return bus_get_owner_creds_dbus1(bus, mask, ret);
993 static int add_name_change_match(sd_bus *bus,
996 const char *old_owner,
997 const char *new_owner) {
999 uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
1000 int is_name_id = -1, r;
1001 struct kdbus_item *item;
1005 /* If we encounter a match that could match against
1006 * NameOwnerChanged messages, then we need to create
1007 * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
1008 * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
1009 * multiple if the match is underspecified.
1011 * The NameOwnerChanged signals take three parameters with
1012 * unique or well-known names, but only some forms actually
1015 * WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD
1016 * WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE
1017 * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE
1018 * UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD
1019 * UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE
1021 * For the latter two the two unique names must be identical.
1026 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
1031 if (!isempty(old_owner)) {
1032 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
1037 if (is_name_id > 0 && old_owner_id != name_id)
1040 old_owner_id = KDBUS_MATCH_ID_ANY;
1042 if (!isempty(new_owner)) {
1043 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
1048 if (is_name_id > 0 && new_owner_id != name_id)
1051 new_owner_id = KDBUS_MATCH_ID_ANY;
1053 if (is_name_id <= 0) {
1054 struct kdbus_cmd_match *m;
1057 /* If the name argument is missing or is a well-known
1058 * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
1061 l = name ? strlen(name) + 1 : 0;
1063 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1064 offsetof(struct kdbus_item, name_change) +
1065 offsetof(struct kdbus_notify_name_change, name) +
1068 m = alloca0_align(sz, 8);
1074 offsetof(struct kdbus_item, name_change) +
1075 offsetof(struct kdbus_notify_name_change, name) +
1078 item->name_change.old_id.id = old_owner_id;
1079 item->name_change.new_id.id = new_owner_id;
1082 memcpy(item->name_change.name, name, l);
1084 /* If the old name is unset or empty, then
1085 * this can match against added names */
1086 if (!old_owner || old_owner[0] == 0) {
1087 item->type = KDBUS_ITEM_NAME_ADD;
1089 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1094 /* If the new name is unset or empty, then
1095 * this can match against removed names */
1096 if (!new_owner || new_owner[0] == 0) {
1097 item->type = KDBUS_ITEM_NAME_REMOVE;
1099 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1104 /* The CHANGE match we need in either case, because
1105 * what is reported as a name change by the kernel
1106 * might just be an owner change between starter and
1107 * normal clients. For userspace such a change should
1108 * be considered a removal/addition, hence let's
1109 * subscribe to this unconditionally. */
1110 item->type = KDBUS_ITEM_NAME_CHANGE;
1111 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1116 if (is_name_id != 0) {
1117 struct kdbus_cmd_match *m;
1120 /* If the name argument is missing or is a unique
1121 * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
1124 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1125 offsetof(struct kdbus_item, id_change) +
1126 sizeof(struct kdbus_notify_id_change));
1128 m = alloca0_align(sz, 8);
1134 offsetof(struct kdbus_item, id_change) +
1135 sizeof(struct kdbus_notify_id_change);
1136 item->id_change.id = name_id;
1138 /* If the old name is unset or empty, then this can
1139 * match against added ids */
1140 if (!old_owner || old_owner[0] == 0) {
1141 item->type = KDBUS_ITEM_ID_ADD;
1143 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1148 /* If thew new name is unset or empty, then this can
1149 * match against removed ids */
1150 if (!new_owner || new_owner[0] == 0) {
1151 item->type = KDBUS_ITEM_ID_REMOVE;
1153 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1162 int bus_add_match_internal_kernel(
1164 struct bus_match_component *components,
1165 unsigned n_components,
1168 struct kdbus_cmd_match *m;
1169 struct kdbus_item *item;
1172 const char *sender = NULL;
1173 size_t sender_length = 0;
1174 uint64_t src_id = KDBUS_MATCH_ID_ANY;
1175 bool using_bloom = false;
1177 bool matches_name_change = true;
1178 const char *name_change_arg[3] = {};
1183 /* Monitor streams don't support matches, make this a NOP */
1184 if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1187 bloom = alloca0(bus->bloom_size);
1189 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
1191 for (i = 0; i < n_components; i++) {
1192 struct bus_match_component *c = &components[i];
1196 case BUS_MATCH_SENDER:
1197 if (!streq(c->value_str, "org.freedesktop.DBus"))
1198 matches_name_change = false;
1200 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
1204 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1206 sender = c->value_str;
1207 sender_length = strlen(sender);
1208 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
1213 case BUS_MATCH_MESSAGE_TYPE:
1214 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
1215 matches_name_change = false;
1217 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
1221 case BUS_MATCH_INTERFACE:
1222 if (!streq(c->value_str, "org.freedesktop.DBus"))
1223 matches_name_change = false;
1225 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1229 case BUS_MATCH_MEMBER:
1230 if (!streq(c->value_str, "NameOwnerChanged"))
1231 matches_name_change = false;
1233 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1237 case BUS_MATCH_PATH:
1238 if (!streq(c->value_str, "/org/freedesktop/DBus"))
1239 matches_name_change = false;
1241 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1245 case BUS_MATCH_PATH_NAMESPACE:
1246 if (!streq(c->value_str, "/")) {
1247 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1252 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1253 char buf[sizeof("arg")-1 + 2 + 1];
1255 if (c->type - BUS_MATCH_ARG < 3)
1256 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1258 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
1259 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1264 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
1265 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1267 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
1268 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1273 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1274 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1276 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1277 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1282 case BUS_MATCH_DESTINATION:
1283 /* The bloom filter does not include
1284 the destination, since it is only
1285 available for broadcast messages
1286 which do not carry a destination
1287 since they are undirected. */
1290 case BUS_MATCH_ROOT:
1291 case BUS_MATCH_VALUE:
1292 case BUS_MATCH_LEAF:
1293 case _BUS_MATCH_NODE_TYPE_MAX:
1294 case _BUS_MATCH_NODE_TYPE_INVALID:
1295 assert_not_reached("Invalid match type?");
1300 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1302 m = alloca0_align(sz, 8);
1308 if (src_id != KDBUS_MATCH_ID_ANY) {
1309 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1310 item->type = KDBUS_ITEM_ID;
1312 item = KDBUS_ITEM_NEXT(item);
1316 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1317 item->type = KDBUS_ITEM_BLOOM_MASK;
1318 memcpy(item->data64, bloom, bus->bloom_size);
1319 item = KDBUS_ITEM_NEXT(item);
1323 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1324 item->type = KDBUS_ITEM_NAME;
1325 memcpy(item->str, sender, sender_length + 1);
1328 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1332 if (matches_name_change) {
1334 /* If this match could theoretically match
1335 * NameOwnerChanged messages, we need to
1336 * install a second non-bloom filter explitly
1339 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1347 #define internal_match(bus, m) \
1348 ((bus)->hello_flags & KDBUS_HELLO_MONITOR \
1349 ? (isempty(m) ? "eavesdrop='true'" : strappenda((m), ",eavesdrop='true'")) \
1352 static int bus_add_match_internal_dbus1(
1354 const char *match) {
1361 e = internal_match(bus, match);
1363 return sd_bus_call_method(
1365 "org.freedesktop.DBus",
1366 "/org/freedesktop/DBus",
1367 "org.freedesktop.DBus",
1375 int bus_add_match_internal(
1378 struct bus_match_component *components,
1379 unsigned n_components,
1385 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1387 return bus_add_match_internal_dbus1(bus, match);
1390 int bus_remove_match_internal_kernel(
1394 struct kdbus_cmd_match m;
1399 /* Monitor streams don't support matches, make this a NOP */
1400 if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1404 m.size = offsetof(struct kdbus_cmd_match, items);
1407 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1414 static int bus_remove_match_internal_dbus1(
1416 const char *match) {
1423 e = internal_match(bus, match);
1425 return sd_bus_call_method(
1427 "org.freedesktop.DBus",
1428 "/org/freedesktop/DBus",
1429 "org.freedesktop.DBus",
1437 int bus_remove_match_internal(
1445 return bus_remove_match_internal_kernel(bus, cookie);
1447 return bus_remove_match_internal_dbus1(bus, match);
1450 _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1451 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1455 assert_return(bus, -EINVAL);
1456 assert_return(name, -EINVAL);
1457 assert_return(machine, -EINVAL);
1458 assert_return(!bus_pid_changed(bus), -ECHILD);
1459 assert_return(service_name_is_valid(name), -EINVAL);
1461 if (!BUS_IS_OPEN(bus->state))
1464 if (streq_ptr(name, bus->unique_name))
1465 return sd_id128_get_machine(machine);
1467 r = sd_bus_message_new_method_call(
1472 "org.freedesktop.DBus.Peer",
1477 r = sd_bus_message_set_auto_start(m, false);
1481 r = sd_bus_call(bus, m, 0, NULL, &reply);
1485 r = sd_bus_message_read(reply, "s", &mid);
1489 return sd_id128_from_string(mid, machine);