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 r = bus_populate_creds_from_items(bus, conn_info, mask, c);
699 r = bus_creds_add_more(c, mask, 0, 0);
711 kernel_cmd_free(bus, cmd->offset);
715 static int bus_get_name_creds_dbus1(
719 sd_bus_creds **creds) {
721 _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
722 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
723 const char *unique = NULL;
727 /* Only query the owner if the caller wants to know it or if
728 * the caller just wants to check whether a name exists */
729 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
730 r = sd_bus_call_method(
732 "org.freedesktop.DBus",
733 "/org/freedesktop/DBus",
734 "org.freedesktop.DBus",
743 r = sd_bus_message_read(reply_unique, "s", &unique);
753 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
754 c->unique_name = strdup(unique);
758 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
761 if ((mask & SD_BUS_CREDS_PID) ||
762 ((mask & SD_BUS_CREDS_AUGMENT) &&
763 (mask & (SD_BUS_CREDS_PID_STARTTIME|
764 SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
765 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
766 SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
767 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|
768 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
769 SD_BUS_CREDS_SELINUX_CONTEXT|
770 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))) {
774 r = sd_bus_call_method(
776 "org.freedesktop.DBus",
777 "/org/freedesktop/DBus",
778 "org.freedesktop.DBus",
779 "GetConnectionUnixProcessID",
783 unique ? unique : name);
787 r = sd_bus_message_read(reply, "u", &u);
792 if (mask & SD_BUS_CREDS_PID) {
794 c->mask |= SD_BUS_CREDS_PID;
797 reply = sd_bus_message_unref(reply);
800 if (mask & SD_BUS_CREDS_UID) {
803 r = sd_bus_call_method(
805 "org.freedesktop.DBus",
806 "/org/freedesktop/DBus",
807 "org.freedesktop.DBus",
808 "GetConnectionUnixUser",
812 unique ? unique : name);
816 r = sd_bus_message_read(reply, "u", &u);
821 c->mask |= SD_BUS_CREDS_UID;
823 reply = sd_bus_message_unref(reply);
826 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
827 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
828 const void *p = NULL;
831 r = sd_bus_call_method(
833 "org.freedesktop.DBus",
834 "/org/freedesktop/DBus",
835 "org.freedesktop.DBus",
836 "GetConnectionSELinuxSecurityContext",
840 unique ? unique : name);
842 if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
845 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
849 c->label = strndup(p, sz);
853 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
857 r = bus_creds_add_more(c, mask, pid, 0);
870 _public_ int sd_bus_get_name_creds(
874 sd_bus_creds **creds) {
876 assert_return(bus, -EINVAL);
877 assert_return(name, -EINVAL);
878 assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -ENOTSUP);
879 assert_return(mask == 0 || creds, -EINVAL);
880 assert_return(!bus_pid_changed(bus), -ECHILD);
881 assert_return(service_name_is_valid(name), -EINVAL);
882 assert_return(bus->bus_client, -ENODATA);
884 if (!BUS_IS_OPEN(bus->state))
888 return bus_get_name_creds_kdbus(bus, name, mask, creds);
890 return bus_get_name_creds_dbus1(bus, name, mask, creds);
893 _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
894 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
898 assert_return(bus, -EINVAL);
899 assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -ENOTSUP);
900 assert_return(ret, -EINVAL);
901 assert_return(!bus_pid_changed(bus), -ECHILD);
903 if (!BUS_IS_OPEN(bus->state))
906 if (!bus->ucred_valid && !isempty(bus->label))
913 if (bus->ucred_valid) {
914 pid = c->pid = bus->ucred.pid;
915 c->uid = bus->ucred.uid;
916 c->gid = bus->ucred.gid;
918 c->mask |= (SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_GID) & mask;
921 if (!isempty(bus->label) && (mask & SD_BUS_CREDS_SELINUX_CONTEXT)) {
922 c->label = strdup(bus->label);
926 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
929 if (bus->is_kernel) {
930 struct kdbus_cmd_info cmd = {};
931 struct kdbus_info *creator_info;
933 cmd.size = sizeof(cmd);
934 cmd.flags = attach_flags_to_kdbus(mask);
936 /* If augmentation is on, and the bus doesn't didn't allow us
937 * to get the bits we want, then ask for the PID/TID so that we
938 * can read the rest from /proc. */
939 if ((mask & SD_BUS_CREDS_AUGMENT) &&
940 (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
941 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
942 SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
943 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|
944 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
945 SD_BUS_CREDS_SELINUX_CONTEXT|
946 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
947 cmd.flags |= KDBUS_ATTACH_PIDS;
949 r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
953 creator_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
955 r = bus_populate_creds_from_items(bus, creator_info, mask, c);
956 kernel_cmd_free(bus, cmd.offset);
962 r = bus_creds_add_more(c, mask, pid, 0);
971 static int add_name_change_match(sd_bus *bus,
974 const char *old_owner,
975 const char *new_owner) {
977 uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
978 int is_name_id = -1, r;
979 struct kdbus_item *item;
983 /* If we encounter a match that could match against
984 * NameOwnerChanged messages, then we need to create
985 * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
986 * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
987 * multiple if the match is underspecified.
989 * The NameOwnerChanged signals take three parameters with
990 * unique or well-known names, but only some forms actually
993 * WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD
994 * WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE
995 * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE
996 * UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD
997 * UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE
999 * For the latter two the two unique names must be identical.
1004 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
1009 if (!isempty(old_owner)) {
1010 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
1015 if (is_name_id > 0 && old_owner_id != name_id)
1018 old_owner_id = KDBUS_MATCH_ID_ANY;
1020 if (!isempty(new_owner)) {
1021 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
1026 if (is_name_id > 0 && new_owner_id != name_id)
1029 new_owner_id = KDBUS_MATCH_ID_ANY;
1031 if (is_name_id <= 0) {
1032 struct kdbus_cmd_match *m;
1035 /* If the name argument is missing or is a well-known
1036 * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
1039 l = name ? strlen(name) + 1 : 0;
1041 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1042 offsetof(struct kdbus_item, name_change) +
1043 offsetof(struct kdbus_notify_name_change, name) +
1046 m = alloca0_align(sz, 8);
1052 offsetof(struct kdbus_item, name_change) +
1053 offsetof(struct kdbus_notify_name_change, name) +
1056 item->name_change.old_id.id = old_owner_id;
1057 item->name_change.new_id.id = new_owner_id;
1060 memcpy(item->name_change.name, name, l);
1062 /* If the old name is unset or empty, then
1063 * this can match against added names */
1064 if (!old_owner || old_owner[0] == 0) {
1065 item->type = KDBUS_ITEM_NAME_ADD;
1067 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1072 /* If the new name is unset or empty, then
1073 * this can match against removed names */
1074 if (!new_owner || new_owner[0] == 0) {
1075 item->type = KDBUS_ITEM_NAME_REMOVE;
1077 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1082 /* The CHANGE match we need in either case, because
1083 * what is reported as a name change by the kernel
1084 * might just be an owner change between starter and
1085 * normal clients. For userspace such a change should
1086 * be considered a removal/addition, hence let's
1087 * subscribe to this unconditionally. */
1088 item->type = KDBUS_ITEM_NAME_CHANGE;
1089 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1094 if (is_name_id != 0) {
1095 struct kdbus_cmd_match *m;
1098 /* If the name argument is missing or is a unique
1099 * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
1102 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1103 offsetof(struct kdbus_item, id_change) +
1104 sizeof(struct kdbus_notify_id_change));
1106 m = alloca0_align(sz, 8);
1112 offsetof(struct kdbus_item, id_change) +
1113 sizeof(struct kdbus_notify_id_change);
1114 item->id_change.id = name_id;
1116 /* If the old name is unset or empty, then this can
1117 * match against added ids */
1118 if (!old_owner || old_owner[0] == 0) {
1119 item->type = KDBUS_ITEM_ID_ADD;
1121 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1126 /* If thew new name is unset or empty, then this can
1127 * match against removed ids */
1128 if (!new_owner || new_owner[0] == 0) {
1129 item->type = KDBUS_ITEM_ID_REMOVE;
1131 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1140 int bus_add_match_internal_kernel(
1142 struct bus_match_component *components,
1143 unsigned n_components,
1146 struct kdbus_cmd_match *m;
1147 struct kdbus_item *item;
1150 const char *sender = NULL;
1151 size_t sender_length = 0;
1152 uint64_t src_id = KDBUS_MATCH_ID_ANY;
1153 bool using_bloom = false;
1155 bool matches_name_change = true;
1156 const char *name_change_arg[3] = {};
1161 bloom = alloca0(bus->bloom_size);
1163 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
1165 for (i = 0; i < n_components; i++) {
1166 struct bus_match_component *c = &components[i];
1170 case BUS_MATCH_SENDER:
1171 if (!streq(c->value_str, "org.freedesktop.DBus"))
1172 matches_name_change = false;
1174 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
1178 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1180 sender = c->value_str;
1181 sender_length = strlen(sender);
1182 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
1187 case BUS_MATCH_MESSAGE_TYPE:
1188 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
1189 matches_name_change = false;
1191 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
1195 case BUS_MATCH_INTERFACE:
1196 if (!streq(c->value_str, "org.freedesktop.DBus"))
1197 matches_name_change = false;
1199 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1203 case BUS_MATCH_MEMBER:
1204 if (!streq(c->value_str, "NameOwnerChanged"))
1205 matches_name_change = false;
1207 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1211 case BUS_MATCH_PATH:
1212 if (!streq(c->value_str, "/org/freedesktop/DBus"))
1213 matches_name_change = false;
1215 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1219 case BUS_MATCH_PATH_NAMESPACE:
1220 if (!streq(c->value_str, "/")) {
1221 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1226 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1227 char buf[sizeof("arg")-1 + 2 + 1];
1229 if (c->type - BUS_MATCH_ARG < 3)
1230 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1232 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
1233 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1238 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
1239 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1241 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
1242 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1247 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1248 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1250 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1251 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1256 case BUS_MATCH_DESTINATION:
1257 /* The bloom filter does not include
1258 the destination, since it is only
1259 available for broadcast messages
1260 which do not carry a destination
1261 since they are undirected. */
1264 case BUS_MATCH_ROOT:
1265 case BUS_MATCH_VALUE:
1266 case BUS_MATCH_LEAF:
1267 case _BUS_MATCH_NODE_TYPE_MAX:
1268 case _BUS_MATCH_NODE_TYPE_INVALID:
1269 assert_not_reached("Invalid match type?");
1274 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1276 m = alloca0_align(sz, 8);
1282 if (src_id != KDBUS_MATCH_ID_ANY) {
1283 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1284 item->type = KDBUS_ITEM_ID;
1286 item = KDBUS_ITEM_NEXT(item);
1290 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1291 item->type = KDBUS_ITEM_BLOOM_MASK;
1292 memcpy(item->data64, bloom, bus->bloom_size);
1293 item = KDBUS_ITEM_NEXT(item);
1297 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1298 item->type = KDBUS_ITEM_NAME;
1299 memcpy(item->str, sender, sender_length + 1);
1302 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1306 if (matches_name_change) {
1308 /* If this match could theoretically match
1309 * NameOwnerChanged messages, we need to
1310 * install a second non-bloom filter explitly
1313 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1321 #define internal_match(bus, m) \
1322 ((bus)->hello_flags & KDBUS_HELLO_MONITOR \
1323 ? (isempty(m) ? "eavesdrop='true'" : strappenda((m), ",eavesdrop='true'")) \
1326 static int bus_add_match_internal_dbus1(
1328 const char *match) {
1335 e = internal_match(bus, match);
1337 return sd_bus_call_method(
1339 "org.freedesktop.DBus",
1340 "/org/freedesktop/DBus",
1341 "org.freedesktop.DBus",
1349 int bus_add_match_internal(
1352 struct bus_match_component *components,
1353 unsigned n_components,
1359 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1361 return bus_add_match_internal_dbus1(bus, match);
1364 int bus_remove_match_internal_kernel(
1368 struct kdbus_cmd_match m;
1374 m.size = offsetof(struct kdbus_cmd_match, items);
1377 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1384 static int bus_remove_match_internal_dbus1(
1386 const char *match) {
1393 e = internal_match(bus, match);
1395 return sd_bus_call_method(
1397 "org.freedesktop.DBus",
1398 "/org/freedesktop/DBus",
1399 "org.freedesktop.DBus",
1407 int bus_remove_match_internal(
1415 return bus_remove_match_internal_kernel(bus, cookie);
1417 return bus_remove_match_internal_dbus1(bus, match);
1420 _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1421 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1425 assert_return(bus, -EINVAL);
1426 assert_return(name, -EINVAL);
1427 assert_return(machine, -EINVAL);
1428 assert_return(!bus_pid_changed(bus), -ECHILD);
1429 assert_return(service_name_is_valid(name), -EINVAL);
1431 if (!BUS_IS_OPEN(bus->state))
1434 if (streq_ptr(name, bus->unique_name))
1435 return sd_id128_get_machine(machine);
1437 r = sd_bus_message_new_method_call(
1442 "org.freedesktop.DBus.Peer",
1447 r = sd_bus_message_set_auto_start(m, false);
1451 r = sd_bus_call(bus, m, 0, NULL, &reply);
1455 r = sd_bus_message_read(reply, "s", &mid);
1459 return sd_id128_from_string(mid, machine);