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;
405 KDBUS_ITEM_FOREACH(item, info, items) {
407 switch (item->type) {
409 case KDBUS_ITEM_PIDS:
411 if (mask & SD_BUS_CREDS_PID && item->pids.pid > 0) {
412 c->pid = (pid_t) item->pids.pid;
413 c->mask |= SD_BUS_CREDS_PID;
416 if (mask & SD_BUS_CREDS_TID && item->pids.tid > 0) {
417 c->tid = (pid_t) item->pids.tid;
418 c->mask |= SD_BUS_CREDS_TID;
421 if (mask & SD_BUS_CREDS_PID_STARTTIME && item->pids.starttime > 0) {
422 c->pid_starttime = item->pids.starttime;
423 c->mask |= SD_BUS_CREDS_PID_STARTTIME;
428 case KDBUS_ITEM_CREDS:
430 if (mask & SD_BUS_CREDS_UID && (uid_t) item->creds.uid != (uid_t) -1) {
431 c->uid = (uid_t) item->creds.uid;
432 c->mask |= SD_BUS_CREDS_UID;
435 if (mask & SD_BUS_CREDS_EUID && (uid_t) item->creds.euid != (uid_t) -1) {
436 c->euid = (uid_t) item->creds.euid;
437 c->mask |= SD_BUS_CREDS_EUID;
440 if (mask & SD_BUS_CREDS_SUID && (uid_t) item->creds.suid != (uid_t) -1) {
441 c->suid = (uid_t) item->creds.suid;
442 c->mask |= SD_BUS_CREDS_SUID;
445 if (mask & SD_BUS_CREDS_FSUID && (uid_t) item->creds.fsuid != (uid_t) -1) {
446 c->fsuid = (uid_t) item->creds.fsuid;
447 c->mask |= SD_BUS_CREDS_FSUID;
450 if (mask & SD_BUS_CREDS_GID && (gid_t) item->creds.gid != (gid_t) -1) {
451 c->gid = (gid_t) item->creds.gid;
452 c->mask |= SD_BUS_CREDS_GID;
455 if (mask & SD_BUS_CREDS_EGID && (gid_t) item->creds.egid != (gid_t) -1) {
456 c->egid = (gid_t) item->creds.egid;
457 c->mask |= SD_BUS_CREDS_EGID;
460 if (mask & SD_BUS_CREDS_SGID && (gid_t) item->creds.sgid != (gid_t) -1) {
461 c->sgid = (gid_t) item->creds.sgid;
462 c->mask |= SD_BUS_CREDS_SGID;
465 if (mask & SD_BUS_CREDS_FSGID && (gid_t) item->creds.fsgid != (gid_t) -1) {
466 c->fsgid = (gid_t) item->creds.fsgid;
467 c->mask |= SD_BUS_CREDS_FSGID;
472 case KDBUS_ITEM_PID_COMM:
473 if (mask & SD_BUS_CREDS_COMM) {
474 r = free_and_strdup(&c->comm, item->str);
478 c->mask |= SD_BUS_CREDS_COMM;
482 case KDBUS_ITEM_TID_COMM:
483 if (mask & SD_BUS_CREDS_TID_COMM) {
484 r = free_and_strdup(&c->tid_comm, item->str);
488 c->mask |= SD_BUS_CREDS_TID_COMM;
493 if (mask & SD_BUS_CREDS_EXE) {
494 r = free_and_strdup(&c->exe, item->str);
498 c->mask |= SD_BUS_CREDS_EXE;
502 case KDBUS_ITEM_CMDLINE:
503 if (mask & SD_BUS_CREDS_CMDLINE) {
504 c->cmdline_size = item->size - offsetof(struct kdbus_item, data);
505 c->cmdline = memdup(item->data, c->cmdline_size);
509 c->mask |= SD_BUS_CREDS_CMDLINE;
513 case KDBUS_ITEM_CGROUP:
514 m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
515 SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
516 SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
519 r = free_and_strdup(&c->cgroup, item->str);
523 r = bus_get_root_path(bus);
527 r = free_and_strdup(&c->cgroup_root, bus->cgroup_root);
535 case KDBUS_ITEM_CAPS:
536 m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
537 SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
540 c->capability_size = item->size - offsetof(struct kdbus_item, caps.caps);
541 c->capability = memdup(item->caps.caps, c->capability_size);
549 case KDBUS_ITEM_SECLABEL:
550 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
551 r = free_and_strdup(&c->label, item->str);
555 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
559 case KDBUS_ITEM_AUDIT:
560 if (mask & SD_BUS_CREDS_AUDIT_SESSION_ID && (uint32_t) item->audit.sessionid != (uint32_t) -1) {
561 c->audit_session_id = (uint32_t) item->audit.sessionid;
562 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
565 if (mask & SD_BUS_CREDS_AUDIT_LOGIN_UID && (uid_t) item->audit.loginuid != (uid_t) -1) {
566 c->audit_login_uid = (uid_t) item->audit.loginuid;
567 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
571 case KDBUS_ITEM_OWNED_NAME:
572 if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
573 r = strv_extend(&c->well_known_names, item->name.name);
577 c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
581 case KDBUS_ITEM_CONN_DESCRIPTION:
582 if (mask & SD_BUS_CREDS_DESCRIPTION) {
583 r = free_and_strdup(&c->description, item->str);
587 c->mask |= SD_BUS_CREDS_DESCRIPTION;
591 case KDBUS_ITEM_AUXGROUPS:
592 if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
596 n = (item->size - offsetof(struct kdbus_item, data64)) / sizeof(uint64_t);
601 for (i = 0; i < n; i++)
602 u[i] = (uid_t) item->data64[i];
604 c->supplementary_gids = u;
605 c->n_supplementary_gids = n;
607 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
616 static int bus_get_name_creds_kdbus(
620 sd_bus_creds **creds) {
622 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
623 struct kdbus_cmd_info *cmd;
624 struct kdbus_info *conn_info;
629 r = bus_kernel_parse_unique_name(name, &id);
633 size = offsetof(struct kdbus_cmd_info, items);
634 cmd = alloca0_align(size, 8);
637 l = strlen(name) + 1;
638 size = offsetof(struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(l);
639 cmd = alloca0_align(size, 8);
640 cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
641 cmd->items[0].type = KDBUS_ITEM_NAME;
642 memcpy(cmd->items[0].str, name, l);
646 cmd->flags = attach_flags_to_kdbus(mask);
648 /* If augmentation is on, and the bus doesn't didn't allow us
649 * to get the bits we want, then ask for the PID/TID so that we
650 * can read the rest from /proc. */
651 if ((mask & SD_BUS_CREDS_AUGMENT) &&
652 (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
653 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
654 SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
655 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|
656 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
657 SD_BUS_CREDS_SELINUX_CONTEXT|
658 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
659 cmd->flags |= KDBUS_ATTACH_PIDS;
661 r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
665 conn_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
667 /* Non-activated names are considered not available */
668 if (conn_info->flags & KDBUS_HELLO_ACTIVATOR) {
682 if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
683 if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0) {
688 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
691 r = bus_populate_creds_from_items(bus, conn_info, mask, c);
695 r = bus_creds_add_more(c, mask, 0, 0);
707 kernel_cmd_free(bus, cmd->offset);
711 static int bus_get_name_creds_dbus1(
715 sd_bus_creds **creds) {
717 _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
718 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
719 const char *unique = NULL;
723 /* Only query the owner if the caller wants to know it or if
724 * the caller just wants to check whether a name exists */
725 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
726 r = sd_bus_call_method(
728 "org.freedesktop.DBus",
729 "/org/freedesktop/DBus",
730 "org.freedesktop.DBus",
739 r = sd_bus_message_read(reply_unique, "s", &unique);
749 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
750 c->unique_name = strdup(unique);
754 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
757 if ((mask & SD_BUS_CREDS_PID) ||
758 ((mask & SD_BUS_CREDS_AUGMENT) &&
759 (mask & (SD_BUS_CREDS_PID_STARTTIME|
760 SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
761 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
762 SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
763 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|
764 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
765 SD_BUS_CREDS_SELINUX_CONTEXT|
766 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))) {
770 r = sd_bus_call_method(
772 "org.freedesktop.DBus",
773 "/org/freedesktop/DBus",
774 "org.freedesktop.DBus",
775 "GetConnectionUnixProcessID",
779 unique ? unique : name);
783 r = sd_bus_message_read(reply, "u", &u);
788 if (mask & SD_BUS_CREDS_PID) {
790 c->mask |= SD_BUS_CREDS_PID;
793 reply = sd_bus_message_unref(reply);
796 if (mask & SD_BUS_CREDS_UID) {
799 r = sd_bus_call_method(
801 "org.freedesktop.DBus",
802 "/org/freedesktop/DBus",
803 "org.freedesktop.DBus",
804 "GetConnectionUnixUser",
808 unique ? unique : name);
812 r = sd_bus_message_read(reply, "u", &u);
817 c->mask |= SD_BUS_CREDS_UID;
819 reply = sd_bus_message_unref(reply);
822 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
823 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
824 const void *p = NULL;
827 r = sd_bus_call_method(
829 "org.freedesktop.DBus",
830 "/org/freedesktop/DBus",
831 "org.freedesktop.DBus",
832 "GetConnectionSELinuxSecurityContext",
836 unique ? unique : name);
838 if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
841 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
845 c->label = strndup(p, sz);
849 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
853 r = bus_creds_add_more(c, mask, pid, 0);
866 _public_ int sd_bus_get_name_creds(
870 sd_bus_creds **creds) {
872 assert_return(bus, -EINVAL);
873 assert_return(name, -EINVAL);
874 assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -ENOTSUP);
875 assert_return(mask == 0 || creds, -EINVAL);
876 assert_return(!bus_pid_changed(bus), -ECHILD);
877 assert_return(service_name_is_valid(name), -EINVAL);
878 assert_return(bus->bus_client, -ENODATA);
880 if (!BUS_IS_OPEN(bus->state))
884 return bus_get_name_creds_kdbus(bus, name, mask, creds);
886 return bus_get_name_creds_dbus1(bus, name, mask, creds);
889 _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
890 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
894 assert_return(bus, -EINVAL);
895 assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -ENOTSUP);
896 assert_return(ret, -EINVAL);
897 assert_return(!bus_pid_changed(bus), -ECHILD);
899 if (!BUS_IS_OPEN(bus->state))
902 if (!bus->ucred_valid && !isempty(bus->label))
909 if (bus->ucred_valid) {
910 pid = c->pid = bus->ucred.pid;
911 c->uid = bus->ucred.uid;
912 c->gid = bus->ucred.gid;
914 c->mask |= (SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_GID) & mask;
917 if (!isempty(bus->label) && (mask & SD_BUS_CREDS_SELINUX_CONTEXT)) {
918 c->label = strdup(bus->label);
922 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
925 if (bus->is_kernel) {
926 struct kdbus_cmd_info cmd = {};
927 struct kdbus_info *creator_info;
929 cmd.size = sizeof(cmd);
930 cmd.flags = attach_flags_to_kdbus(mask);
932 /* If augmentation is on, and the bus doesn't didn't allow us
933 * to get the bits we want, then ask for the PID/TID so that we
934 * can read the rest from /proc. */
935 if ((mask & SD_BUS_CREDS_AUGMENT) &&
936 (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
937 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
938 SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
939 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|
940 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
941 SD_BUS_CREDS_SELINUX_CONTEXT|
942 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
943 cmd.flags |= KDBUS_ATTACH_PIDS;
945 r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
949 creator_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
951 r = bus_populate_creds_from_items(bus, creator_info, mask, c);
952 kernel_cmd_free(bus, cmd.offset);
958 r = bus_creds_add_more(c, mask, pid, 0);
967 static int add_name_change_match(sd_bus *bus,
970 const char *old_owner,
971 const char *new_owner) {
973 uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
974 int is_name_id = -1, r;
975 struct kdbus_item *item;
979 /* If we encounter a match that could match against
980 * NameOwnerChanged messages, then we need to create
981 * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
982 * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
983 * multiple if the match is underspecified.
985 * The NameOwnerChanged signals take three parameters with
986 * unique or well-known names, but only some forms actually
989 * WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD
990 * WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE
991 * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE
992 * UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD
993 * UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE
995 * For the latter two the two unique names must be identical.
1000 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
1005 if (!isempty(old_owner)) {
1006 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
1011 if (is_name_id > 0 && old_owner_id != name_id)
1014 old_owner_id = KDBUS_MATCH_ID_ANY;
1016 if (!isempty(new_owner)) {
1017 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
1022 if (is_name_id > 0 && new_owner_id != name_id)
1025 new_owner_id = KDBUS_MATCH_ID_ANY;
1027 if (is_name_id <= 0) {
1028 struct kdbus_cmd_match *m;
1031 /* If the name argument is missing or is a well-known
1032 * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
1035 l = name ? strlen(name) + 1 : 0;
1037 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1038 offsetof(struct kdbus_item, name_change) +
1039 offsetof(struct kdbus_notify_name_change, name) +
1042 m = alloca0_align(sz, 8);
1048 offsetof(struct kdbus_item, name_change) +
1049 offsetof(struct kdbus_notify_name_change, name) +
1052 item->name_change.old_id.id = old_owner_id;
1053 item->name_change.new_id.id = new_owner_id;
1056 memcpy(item->name_change.name, name, l);
1058 /* If the old name is unset or empty, then
1059 * this can match against added names */
1060 if (!old_owner || old_owner[0] == 0) {
1061 item->type = KDBUS_ITEM_NAME_ADD;
1063 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1068 /* If the new name is unset or empty, then
1069 * this can match against removed names */
1070 if (!new_owner || new_owner[0] == 0) {
1071 item->type = KDBUS_ITEM_NAME_REMOVE;
1073 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1078 /* The CHANGE match we need in either case, because
1079 * what is reported as a name change by the kernel
1080 * might just be an owner change between starter and
1081 * normal clients. For userspace such a change should
1082 * be considered a removal/addition, hence let's
1083 * subscribe to this unconditionally. */
1084 item->type = KDBUS_ITEM_NAME_CHANGE;
1085 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1090 if (is_name_id != 0) {
1091 struct kdbus_cmd_match *m;
1094 /* If the name argument is missing or is a unique
1095 * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
1098 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1099 offsetof(struct kdbus_item, id_change) +
1100 sizeof(struct kdbus_notify_id_change));
1102 m = alloca0_align(sz, 8);
1108 offsetof(struct kdbus_item, id_change) +
1109 sizeof(struct kdbus_notify_id_change);
1110 item->id_change.id = name_id;
1112 /* If the old name is unset or empty, then this can
1113 * match against added ids */
1114 if (!old_owner || old_owner[0] == 0) {
1115 item->type = KDBUS_ITEM_ID_ADD;
1117 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1122 /* If thew new name is unset or empty, then this can
1123 * match against removed ids */
1124 if (!new_owner || new_owner[0] == 0) {
1125 item->type = KDBUS_ITEM_ID_REMOVE;
1127 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1136 int bus_add_match_internal_kernel(
1138 struct bus_match_component *components,
1139 unsigned n_components,
1142 struct kdbus_cmd_match *m;
1143 struct kdbus_item *item;
1146 const char *sender = NULL;
1147 size_t sender_length = 0;
1148 uint64_t src_id = KDBUS_MATCH_ID_ANY;
1149 bool using_bloom = false;
1151 bool matches_name_change = true;
1152 const char *name_change_arg[3] = {};
1157 bloom = alloca0(bus->bloom_size);
1159 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
1161 for (i = 0; i < n_components; i++) {
1162 struct bus_match_component *c = &components[i];
1166 case BUS_MATCH_SENDER:
1167 if (!streq(c->value_str, "org.freedesktop.DBus"))
1168 matches_name_change = false;
1170 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
1174 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1176 sender = c->value_str;
1177 sender_length = strlen(sender);
1178 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
1183 case BUS_MATCH_MESSAGE_TYPE:
1184 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
1185 matches_name_change = false;
1187 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
1191 case BUS_MATCH_INTERFACE:
1192 if (!streq(c->value_str, "org.freedesktop.DBus"))
1193 matches_name_change = false;
1195 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1199 case BUS_MATCH_MEMBER:
1200 if (!streq(c->value_str, "NameOwnerChanged"))
1201 matches_name_change = false;
1203 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1207 case BUS_MATCH_PATH:
1208 if (!streq(c->value_str, "/org/freedesktop/DBus"))
1209 matches_name_change = false;
1211 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1215 case BUS_MATCH_PATH_NAMESPACE:
1216 if (!streq(c->value_str, "/")) {
1217 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1222 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1223 char buf[sizeof("arg")-1 + 2 + 1];
1225 if (c->type - BUS_MATCH_ARG < 3)
1226 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1228 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
1229 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1234 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
1235 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1237 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
1238 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1243 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1244 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1246 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1247 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1252 case BUS_MATCH_DESTINATION:
1253 /* The bloom filter does not include
1254 the destination, since it is only
1255 available for broadcast messages
1256 which do not carry a destination
1257 since they are undirected. */
1260 case BUS_MATCH_ROOT:
1261 case BUS_MATCH_VALUE:
1262 case BUS_MATCH_LEAF:
1263 case _BUS_MATCH_NODE_TYPE_MAX:
1264 case _BUS_MATCH_NODE_TYPE_INVALID:
1265 assert_not_reached("Invalid match type?");
1270 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1272 m = alloca0_align(sz, 8);
1278 if (src_id != KDBUS_MATCH_ID_ANY) {
1279 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1280 item->type = KDBUS_ITEM_ID;
1282 item = KDBUS_ITEM_NEXT(item);
1286 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1287 item->type = KDBUS_ITEM_BLOOM_MASK;
1288 memcpy(item->data64, bloom, bus->bloom_size);
1289 item = KDBUS_ITEM_NEXT(item);
1293 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1294 item->type = KDBUS_ITEM_NAME;
1295 memcpy(item->str, sender, sender_length + 1);
1298 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1302 if (matches_name_change) {
1304 /* If this match could theoretically match
1305 * NameOwnerChanged messages, we need to
1306 * install a second non-bloom filter explitly
1309 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1317 #define internal_match(bus, m) \
1318 ((bus)->hello_flags & KDBUS_HELLO_MONITOR \
1319 ? (isempty(m) ? "eavesdrop='true'" : strappenda((m), ",eavesdrop='true'")) \
1322 static int bus_add_match_internal_dbus1(
1324 const char *match) {
1331 e = internal_match(bus, match);
1333 return sd_bus_call_method(
1335 "org.freedesktop.DBus",
1336 "/org/freedesktop/DBus",
1337 "org.freedesktop.DBus",
1345 int bus_add_match_internal(
1348 struct bus_match_component *components,
1349 unsigned n_components,
1355 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1357 return bus_add_match_internal_dbus1(bus, match);
1360 int bus_remove_match_internal_kernel(
1364 struct kdbus_cmd_match m;
1370 m.size = offsetof(struct kdbus_cmd_match, items);
1373 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1380 static int bus_remove_match_internal_dbus1(
1382 const char *match) {
1389 e = internal_match(bus, match);
1391 return sd_bus_call_method(
1393 "org.freedesktop.DBus",
1394 "/org/freedesktop/DBus",
1395 "org.freedesktop.DBus",
1403 int bus_remove_match_internal(
1411 return bus_remove_match_internal_kernel(bus, cookie);
1413 return bus_remove_match_internal_dbus1(bus, match);
1416 _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1417 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1421 assert_return(bus, -EINVAL);
1422 assert_return(name, -EINVAL);
1423 assert_return(machine, -EINVAL);
1424 assert_return(!bus_pid_changed(bus), -ECHILD);
1425 assert_return(service_name_is_valid(name), -EINVAL);
1427 if (!BUS_IS_OPEN(bus->state))
1430 if (streq_ptr(name, bus->unique_name))
1431 return sd_id128_get_machine(machine);
1433 r = sd_bus_message_new_method_call(
1438 "org.freedesktop.DBus.Peer",
1443 r = sd_bus_message_set_auto_start(m, false);
1447 r = sd_bus_call(bus, m, 0, NULL, &reply);
1451 r = sd_bus_message_read(reply, "s", &mid);
1455 return sd_id128_from_string(mid, machine);