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 kdbus_translate_request_name_flags(flags, (uint64_t *) &n->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(sd_bus *bus,
396 struct kdbus_info *info,
400 struct kdbus_item *item;
404 KDBUS_ITEM_FOREACH(item, info, items) {
406 switch (item->type) {
408 case KDBUS_ITEM_PIDS:
410 if (mask & SD_BUS_CREDS_PID && item->pids.pid > 0) {
411 c->pid = (pid_t) item->pids.pid;
412 c->mask |= SD_BUS_CREDS_PID;
415 if (mask & SD_BUS_CREDS_TID && item->pids.tid > 0) {
416 c->tid = (pid_t) item->pids.tid;
417 c->mask |= SD_BUS_CREDS_TID;
420 if (mask & SD_BUS_CREDS_PID_STARTTIME && item->pids.starttime > 0) {
421 c->pid_starttime = item->pids.starttime;
422 c->mask |= SD_BUS_CREDS_PID_STARTTIME;
427 case KDBUS_ITEM_CREDS:
429 if (mask & SD_BUS_CREDS_UID && (uid_t) item->creds.uid != (uid_t) -1) {
430 c->uid = (uid_t) item->creds.uid;
431 c->mask |= SD_BUS_CREDS_UID;
434 if (mask & SD_BUS_CREDS_EUID && (uid_t) item->creds.euid != (uid_t) -1) {
435 c->euid = (uid_t) item->creds.euid;
436 c->mask |= SD_BUS_CREDS_EUID;
439 if (mask & SD_BUS_CREDS_SUID && (uid_t) item->creds.suid != (uid_t) -1) {
440 c->suid = (uid_t) item->creds.suid;
441 c->mask |= SD_BUS_CREDS_SUID;
444 if (mask & SD_BUS_CREDS_FSUID && (uid_t) item->creds.fsuid != (uid_t) -1) {
445 c->fsuid = (uid_t) item->creds.fsuid;
446 c->mask |= SD_BUS_CREDS_FSUID;
449 if (mask & SD_BUS_CREDS_GID && (gid_t) item->creds.gid != (gid_t) -1) {
450 c->gid = (gid_t) item->creds.gid;
451 c->mask |= SD_BUS_CREDS_GID;
454 if (mask & SD_BUS_CREDS_EGID && (gid_t) item->creds.egid != (gid_t) -1) {
455 c->egid = (gid_t) item->creds.egid;
456 c->mask |= SD_BUS_CREDS_EGID;
459 if (mask & SD_BUS_CREDS_SGID && (gid_t) item->creds.sgid != (gid_t) -1) {
460 c->sgid = (gid_t) item->creds.sgid;
461 c->mask |= SD_BUS_CREDS_SGID;
464 if (mask & SD_BUS_CREDS_FSGID && (gid_t) item->creds.fsgid != (gid_t) -1) {
465 c->fsgid = (gid_t) item->creds.fsgid;
466 c->mask |= SD_BUS_CREDS_FSGID;
471 case KDBUS_ITEM_PID_COMM:
472 if (mask & SD_BUS_CREDS_COMM) {
473 c->comm = strdup(item->str);
477 c->mask |= SD_BUS_CREDS_COMM;
481 case KDBUS_ITEM_TID_COMM:
482 if (mask & SD_BUS_CREDS_TID_COMM) {
483 c->tid_comm = strdup(item->str);
487 c->mask |= SD_BUS_CREDS_TID_COMM;
492 if (mask & SD_BUS_CREDS_EXE) {
493 c->exe = strdup(item->str);
497 c->mask |= SD_BUS_CREDS_EXE;
501 case KDBUS_ITEM_CMDLINE:
502 if (mask & SD_BUS_CREDS_CMDLINE) {
503 c->cmdline_size = item->size - offsetof(struct kdbus_item, data);
504 c->cmdline = memdup(item->data, c->cmdline_size);
508 c->mask |= SD_BUS_CREDS_CMDLINE;
512 case KDBUS_ITEM_CGROUP:
513 m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
514 SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
515 SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
518 c->cgroup = strdup(item->str);
522 r = bus_get_root_path(bus);
526 c->cgroup_root = strdup(bus->cgroup_root);
534 case KDBUS_ITEM_CAPS:
535 m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
536 SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
539 c->capability_size = item->size - offsetof(struct kdbus_item, caps.caps);
540 c->capability = memdup(item->caps.caps, c->capability_size);
548 case KDBUS_ITEM_SECLABEL:
549 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
550 c->label = strdup(item->str);
554 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
558 case KDBUS_ITEM_AUDIT:
559 if (mask & SD_BUS_CREDS_AUDIT_SESSION_ID && (uint32_t) item->audit.sessionid != (uint32_t) -1) {
560 c->audit_session_id = (uint32_t) item->audit.sessionid;
561 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
564 if (mask & SD_BUS_CREDS_AUDIT_LOGIN_UID && (uid_t) item->audit.loginuid != (uid_t) -1) {
565 c->audit_login_uid = (uid_t) item->audit.loginuid;
566 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
570 case KDBUS_ITEM_OWNED_NAME:
571 if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
572 r = strv_extend(&c->well_known_names, item->name.name);
576 c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
580 case KDBUS_ITEM_CONN_DESCRIPTION:
581 if (mask & SD_BUS_CREDS_DESCRIPTION) {
582 c->description = strdup(item->str);
586 c->mask |= SD_BUS_CREDS_DESCRIPTION;
590 case KDBUS_ITEM_AUXGROUPS:
591 if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
595 n = (item->size - offsetof(struct kdbus_item, data64)) / sizeof(uint64_t);
600 for (i = 0; i < n; i++)
601 u[i] = (uid_t) item->data64[i];
603 c->supplementary_gids = u;
604 c->n_supplementary_gids = n;
606 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
615 static int bus_get_name_creds_kdbus(
619 sd_bus_creds **creds) {
621 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
622 struct kdbus_cmd_info *cmd;
623 struct kdbus_info *conn_info;
628 r = bus_kernel_parse_unique_name(name, &id);
632 size = offsetof(struct kdbus_cmd_info, items);
633 cmd = alloca0_align(size, 8);
636 l = strlen(name) + 1;
637 size = offsetof(struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(l);
638 cmd = alloca0_align(size, 8);
639 cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
640 cmd->items[0].type = KDBUS_ITEM_NAME;
641 memcpy(cmd->items[0].str, name, l);
645 kdbus_translate_attach_flags(mask, (uint64_t*) &cmd->flags);
647 /* If augmentation is on, and the bus doesn't didn't allow us
648 * to get the bits we want, then ask for the PID/TID so that we
649 * can read the rest from /proc. */
650 if ((mask & SD_BUS_CREDS_AUGMENT) &&
651 (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
652 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
653 SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
654 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|
655 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
656 SD_BUS_CREDS_SELINUX_CONTEXT|
657 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
658 cmd->flags |= KDBUS_ATTACH_PIDS;
660 r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
664 conn_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
666 /* Non-activated names are considered not available */
667 if (conn_info->flags & KDBUS_HELLO_ACTIVATOR) {
681 if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
682 if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0) {
687 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
690 r = bus_populate_creds_from_items(bus, conn_info, mask, c);
694 r = bus_creds_add_more(c, mask, 0, 0);
706 kernel_cmd_free(bus, cmd->offset);
710 static int bus_get_name_creds_dbus1(
714 sd_bus_creds **creds) {
716 _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
717 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
718 const char *unique = NULL;
722 /* Only query the owner if the caller wants to know it or if
723 * the caller just wants to check whether a name exists */
724 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
725 r = sd_bus_call_method(
727 "org.freedesktop.DBus",
728 "/org/freedesktop/DBus",
729 "org.freedesktop.DBus",
738 r = sd_bus_message_read(reply_unique, "s", &unique);
748 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
749 c->unique_name = strdup(unique);
753 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
756 if ((mask & SD_BUS_CREDS_PID) ||
757 ((mask & SD_BUS_CREDS_AUGMENT) &&
758 (mask & (SD_BUS_CREDS_PID_STARTTIME|
759 SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
760 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
761 SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
762 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|
763 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
764 SD_BUS_CREDS_SELINUX_CONTEXT|
765 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))) {
769 r = sd_bus_call_method(
771 "org.freedesktop.DBus",
772 "/org/freedesktop/DBus",
773 "org.freedesktop.DBus",
774 "GetConnectionUnixProcessID",
778 unique ? unique : name);
782 r = sd_bus_message_read(reply, "u", &u);
787 if (mask & SD_BUS_CREDS_PID) {
789 c->mask |= SD_BUS_CREDS_PID;
792 reply = sd_bus_message_unref(reply);
795 if (mask & SD_BUS_CREDS_UID) {
798 r = sd_bus_call_method(
800 "org.freedesktop.DBus",
801 "/org/freedesktop/DBus",
802 "org.freedesktop.DBus",
803 "GetConnectionUnixUser",
807 unique ? unique : name);
811 r = sd_bus_message_read(reply, "u", &u);
816 c->mask |= SD_BUS_CREDS_UID;
818 reply = sd_bus_message_unref(reply);
821 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
822 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
823 const void *p = NULL;
826 r = sd_bus_call_method(
828 "org.freedesktop.DBus",
829 "/org/freedesktop/DBus",
830 "org.freedesktop.DBus",
831 "GetConnectionSELinuxSecurityContext",
835 unique ? unique : name);
837 if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
840 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
844 c->label = strndup(p, sz);
848 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
852 r = bus_creds_add_more(c, mask, pid, 0);
865 _public_ int sd_bus_get_name_creds(
869 sd_bus_creds **creds) {
871 assert_return(bus, -EINVAL);
872 assert_return(name, -EINVAL);
873 assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -ENOTSUP);
874 assert_return(mask == 0 || creds, -EINVAL);
875 assert_return(!bus_pid_changed(bus), -ECHILD);
876 assert_return(service_name_is_valid(name), -EINVAL);
877 assert_return(bus->bus_client, -ENODATA);
879 if (!BUS_IS_OPEN(bus->state))
883 return bus_get_name_creds_kdbus(bus, name, mask, creds);
885 return bus_get_name_creds_dbus1(bus, name, mask, creds);
888 _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
889 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
893 assert_return(bus, -EINVAL);
894 assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -ENOTSUP);
895 assert_return(ret, -EINVAL);
896 assert_return(!bus_pid_changed(bus), -ECHILD);
898 if (!BUS_IS_OPEN(bus->state))
901 if (!bus->ucred_valid && !isempty(bus->label))
908 if (bus->ucred_valid) {
909 pid = c->pid = bus->ucred.pid;
910 c->uid = bus->ucred.uid;
911 c->gid = bus->ucred.gid;
913 c->mask |= (SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_GID) & mask;
916 if (!isempty(bus->label) && (mask & SD_BUS_CREDS_SELINUX_CONTEXT)) {
917 c->label = strdup(bus->label);
921 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
924 if (bus->is_kernel) {
925 struct kdbus_cmd_info cmd = {};
926 struct kdbus_info *creator_info;
928 cmd.size = sizeof(cmd);
929 kdbus_translate_attach_flags(mask, (uint64_t*) &cmd.flags);
931 /* If augmentation is on, and the bus doesn't didn't allow us
932 * to get the bits we want, then ask for the PID/TID so that we
933 * can read the rest from /proc. */
934 if ((mask & SD_BUS_CREDS_AUGMENT) &&
935 (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
936 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
937 SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
938 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|
939 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
940 SD_BUS_CREDS_SELINUX_CONTEXT|
941 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
942 cmd.flags |= KDBUS_ATTACH_PIDS;
944 r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
948 creator_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
950 r = bus_populate_creds_from_items(bus, creator_info, mask, c);
951 kernel_cmd_free(bus, cmd.offset);
957 r = bus_creds_add_more(c, mask, pid, 0);
966 static int add_name_change_match(sd_bus *bus,
969 const char *old_owner,
970 const char *new_owner) {
972 uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
973 int is_name_id = -1, r;
974 struct kdbus_item *item;
978 /* If we encounter a match that could match against
979 * NameOwnerChanged messages, then we need to create
980 * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
981 * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
982 * multiple if the match is underspecified.
984 * The NameOwnerChanged signals take three parameters with
985 * unique or well-known names, but only some forms actually
988 * WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD
989 * WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE
990 * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE
991 * UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD
992 * UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE
994 * For the latter two the two unique names must be identical.
999 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
1004 if (!isempty(old_owner)) {
1005 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
1010 if (is_name_id > 0 && old_owner_id != name_id)
1013 old_owner_id = KDBUS_MATCH_ID_ANY;
1015 if (!isempty(new_owner)) {
1016 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
1021 if (is_name_id > 0 && new_owner_id != name_id)
1024 new_owner_id = KDBUS_MATCH_ID_ANY;
1026 if (is_name_id <= 0) {
1027 struct kdbus_cmd_match *m;
1030 /* If the name argument is missing or is a well-known
1031 * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
1034 l = name ? strlen(name) + 1 : 0;
1036 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1037 offsetof(struct kdbus_item, name_change) +
1038 offsetof(struct kdbus_notify_name_change, name) +
1041 m = alloca0_align(sz, 8);
1047 offsetof(struct kdbus_item, name_change) +
1048 offsetof(struct kdbus_notify_name_change, name) +
1051 item->name_change.old_id.id = old_owner_id;
1052 item->name_change.new_id.id = new_owner_id;
1055 memcpy(item->name_change.name, name, l);
1057 /* If the old name is unset or empty, then
1058 * this can match against added names */
1059 if (!old_owner || old_owner[0] == 0) {
1060 item->type = KDBUS_ITEM_NAME_ADD;
1062 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1067 /* If the new name is unset or empty, then
1068 * this can match against removed names */
1069 if (!new_owner || new_owner[0] == 0) {
1070 item->type = KDBUS_ITEM_NAME_REMOVE;
1072 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1077 /* The CHANGE match we need in either case, because
1078 * what is reported as a name change by the kernel
1079 * might just be an owner change between starter and
1080 * normal clients. For userspace such a change should
1081 * be considered a removal/addition, hence let's
1082 * subscribe to this unconditionally. */
1083 item->type = KDBUS_ITEM_NAME_CHANGE;
1084 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1089 if (is_name_id != 0) {
1090 struct kdbus_cmd_match *m;
1093 /* If the name argument is missing or is a unique
1094 * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
1097 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1098 offsetof(struct kdbus_item, id_change) +
1099 sizeof(struct kdbus_notify_id_change));
1101 m = alloca0_align(sz, 8);
1107 offsetof(struct kdbus_item, id_change) +
1108 sizeof(struct kdbus_notify_id_change);
1109 item->id_change.id = name_id;
1111 /* If the old name is unset or empty, then this can
1112 * match against added ids */
1113 if (!old_owner || old_owner[0] == 0) {
1114 item->type = KDBUS_ITEM_ID_ADD;
1116 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1121 /* If thew new name is unset or empty, then this can
1122 * match against removed ids */
1123 if (!new_owner || new_owner[0] == 0) {
1124 item->type = KDBUS_ITEM_ID_REMOVE;
1126 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1135 int bus_add_match_internal_kernel(
1137 struct bus_match_component *components,
1138 unsigned n_components,
1141 struct kdbus_cmd_match *m;
1142 struct kdbus_item *item;
1145 const char *sender = NULL;
1146 size_t sender_length = 0;
1147 uint64_t src_id = KDBUS_MATCH_ID_ANY;
1148 bool using_bloom = false;
1150 bool matches_name_change = true;
1151 const char *name_change_arg[3] = {};
1156 bloom = alloca0(bus->bloom_size);
1158 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
1160 for (i = 0; i < n_components; i++) {
1161 struct bus_match_component *c = &components[i];
1165 case BUS_MATCH_SENDER:
1166 if (!streq(c->value_str, "org.freedesktop.DBus"))
1167 matches_name_change = false;
1169 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
1173 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1175 sender = c->value_str;
1176 sender_length = strlen(sender);
1177 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
1182 case BUS_MATCH_MESSAGE_TYPE:
1183 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
1184 matches_name_change = false;
1186 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
1190 case BUS_MATCH_INTERFACE:
1191 if (!streq(c->value_str, "org.freedesktop.DBus"))
1192 matches_name_change = false;
1194 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1198 case BUS_MATCH_MEMBER:
1199 if (!streq(c->value_str, "NameOwnerChanged"))
1200 matches_name_change = false;
1202 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1206 case BUS_MATCH_PATH:
1207 if (!streq(c->value_str, "/org/freedesktop/DBus"))
1208 matches_name_change = false;
1210 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1214 case BUS_MATCH_PATH_NAMESPACE:
1215 if (!streq(c->value_str, "/")) {
1216 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1221 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1222 char buf[sizeof("arg")-1 + 2 + 1];
1224 if (c->type - BUS_MATCH_ARG < 3)
1225 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1227 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
1228 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1233 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
1234 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1236 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
1237 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1242 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1243 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1245 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1246 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1251 case BUS_MATCH_DESTINATION:
1252 /* The bloom filter does not include
1253 the destination, since it is only
1254 available for broadcast messages
1255 which do not carry a destination
1256 since they are undirected. */
1259 case BUS_MATCH_ROOT:
1260 case BUS_MATCH_VALUE:
1261 case BUS_MATCH_LEAF:
1262 case _BUS_MATCH_NODE_TYPE_MAX:
1263 case _BUS_MATCH_NODE_TYPE_INVALID:
1264 assert_not_reached("Invalid match type?");
1269 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1271 m = alloca0_align(sz, 8);
1277 if (src_id != KDBUS_MATCH_ID_ANY) {
1278 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1279 item->type = KDBUS_ITEM_ID;
1281 item = KDBUS_ITEM_NEXT(item);
1285 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1286 item->type = KDBUS_ITEM_BLOOM_MASK;
1287 memcpy(item->data64, bloom, bus->bloom_size);
1288 item = KDBUS_ITEM_NEXT(item);
1292 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1293 item->type = KDBUS_ITEM_NAME;
1294 memcpy(item->str, sender, sender_length + 1);
1297 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1301 if (matches_name_change) {
1303 /* If this match could theoretically match
1304 * NameOwnerChanged messages, we need to
1305 * install a second non-bloom filter explitly
1308 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1316 #define internal_match(bus, m) \
1317 ((bus)->hello_flags & KDBUS_HELLO_MONITOR \
1318 ? (isempty(m) ? "eavesdrop='true'" : strappenda((m), ",eavesdrop='true'")) \
1321 static int bus_add_match_internal_dbus1(
1323 const char *match) {
1330 e = internal_match(bus, match);
1332 return sd_bus_call_method(
1334 "org.freedesktop.DBus",
1335 "/org/freedesktop/DBus",
1336 "org.freedesktop.DBus",
1344 int bus_add_match_internal(
1347 struct bus_match_component *components,
1348 unsigned n_components,
1354 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1356 return bus_add_match_internal_dbus1(bus, match);
1359 int bus_remove_match_internal_kernel(
1363 struct kdbus_cmd_match m;
1369 m.size = offsetof(struct kdbus_cmd_match, items);
1372 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1379 static int bus_remove_match_internal_dbus1(
1381 const char *match) {
1388 e = internal_match(bus, match);
1390 return sd_bus_call_method(
1392 "org.freedesktop.DBus",
1393 "/org/freedesktop/DBus",
1394 "org.freedesktop.DBus",
1402 int bus_remove_match_internal(
1410 return bus_remove_match_internal_kernel(bus, cookie);
1412 return bus_remove_match_internal_dbus1(bus, match);
1415 _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1416 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1420 assert_return(bus, -EINVAL);
1421 assert_return(name, -EINVAL);
1422 assert_return(machine, -EINVAL);
1423 assert_return(!bus_pid_changed(bus), -ECHILD);
1424 assert_return(service_name_is_valid(name), -EINVAL);
1426 if (!BUS_IS_OPEN(bus->state))
1429 if (streq_ptr(name, bus->unique_name))
1430 return sd_id128_get_machine(machine);
1432 r = sd_bus_message_new_method_call(
1437 "org.freedesktop.DBus.Peer",
1442 r = sd_bus_message_set_auto_start(m, false);
1446 r = sd_bus_call(bus, m, 0, NULL, &reply);
1450 r = sd_bus_message_read(reply, "s", &mid);
1454 return sd_id128_from_string(mid, machine);