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 - KDBUS_ITEM_HEADER_SIZE;
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;
595 static int bus_get_name_creds_kdbus(
599 sd_bus_creds **creds) {
601 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
602 struct kdbus_cmd_info *cmd;
603 struct kdbus_info *conn_info;
608 r = bus_kernel_parse_unique_name(name, &id);
612 size = offsetof(struct kdbus_cmd_info, items);
613 cmd = alloca0_align(size, 8);
616 l = strlen(name) + 1;
617 size = offsetof(struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(l);
618 cmd = alloca0_align(size, 8);
619 cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
620 cmd->items[0].type = KDBUS_ITEM_NAME;
621 memcpy(cmd->items[0].str, name, l);
625 kdbus_translate_attach_flags(mask, (uint64_t*) &cmd->flags);
627 /* If augmentation is on, and the bus doesn't didn't allow us
628 * to get the bits we want, then ask for the PID/TID so that we
629 * can read the rest from /proc. */
630 if ((mask & SD_BUS_CREDS_AUGMENT) &&
631 (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
632 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
633 SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
634 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|
635 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
636 SD_BUS_CREDS_SELINUX_CONTEXT|
637 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
638 cmd->flags |= KDBUS_ATTACH_PIDS;
640 r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
644 conn_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
646 /* Non-activated names are considered not available */
647 if (conn_info->flags & KDBUS_HELLO_ACTIVATOR) {
661 if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
662 if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0) {
667 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
670 r = bus_populate_creds_from_items(bus, conn_info, mask, c);
674 r = bus_creds_add_more(c, mask, 0, 0);
686 kernel_cmd_free(bus, cmd->offset);
690 static int bus_get_name_creds_dbus1(
694 sd_bus_creds **creds) {
696 _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
697 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
698 const char *unique = NULL;
702 /* Only query the owner if the caller wants to know it or if
703 * the caller just wants to check whether a name exists */
704 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
705 r = sd_bus_call_method(
707 "org.freedesktop.DBus",
708 "/org/freedesktop/DBus",
709 "org.freedesktop.DBus",
718 r = sd_bus_message_read(reply_unique, "s", &unique);
728 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
729 c->unique_name = strdup(unique);
733 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
736 if ((mask & SD_BUS_CREDS_PID) ||
737 ((mask & SD_BUS_CREDS_AUGMENT) &&
738 (mask & (SD_BUS_CREDS_PID_STARTTIME|
739 SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
740 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
741 SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
742 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|
743 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
744 SD_BUS_CREDS_SELINUX_CONTEXT|
745 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))) {
749 r = sd_bus_call_method(
751 "org.freedesktop.DBus",
752 "/org/freedesktop/DBus",
753 "org.freedesktop.DBus",
754 "GetConnectionUnixProcessID",
758 unique ? unique : name);
762 r = sd_bus_message_read(reply, "u", &u);
767 if (mask & SD_BUS_CREDS_PID) {
769 c->mask |= SD_BUS_CREDS_PID;
772 reply = sd_bus_message_unref(reply);
775 if (mask & SD_BUS_CREDS_UID) {
778 r = sd_bus_call_method(
780 "org.freedesktop.DBus",
781 "/org/freedesktop/DBus",
782 "org.freedesktop.DBus",
783 "GetConnectionUnixUser",
787 unique ? unique : name);
791 r = sd_bus_message_read(reply, "u", &u);
796 c->mask |= SD_BUS_CREDS_UID;
798 reply = sd_bus_message_unref(reply);
801 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
802 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
803 const void *p = NULL;
806 r = sd_bus_call_method(
808 "org.freedesktop.DBus",
809 "/org/freedesktop/DBus",
810 "org.freedesktop.DBus",
811 "GetConnectionSELinuxSecurityContext",
815 unique ? unique : name);
817 if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
820 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
824 c->label = strndup(p, sz);
828 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
832 r = bus_creds_add_more(c, mask, pid, 0);
845 _public_ int sd_bus_get_name_creds(
849 sd_bus_creds **creds) {
851 assert_return(bus, -EINVAL);
852 assert_return(name, -EINVAL);
853 assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -ENOTSUP);
854 assert_return(mask == 0 || creds, -EINVAL);
855 assert_return(!bus_pid_changed(bus), -ECHILD);
856 assert_return(service_name_is_valid(name), -EINVAL);
857 assert_return(bus->bus_client, -ENODATA);
859 if (!BUS_IS_OPEN(bus->state))
863 return bus_get_name_creds_kdbus(bus, name, mask, creds);
865 return bus_get_name_creds_dbus1(bus, name, mask, creds);
868 _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
869 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
873 assert_return(bus, -EINVAL);
874 assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -ENOTSUP);
875 assert_return(ret, -EINVAL);
876 assert_return(!bus_pid_changed(bus), -ECHILD);
878 if (!BUS_IS_OPEN(bus->state))
881 if (!bus->ucred_valid && !isempty(bus->label))
888 if (bus->ucred_valid) {
889 pid = c->pid = bus->ucred.pid;
890 c->uid = bus->ucred.uid;
891 c->gid = bus->ucred.gid;
893 c->mask |= (SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_GID) & mask;
896 if (!isempty(bus->label) && (mask & SD_BUS_CREDS_SELINUX_CONTEXT)) {
897 c->label = strdup(bus->label);
901 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
904 if (bus->is_kernel) {
905 struct kdbus_cmd_info cmd = {};
906 struct kdbus_info *creator_info;
908 cmd.size = sizeof(cmd);
909 kdbus_translate_attach_flags(mask, (uint64_t*) &cmd.flags);
911 /* If augmentation is on, and the bus doesn't didn't allow us
912 * to get the bits we want, then ask for the PID/TID so that we
913 * can read the rest from /proc. */
914 if ((mask & SD_BUS_CREDS_AUGMENT) &&
915 (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
916 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
917 SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
918 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|
919 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
920 SD_BUS_CREDS_SELINUX_CONTEXT|
921 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
922 cmd.flags |= KDBUS_ATTACH_PIDS;
924 r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
928 creator_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
930 r = bus_populate_creds_from_items(bus, creator_info, mask, c);
931 kernel_cmd_free(bus, cmd.offset);
937 r = bus_creds_add_more(c, mask, pid, 0);
946 static int add_name_change_match(sd_bus *bus,
949 const char *old_owner,
950 const char *new_owner) {
952 uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
953 int is_name_id = -1, r;
954 struct kdbus_item *item;
958 /* If we encounter a match that could match against
959 * NameOwnerChanged messages, then we need to create
960 * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
961 * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
962 * multiple if the match is underspecified.
964 * The NameOwnerChanged signals take three parameters with
965 * unique or well-known names, but only some forms actually
968 * WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD
969 * WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE
970 * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE
971 * UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD
972 * UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE
974 * For the latter two the two unique names must be identical.
979 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
984 if (!isempty(old_owner)) {
985 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
990 if (is_name_id > 0 && old_owner_id != name_id)
993 old_owner_id = KDBUS_MATCH_ID_ANY;
995 if (!isempty(new_owner)) {
996 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
1001 if (is_name_id > 0 && new_owner_id != name_id)
1004 new_owner_id = KDBUS_MATCH_ID_ANY;
1006 if (is_name_id <= 0) {
1007 struct kdbus_cmd_match *m;
1010 /* If the name argument is missing or is a well-known
1011 * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
1014 l = name ? strlen(name) + 1 : 0;
1016 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1017 offsetof(struct kdbus_item, name_change) +
1018 offsetof(struct kdbus_notify_name_change, name) +
1021 m = alloca0_align(sz, 8);
1027 offsetof(struct kdbus_item, name_change) +
1028 offsetof(struct kdbus_notify_name_change, name) +
1031 item->name_change.old_id.id = old_owner_id;
1032 item->name_change.new_id.id = new_owner_id;
1035 memcpy(item->name_change.name, name, l);
1037 /* If the old name is unset or empty, then
1038 * this can match against added names */
1039 if (!old_owner || old_owner[0] == 0) {
1040 item->type = KDBUS_ITEM_NAME_ADD;
1042 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1047 /* If the new name is unset or empty, then
1048 * this can match against removed names */
1049 if (!new_owner || new_owner[0] == 0) {
1050 item->type = KDBUS_ITEM_NAME_REMOVE;
1052 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1057 /* The CHANGE match we need in either case, because
1058 * what is reported as a name change by the kernel
1059 * might just be an owner change between starter and
1060 * normal clients. For userspace such a change should
1061 * be considered a removal/addition, hence let's
1062 * subscribe to this unconditionally. */
1063 item->type = KDBUS_ITEM_NAME_CHANGE;
1064 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1069 if (is_name_id != 0) {
1070 struct kdbus_cmd_match *m;
1073 /* If the name argument is missing or is a unique
1074 * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
1077 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1078 offsetof(struct kdbus_item, id_change) +
1079 sizeof(struct kdbus_notify_id_change));
1081 m = alloca0_align(sz, 8);
1087 offsetof(struct kdbus_item, id_change) +
1088 sizeof(struct kdbus_notify_id_change);
1089 item->id_change.id = name_id;
1091 /* If the old name is unset or empty, then this can
1092 * match against added ids */
1093 if (!old_owner || old_owner[0] == 0) {
1094 item->type = KDBUS_ITEM_ID_ADD;
1096 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1101 /* If thew new name is unset or empty, then this can
1102 * match against removed ids */
1103 if (!new_owner || new_owner[0] == 0) {
1104 item->type = KDBUS_ITEM_ID_REMOVE;
1106 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1115 int bus_add_match_internal_kernel(
1117 struct bus_match_component *components,
1118 unsigned n_components,
1121 struct kdbus_cmd_match *m;
1122 struct kdbus_item *item;
1125 const char *sender = NULL;
1126 size_t sender_length = 0;
1127 uint64_t src_id = KDBUS_MATCH_ID_ANY;
1128 bool using_bloom = false;
1130 bool matches_name_change = true;
1131 const char *name_change_arg[3] = {};
1136 bloom = alloca0(bus->bloom_size);
1138 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
1140 for (i = 0; i < n_components; i++) {
1141 struct bus_match_component *c = &components[i];
1145 case BUS_MATCH_SENDER:
1146 if (!streq(c->value_str, "org.freedesktop.DBus"))
1147 matches_name_change = false;
1149 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
1153 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1155 sender = c->value_str;
1156 sender_length = strlen(sender);
1157 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
1162 case BUS_MATCH_MESSAGE_TYPE:
1163 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
1164 matches_name_change = false;
1166 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
1170 case BUS_MATCH_INTERFACE:
1171 if (!streq(c->value_str, "org.freedesktop.DBus"))
1172 matches_name_change = false;
1174 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1178 case BUS_MATCH_MEMBER:
1179 if (!streq(c->value_str, "NameOwnerChanged"))
1180 matches_name_change = false;
1182 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1186 case BUS_MATCH_PATH:
1187 if (!streq(c->value_str, "/org/freedesktop/DBus"))
1188 matches_name_change = false;
1190 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1194 case BUS_MATCH_PATH_NAMESPACE:
1195 if (!streq(c->value_str, "/")) {
1196 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1201 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1202 char buf[sizeof("arg")-1 + 2 + 1];
1204 if (c->type - BUS_MATCH_ARG < 3)
1205 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1207 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
1208 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1213 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
1214 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1216 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
1217 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1222 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1223 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1225 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1226 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1231 case BUS_MATCH_DESTINATION:
1232 /* The bloom filter does not include
1233 the destination, since it is only
1234 available for broadcast messages
1235 which do not carry a destination
1236 since they are undirected. */
1239 case BUS_MATCH_ROOT:
1240 case BUS_MATCH_VALUE:
1241 case BUS_MATCH_LEAF:
1242 case _BUS_MATCH_NODE_TYPE_MAX:
1243 case _BUS_MATCH_NODE_TYPE_INVALID:
1244 assert_not_reached("Invalid match type?");
1249 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1251 m = alloca0_align(sz, 8);
1257 if (src_id != KDBUS_MATCH_ID_ANY) {
1258 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1259 item->type = KDBUS_ITEM_ID;
1261 item = KDBUS_ITEM_NEXT(item);
1265 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1266 item->type = KDBUS_ITEM_BLOOM_MASK;
1267 memcpy(item->data64, bloom, bus->bloom_size);
1268 item = KDBUS_ITEM_NEXT(item);
1272 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1273 item->type = KDBUS_ITEM_NAME;
1274 memcpy(item->str, sender, sender_length + 1);
1277 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1281 if (matches_name_change) {
1283 /* If this match could theoretically match
1284 * NameOwnerChanged messages, we need to
1285 * install a second non-bloom filter explitly
1288 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1296 #define internal_match(bus, m) \
1297 ((bus)->hello_flags & KDBUS_HELLO_MONITOR \
1298 ? (isempty(m) ? "eavesdrop='true'" : strappenda((m), ",eavesdrop='true'")) \
1301 static int bus_add_match_internal_dbus1(
1303 const char *match) {
1310 e = internal_match(bus, match);
1312 return sd_bus_call_method(
1314 "org.freedesktop.DBus",
1315 "/org/freedesktop/DBus",
1316 "org.freedesktop.DBus",
1324 int bus_add_match_internal(
1327 struct bus_match_component *components,
1328 unsigned n_components,
1334 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1336 return bus_add_match_internal_dbus1(bus, match);
1339 int bus_remove_match_internal_kernel(
1343 struct kdbus_cmd_match m;
1349 m.size = offsetof(struct kdbus_cmd_match, items);
1352 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1359 static int bus_remove_match_internal_dbus1(
1361 const char *match) {
1368 e = internal_match(bus, match);
1370 return sd_bus_call_method(
1372 "org.freedesktop.DBus",
1373 "/org/freedesktop/DBus",
1374 "org.freedesktop.DBus",
1382 int bus_remove_match_internal(
1390 return bus_remove_match_internal_kernel(bus, cookie);
1392 return bus_remove_match_internal_dbus1(bus, match);
1395 _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1396 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1400 assert_return(bus, -EINVAL);
1401 assert_return(name, -EINVAL);
1402 assert_return(machine, -EINVAL);
1403 assert_return(!bus_pid_changed(bus), -ECHILD);
1404 assert_return(service_name_is_valid(name), -EINVAL);
1406 if (!BUS_IS_OPEN(bus->state))
1409 if (streq_ptr(name, bus->unique_name))
1410 return sd_id128_get_machine(machine);
1412 r = sd_bus_message_new_method_call(
1417 "org.freedesktop.DBus.Peer",
1422 r = sd_bus_message_set_auto_start(m, false);
1426 r = sd_bus_call(bus, m, 0, NULL, &reply);
1430 r = sd_bus_message_read(reply, "s", &mid);
1434 return sd_id128_from_string(mid, machine);