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_cmd_free(sd_bus *bus, uint64_t offset)
228 struct kdbus_cmd_free cmd;
236 r = ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd);
243 static int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) {
244 struct kdbus_cmd_name_list cmd = {};
245 struct kdbus_name_list *name_list;
246 struct kdbus_name_info *name;
247 uint64_t previous_id = 0;
250 /* Caller will free half-constructed list on failure... */
254 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
258 name_list = (struct kdbus_name_list *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
260 KDBUS_ITEM_FOREACH(name, name_list, names) {
262 struct kdbus_item *item;
263 const char *entry_name = NULL;
265 if ((flags & KDBUS_NAME_LIST_UNIQUE) && name->owner_id != previous_id) {
268 if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) {
273 r = strv_consume(x, n);
277 previous_id = name->owner_id;
280 KDBUS_ITEM_FOREACH(item, name, items)
281 if (item->type == KDBUS_ITEM_OWNED_NAME)
282 entry_name = item->name.name;
284 if (entry_name && service_name_is_valid(entry_name)) {
285 r = strv_extend(x, entry_name);
296 kernel_cmd_free(bus, cmd.offset);
300 static int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activatable) {
301 _cleanup_strv_free_ char **x = NULL, **y = NULL;
305 r = kernel_get_list(bus, KDBUS_NAME_LIST_UNIQUE | KDBUS_NAME_LIST_NAMES, &x);
311 r = kernel_get_list(bus, KDBUS_NAME_LIST_ACTIVATORS, &y);
327 static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
328 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
329 _cleanup_strv_free_ char **x = NULL, **y = NULL;
333 r = sd_bus_call_method(
335 "org.freedesktop.DBus",
336 "/org/freedesktop/DBus",
337 "org.freedesktop.DBus",
345 r = sd_bus_message_read_strv(reply, &x);
349 reply = sd_bus_message_unref(reply);
353 r = sd_bus_call_method(
355 "org.freedesktop.DBus",
356 "/org/freedesktop/DBus",
357 "org.freedesktop.DBus",
358 "ListActivatableNames",
365 r = sd_bus_message_read_strv(reply, &y);
381 _public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
382 assert_return(bus, -EINVAL);
383 assert_return(acquired || activatable, -EINVAL);
384 assert_return(!bus_pid_changed(bus), -ECHILD);
386 if (!BUS_IS_OPEN(bus->state))
390 return bus_list_names_kernel(bus, acquired, activatable);
392 return bus_list_names_dbus1(bus, acquired, activatable);
395 static int bus_populate_creds_from_items(
397 struct kdbus_info *info,
401 struct kdbus_item *item;
409 KDBUS_ITEM_FOREACH(item, info, items) {
411 switch (item->type) {
413 case KDBUS_ITEM_PIDS:
415 if (mask & SD_BUS_CREDS_PID && item->pids.pid > 0) {
416 c->pid = (pid_t) item->pids.pid;
417 c->mask |= SD_BUS_CREDS_PID;
420 if (mask & SD_BUS_CREDS_TID && item->pids.tid > 0) {
421 c->tid = (pid_t) item->pids.tid;
422 c->mask |= SD_BUS_CREDS_TID;
425 if (mask & SD_BUS_CREDS_PID_STARTTIME && item->pids.starttime > 0) {
426 c->pid_starttime = item->pids.starttime;
427 c->mask |= SD_BUS_CREDS_PID_STARTTIME;
432 case KDBUS_ITEM_CREDS:
434 if (mask & SD_BUS_CREDS_UID && (uid_t) item->creds.uid != (uid_t) -1) {
435 c->uid = (uid_t) item->creds.uid;
436 c->mask |= SD_BUS_CREDS_UID;
439 if (mask & SD_BUS_CREDS_EUID && (uid_t) item->creds.euid != (uid_t) -1) {
440 c->euid = (uid_t) item->creds.euid;
441 c->mask |= SD_BUS_CREDS_EUID;
444 if (mask & SD_BUS_CREDS_SUID && (uid_t) item->creds.suid != (uid_t) -1) {
445 c->suid = (uid_t) item->creds.suid;
446 c->mask |= SD_BUS_CREDS_SUID;
449 if (mask & SD_BUS_CREDS_FSUID && (uid_t) item->creds.fsuid != (uid_t) -1) {
450 c->fsuid = (uid_t) item->creds.fsuid;
451 c->mask |= SD_BUS_CREDS_FSUID;
454 if (mask & SD_BUS_CREDS_GID && (gid_t) item->creds.gid != (gid_t) -1) {
455 c->gid = (gid_t) item->creds.gid;
456 c->mask |= SD_BUS_CREDS_GID;
459 if (mask & SD_BUS_CREDS_EGID && (gid_t) item->creds.egid != (gid_t) -1) {
460 c->egid = (gid_t) item->creds.egid;
461 c->mask |= SD_BUS_CREDS_EGID;
464 if (mask & SD_BUS_CREDS_SGID && (gid_t) item->creds.sgid != (gid_t) -1) {
465 c->sgid = (gid_t) item->creds.sgid;
466 c->mask |= SD_BUS_CREDS_SGID;
469 if (mask & SD_BUS_CREDS_FSGID && (gid_t) item->creds.fsgid != (gid_t) -1) {
470 c->fsgid = (gid_t) item->creds.fsgid;
471 c->mask |= SD_BUS_CREDS_FSGID;
476 case KDBUS_ITEM_PID_COMM:
477 if (mask & SD_BUS_CREDS_COMM) {
478 r = free_and_strdup(&c->comm, item->str);
482 c->mask |= SD_BUS_CREDS_COMM;
486 case KDBUS_ITEM_TID_COMM:
487 if (mask & SD_BUS_CREDS_TID_COMM) {
488 r = free_and_strdup(&c->tid_comm, item->str);
492 c->mask |= SD_BUS_CREDS_TID_COMM;
497 if (mask & SD_BUS_CREDS_EXE) {
498 r = free_and_strdup(&c->exe, item->str);
502 c->mask |= SD_BUS_CREDS_EXE;
506 case KDBUS_ITEM_CMDLINE:
507 if (mask & SD_BUS_CREDS_CMDLINE) {
508 c->cmdline_size = item->size - offsetof(struct kdbus_item, data);
509 c->cmdline = memdup(item->data, c->cmdline_size);
513 c->mask |= SD_BUS_CREDS_CMDLINE;
517 case KDBUS_ITEM_CGROUP:
518 m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
519 SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
520 SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
523 r = free_and_strdup(&c->cgroup, item->str);
527 r = bus_get_root_path(bus);
531 r = free_and_strdup(&c->cgroup_root, bus->cgroup_root);
539 case KDBUS_ITEM_CAPS:
540 m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
541 SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
544 c->capability_size = item->size - offsetof(struct kdbus_item, caps.caps);
545 c->capability = memdup(item->caps.caps, c->capability_size);
553 case KDBUS_ITEM_SECLABEL:
554 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
555 r = free_and_strdup(&c->label, item->str);
559 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
563 case KDBUS_ITEM_AUDIT:
564 if (mask & SD_BUS_CREDS_AUDIT_SESSION_ID && (uint32_t) item->audit.sessionid != (uint32_t) -1) {
565 c->audit_session_id = (uint32_t) item->audit.sessionid;
566 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
569 if (mask & SD_BUS_CREDS_AUDIT_LOGIN_UID && (uid_t) item->audit.loginuid != (uid_t) -1) {
570 c->audit_login_uid = (uid_t) item->audit.loginuid;
571 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
575 case KDBUS_ITEM_OWNED_NAME:
576 if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
577 r = strv_extend(&c->well_known_names, item->name.name);
581 c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
585 case KDBUS_ITEM_CONN_DESCRIPTION:
586 if (mask & SD_BUS_CREDS_DESCRIPTION) {
587 r = free_and_strdup(&c->description, item->str);
591 c->mask |= SD_BUS_CREDS_DESCRIPTION;
595 case KDBUS_ITEM_AUXGROUPS:
596 if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
600 assert_cc(sizeof(gid_t) == sizeof(uint32_t));
602 n = (item->size - offsetof(struct kdbus_item, data32)) / sizeof(uint32_t);
603 g = newdup(gid_t, item->data32, n);
607 free(c->supplementary_gids);
608 c->supplementary_gids = g;
609 c->n_supplementary_gids = n;
611 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
620 static int bus_get_name_creds_kdbus(
624 sd_bus_creds **creds) {
626 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
627 struct kdbus_cmd_info *cmd;
628 struct kdbus_info *conn_info;
633 r = bus_kernel_parse_unique_name(name, &id);
637 size = offsetof(struct kdbus_cmd_info, items);
638 cmd = alloca0_align(size, 8);
641 l = strlen(name) + 1;
642 size = offsetof(struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(l);
643 cmd = alloca0_align(size, 8);
644 cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
645 cmd->items[0].type = KDBUS_ITEM_NAME;
646 memcpy(cmd->items[0].str, name, l);
650 cmd->flags = attach_flags_to_kdbus(mask);
652 /* If augmentation is on, and the bus doesn't didn't allow us
653 * to get the bits we want, then ask for the PID/TID so that we
654 * can read the rest from /proc. */
655 if ((mask & SD_BUS_CREDS_AUGMENT) &&
656 (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
657 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
658 SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
659 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|
660 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
661 SD_BUS_CREDS_SELINUX_CONTEXT|
662 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
663 cmd->flags |= KDBUS_ATTACH_PIDS;
665 r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
669 conn_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
671 /* Non-activated names are considered not available */
672 if (conn_info->flags & KDBUS_HELLO_ACTIVATOR) {
686 if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
687 if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0) {
692 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
695 /* If KDBUS_ITEM_OWNED_NAME is requested then we'll get 0 of
696 them in case the service has no names. This does not mean
697 however that the list of owned names could not be
698 acquired. Hence, let's explicitly clarify that the data is
700 c->mask |= mask & SD_BUS_CREDS_WELL_KNOWN_NAMES;
702 r = bus_populate_creds_from_items(bus, conn_info, mask, c);
706 r = bus_creds_add_more(c, mask, 0, 0);
718 kernel_cmd_free(bus, cmd->offset);
722 static int bus_get_name_creds_dbus1(
726 sd_bus_creds **creds) {
728 _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
729 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
730 const char *unique = NULL;
734 /* Only query the owner if the caller wants to know it or if
735 * the caller just wants to check whether a name exists */
736 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
737 r = sd_bus_call_method(
739 "org.freedesktop.DBus",
740 "/org/freedesktop/DBus",
741 "org.freedesktop.DBus",
750 r = sd_bus_message_read(reply_unique, "s", &unique);
760 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
761 c->unique_name = strdup(unique);
765 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
768 if ((mask & SD_BUS_CREDS_PID) ||
769 ((mask & SD_BUS_CREDS_AUGMENT) &&
770 (mask & (SD_BUS_CREDS_PID_STARTTIME|
771 SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
772 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
773 SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
774 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|
775 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
776 SD_BUS_CREDS_SELINUX_CONTEXT|
777 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))) {
781 r = sd_bus_call_method(
783 "org.freedesktop.DBus",
784 "/org/freedesktop/DBus",
785 "org.freedesktop.DBus",
786 "GetConnectionUnixProcessID",
790 unique ? unique : name);
794 r = sd_bus_message_read(reply, "u", &u);
799 if (mask & SD_BUS_CREDS_PID) {
801 c->mask |= SD_BUS_CREDS_PID;
804 reply = sd_bus_message_unref(reply);
807 if (mask & SD_BUS_CREDS_UID) {
810 r = sd_bus_call_method(
812 "org.freedesktop.DBus",
813 "/org/freedesktop/DBus",
814 "org.freedesktop.DBus",
815 "GetConnectionUnixUser",
819 unique ? unique : name);
823 r = sd_bus_message_read(reply, "u", &u);
828 c->mask |= SD_BUS_CREDS_UID;
830 reply = sd_bus_message_unref(reply);
833 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
834 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
835 const void *p = NULL;
838 r = sd_bus_call_method(
840 "org.freedesktop.DBus",
841 "/org/freedesktop/DBus",
842 "org.freedesktop.DBus",
843 "GetConnectionSELinuxSecurityContext",
847 unique ? unique : name);
849 if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
852 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
856 c->label = strndup(p, sz);
860 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
864 r = bus_creds_add_more(c, mask, pid, 0);
877 _public_ int sd_bus_get_name_creds(
881 sd_bus_creds **creds) {
883 assert_return(bus, -EINVAL);
884 assert_return(name, -EINVAL);
885 assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -ENOTSUP);
886 assert_return(mask == 0 || creds, -EINVAL);
887 assert_return(!bus_pid_changed(bus), -ECHILD);
888 assert_return(service_name_is_valid(name), -EINVAL);
889 assert_return(bus->bus_client, -ENODATA);
891 if (!BUS_IS_OPEN(bus->state))
895 return bus_get_name_creds_kdbus(bus, name, mask, creds);
897 return bus_get_name_creds_dbus1(bus, name, mask, creds);
900 _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
901 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
905 assert_return(bus, -EINVAL);
906 assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -ENOTSUP);
907 assert_return(ret, -EINVAL);
908 assert_return(!bus_pid_changed(bus), -ECHILD);
910 if (!BUS_IS_OPEN(bus->state))
913 if (!bus->ucred_valid && !isempty(bus->label))
920 if (bus->ucred_valid) {
921 pid = c->pid = bus->ucred.pid;
922 c->uid = bus->ucred.uid;
923 c->gid = bus->ucred.gid;
925 c->mask |= (SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_GID) & mask;
928 if (!isempty(bus->label) && (mask & SD_BUS_CREDS_SELINUX_CONTEXT)) {
929 c->label = strdup(bus->label);
933 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
936 if (bus->is_kernel) {
937 struct kdbus_cmd_info cmd = {};
938 struct kdbus_info *creator_info;
940 cmd.size = sizeof(cmd);
941 cmd.flags = attach_flags_to_kdbus(mask);
943 /* If augmentation is on, and the bus doesn't didn't allow us
944 * to get the bits we want, then ask for the PID/TID so that we
945 * can read the rest from /proc. */
946 if ((mask & SD_BUS_CREDS_AUGMENT) &&
947 (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
948 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
949 SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
950 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|
951 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
952 SD_BUS_CREDS_SELINUX_CONTEXT|
953 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
954 cmd.flags |= KDBUS_ATTACH_PIDS;
956 r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
960 creator_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
962 r = bus_populate_creds_from_items(bus, creator_info, mask, c);
963 kernel_cmd_free(bus, cmd.offset);
969 r = bus_creds_add_more(c, mask, pid, 0);
978 static int add_name_change_match(sd_bus *bus,
981 const char *old_owner,
982 const char *new_owner) {
984 uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
985 int is_name_id = -1, r;
986 struct kdbus_item *item;
990 /* If we encounter a match that could match against
991 * NameOwnerChanged messages, then we need to create
992 * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
993 * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
994 * multiple if the match is underspecified.
996 * The NameOwnerChanged signals take three parameters with
997 * unique or well-known names, but only some forms actually
1000 * WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD
1001 * WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE
1002 * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE
1003 * UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD
1004 * UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE
1006 * For the latter two the two unique names must be identical.
1011 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
1016 if (!isempty(old_owner)) {
1017 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
1022 if (is_name_id > 0 && old_owner_id != name_id)
1025 old_owner_id = KDBUS_MATCH_ID_ANY;
1027 if (!isempty(new_owner)) {
1028 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
1033 if (is_name_id > 0 && new_owner_id != name_id)
1036 new_owner_id = KDBUS_MATCH_ID_ANY;
1038 if (is_name_id <= 0) {
1039 struct kdbus_cmd_match *m;
1042 /* If the name argument is missing or is a well-known
1043 * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
1046 l = name ? strlen(name) + 1 : 0;
1048 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1049 offsetof(struct kdbus_item, name_change) +
1050 offsetof(struct kdbus_notify_name_change, name) +
1053 m = alloca0_align(sz, 8);
1059 offsetof(struct kdbus_item, name_change) +
1060 offsetof(struct kdbus_notify_name_change, name) +
1063 item->name_change.old_id.id = old_owner_id;
1064 item->name_change.new_id.id = new_owner_id;
1067 memcpy(item->name_change.name, name, l);
1069 /* If the old name is unset or empty, then
1070 * this can match against added names */
1071 if (!old_owner || old_owner[0] == 0) {
1072 item->type = KDBUS_ITEM_NAME_ADD;
1074 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1079 /* If the new name is unset or empty, then
1080 * this can match against removed names */
1081 if (!new_owner || new_owner[0] == 0) {
1082 item->type = KDBUS_ITEM_NAME_REMOVE;
1084 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1089 /* The CHANGE match we need in either case, because
1090 * what is reported as a name change by the kernel
1091 * might just be an owner change between starter and
1092 * normal clients. For userspace such a change should
1093 * be considered a removal/addition, hence let's
1094 * subscribe to this unconditionally. */
1095 item->type = KDBUS_ITEM_NAME_CHANGE;
1096 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1101 if (is_name_id != 0) {
1102 struct kdbus_cmd_match *m;
1105 /* If the name argument is missing or is a unique
1106 * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
1109 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1110 offsetof(struct kdbus_item, id_change) +
1111 sizeof(struct kdbus_notify_id_change));
1113 m = alloca0_align(sz, 8);
1119 offsetof(struct kdbus_item, id_change) +
1120 sizeof(struct kdbus_notify_id_change);
1121 item->id_change.id = name_id;
1123 /* If the old name is unset or empty, then this can
1124 * match against added ids */
1125 if (!old_owner || old_owner[0] == 0) {
1126 item->type = KDBUS_ITEM_ID_ADD;
1128 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1133 /* If thew new name is unset or empty, then this can
1134 * match against removed ids */
1135 if (!new_owner || new_owner[0] == 0) {
1136 item->type = KDBUS_ITEM_ID_REMOVE;
1138 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1147 int bus_add_match_internal_kernel(
1149 struct bus_match_component *components,
1150 unsigned n_components,
1153 struct kdbus_cmd_match *m;
1154 struct kdbus_item *item;
1157 const char *sender = NULL;
1158 size_t sender_length = 0;
1159 uint64_t src_id = KDBUS_MATCH_ID_ANY;
1160 bool using_bloom = false;
1162 bool matches_name_change = true;
1163 const char *name_change_arg[3] = {};
1168 bloom = alloca0(bus->bloom_size);
1170 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
1172 for (i = 0; i < n_components; i++) {
1173 struct bus_match_component *c = &components[i];
1177 case BUS_MATCH_SENDER:
1178 if (!streq(c->value_str, "org.freedesktop.DBus"))
1179 matches_name_change = false;
1181 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
1185 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1187 sender = c->value_str;
1188 sender_length = strlen(sender);
1189 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
1194 case BUS_MATCH_MESSAGE_TYPE:
1195 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
1196 matches_name_change = false;
1198 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
1202 case BUS_MATCH_INTERFACE:
1203 if (!streq(c->value_str, "org.freedesktop.DBus"))
1204 matches_name_change = false;
1206 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1210 case BUS_MATCH_MEMBER:
1211 if (!streq(c->value_str, "NameOwnerChanged"))
1212 matches_name_change = false;
1214 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1218 case BUS_MATCH_PATH:
1219 if (!streq(c->value_str, "/org/freedesktop/DBus"))
1220 matches_name_change = false;
1222 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1226 case BUS_MATCH_PATH_NAMESPACE:
1227 if (!streq(c->value_str, "/")) {
1228 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1233 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1234 char buf[sizeof("arg")-1 + 2 + 1];
1236 if (c->type - BUS_MATCH_ARG < 3)
1237 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1239 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
1240 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1245 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
1246 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1248 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
1249 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1254 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1255 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1257 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1258 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1263 case BUS_MATCH_DESTINATION:
1264 /* The bloom filter does not include
1265 the destination, since it is only
1266 available for broadcast messages
1267 which do not carry a destination
1268 since they are undirected. */
1271 case BUS_MATCH_ROOT:
1272 case BUS_MATCH_VALUE:
1273 case BUS_MATCH_LEAF:
1274 case _BUS_MATCH_NODE_TYPE_MAX:
1275 case _BUS_MATCH_NODE_TYPE_INVALID:
1276 assert_not_reached("Invalid match type?");
1281 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1283 m = alloca0_align(sz, 8);
1289 if (src_id != KDBUS_MATCH_ID_ANY) {
1290 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1291 item->type = KDBUS_ITEM_ID;
1293 item = KDBUS_ITEM_NEXT(item);
1297 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1298 item->type = KDBUS_ITEM_BLOOM_MASK;
1299 memcpy(item->data64, bloom, bus->bloom_size);
1300 item = KDBUS_ITEM_NEXT(item);
1304 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1305 item->type = KDBUS_ITEM_NAME;
1306 memcpy(item->str, sender, sender_length + 1);
1309 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1313 if (matches_name_change) {
1315 /* If this match could theoretically match
1316 * NameOwnerChanged messages, we need to
1317 * install a second non-bloom filter explitly
1320 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1328 #define internal_match(bus, m) \
1329 ((bus)->hello_flags & KDBUS_HELLO_MONITOR \
1330 ? (isempty(m) ? "eavesdrop='true'" : strappenda((m), ",eavesdrop='true'")) \
1333 static int bus_add_match_internal_dbus1(
1335 const char *match) {
1342 e = internal_match(bus, match);
1344 return sd_bus_call_method(
1346 "org.freedesktop.DBus",
1347 "/org/freedesktop/DBus",
1348 "org.freedesktop.DBus",
1356 int bus_add_match_internal(
1359 struct bus_match_component *components,
1360 unsigned n_components,
1366 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1368 return bus_add_match_internal_dbus1(bus, match);
1371 int bus_remove_match_internal_kernel(
1375 struct kdbus_cmd_match m;
1381 m.size = offsetof(struct kdbus_cmd_match, items);
1384 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1391 static int bus_remove_match_internal_dbus1(
1393 const char *match) {
1400 e = internal_match(bus, match);
1402 return sd_bus_call_method(
1404 "org.freedesktop.DBus",
1405 "/org/freedesktop/DBus",
1406 "org.freedesktop.DBus",
1414 int bus_remove_match_internal(
1422 return bus_remove_match_internal_kernel(bus, cookie);
1424 return bus_remove_match_internal_dbus1(bus, match);
1427 _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1428 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1432 assert_return(bus, -EINVAL);
1433 assert_return(name, -EINVAL);
1434 assert_return(machine, -EINVAL);
1435 assert_return(!bus_pid_changed(bus), -ECHILD);
1436 assert_return(service_name_is_valid(name), -EINVAL);
1438 if (!BUS_IS_OPEN(bus->state))
1441 if (streq_ptr(name, bus->unique_name))
1442 return sd_id128_get_machine(machine);
1444 r = sd_bus_message_new_method_call(
1449 "org.freedesktop.DBus.Peer",
1454 r = sd_bus_message_set_auto_start(m, false);
1458 r = sd_bus_call(bus, m, 0, NULL, &reply);
1462 r = sd_bus_message_read(reply, "s", &mid);
1466 return sd_id128_from_string(mid, machine);