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>
32 #include "bus-internal.h"
33 #include "bus-message.h"
34 #include "bus-control.h"
35 #include "bus-bloom.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 _public_ int sd_bus_request_name(sd_bus *bus, const char *name, int flags) {
54 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
58 assert_return(bus, -EINVAL);
59 assert_return(name, -EINVAL);
60 assert_return(bus->bus_client, -EINVAL);
61 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
62 assert_return(!bus_pid_changed(bus), -ECHILD);
65 struct kdbus_cmd_name *n;
69 n = alloca0(offsetof(struct kdbus_cmd_name, name) + l + 1);
70 n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
71 kdbus_translate_request_name_flags(flags, (uint64_t *) &n->flags);
72 memcpy(n->name, name, l+1);
74 #ifdef HAVE_VALGRIND_MEMCHECK_H
75 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
78 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
80 if (errno == -EALREADY)
81 return SD_BUS_NAME_ALREADY_OWNER;
84 return SD_BUS_NAME_EXISTS;
89 if (n->flags & KDBUS_NAME_IN_QUEUE)
90 return SD_BUS_NAME_IN_QUEUE;
92 return SD_BUS_NAME_PRIMARY_OWNER;
94 r = sd_bus_call_method(
96 "org.freedesktop.DBus",
98 "org.freedesktop.DBus",
108 r = sd_bus_message_read(reply, "u", &ret);
116 _public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
117 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
121 assert_return(bus, -EINVAL);
122 assert_return(name, -EINVAL);
123 assert_return(bus->bus_client, -EINVAL);
124 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
125 assert_return(!bus_pid_changed(bus), -ECHILD);
127 if (bus->is_kernel) {
128 struct kdbus_cmd_name *n;
132 n = alloca0(offsetof(struct kdbus_cmd_name, name) + l + 1);
133 n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
134 memcpy(n->name, name, l+1);
136 #ifdef HAVE_VALGRIND_MEMCHECK_H
137 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
139 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
145 r = sd_bus_call_method(
147 "org.freedesktop.DBus",
149 "org.freedesktop.DBus",
158 r = sd_bus_message_read(reply, "u", &ret);
166 _public_ int sd_bus_list_names(sd_bus *bus, char ***l) {
167 _cleanup_bus_message_unref_ sd_bus_message *reply1 = NULL, *reply2 = NULL;
171 assert_return(bus, -EINVAL);
172 assert_return(l, -EINVAL);
173 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
174 assert_return(!bus_pid_changed(bus), -ECHILD);
176 if (bus->is_kernel) {
177 _cleanup_free_ struct kdbus_cmd_name_list *cmd = NULL;
178 struct kdbus_name_list *name_list;
179 struct kdbus_cmd_name *name;
181 cmd = malloc0(sizeof(struct kdbus_cmd_name_list *));
185 cmd->flags = KDBUS_NAME_LIST_UNIQUE_NAMES;
187 r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_NAME_LIST, cmd);
191 name_list = (struct kdbus_name_list *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
193 KDBUS_PART_FOREACH(name, name_list, names) {
196 if (name->size > sizeof(*name))
199 asprintf(&n, ":1.%llu", (unsigned long long) name->id);
201 r = strv_extend(&x, n);
206 r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_FREE, &cmd->offset);
212 r = sd_bus_call_method(
214 "org.freedesktop.DBus",
216 "org.freedesktop.DBus",
224 r = sd_bus_call_method(
226 "org.freedesktop.DBus",
228 "org.freedesktop.DBus",
229 "ListActivatableNames",
236 r = bus_message_read_strv_extend(reply1, &x);
242 r = bus_message_read_strv_extend(reply2, &x);
254 static int sd_bus_get_owner_dbus(
259 sd_bus_creds **creds) {
261 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
262 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
263 _cleanup_free_ char *unique = NULL;
267 /* Only query the owner if the caller wants to know it or if
268 * the caller just wants to check whether a name exists */
269 if (owner || mask == 0) {
272 r = sd_bus_call_method(
274 "org.freedesktop.DBus",
276 "org.freedesktop.DBus",
285 r = sd_bus_message_read(reply, "s", &found);
289 unique = strdup(found);
293 reply = sd_bus_message_unref(reply);
301 if ((mask & SD_BUS_CREDS_PID) ||
302 mask & ~(SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|SD_BUS_CREDS_SELINUX_CONTEXT)) {
305 r = sd_bus_call_method(
307 "org.freedesktop.DBus",
309 "org.freedesktop.DBus",
310 "GetConnectionUnixProcessID",
318 r = sd_bus_message_read(reply, "u", &u);
323 if (mask & SD_BUS_CREDS_PID) {
325 c->mask |= SD_BUS_CREDS_PID;
328 reply = sd_bus_message_unref(reply);
331 if (mask & SD_BUS_CREDS_UID) {
334 r = sd_bus_call_method(
336 "org.freedesktop.DBus",
338 "org.freedesktop.DBus",
339 "GetConnectionUnixUser",
347 r = sd_bus_message_read(reply, "u", &u);
352 c->mask |= SD_BUS_CREDS_UID;
354 reply = sd_bus_message_unref(reply);
357 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
361 r = sd_bus_call_method(
363 "org.freedesktop.DBus",
365 "org.freedesktop.DBus",
366 "GetConnectionSELinuxSecurityContext",
374 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
378 c->label = strndup(p, sz);
382 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
385 r = bus_creds_add_more(c, mask, pid, 0);
403 static int add_name_change_match(sd_bus *bus,
406 const char *old_owner,
407 const char *new_owner) {
409 uint64_t name_id = 0, old_owner_id = 0, new_owner_id = 0;
410 int is_name_id = -1, r;
411 struct kdbus_item *item;
415 /* If we encounter a match that could match against
416 * NameOwnerChanged messages, then we need to create
417 * KDBUS_MATCH_NAME_{ADD,REMOVE,CHANGE} and
418 * KDBUS_MATCH_ID_{ADD,REMOVE} matches for it, possibly
419 * multiple if the match is underspecified.
421 * The NameOwnerChanged signals take three parameters with
422 * unique or well-known names, but only some forms actually
425 * WELLKNOWN, "", UNIQUE → KDBUS_MATCH_NAME_ADD
426 * WELLKNOWN, UNIQUE, "" → KDBUS_MATCH_NAME_REMOVE
427 * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_MATCH_NAME_CHANGE
428 * UNIQUE, "", UNIQUE → KDBUS_MATCH_ID_ADD
429 * UNIQUE, UNIQUE, "" → KDBUS_MATCH_ID_REMOVE
431 * For the latter two the two unique names must be identical.
436 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
442 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
447 if (is_name_id > 0 && old_owner_id != name_id)
452 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
457 if (is_name_id > 0 && new_owner_id != name_id)
461 if (is_name_id <= 0) {
464 /* If the name argument is missing or is a well-known
465 * name, then add KDBUS_MATCH_NAME_{ADD,REMOVE,CHANGE}
468 l = name ? strlen(name) : 0;
470 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
471 offsetof(struct kdbus_item, name_change) +
472 offsetof(struct kdbus_notify_name_change, name) +
478 struct kdbus_cmd_match match;
484 m.match.cookie = cookie;
485 m.match.src_id = KDBUS_SRC_ID_KERNEL;
487 item = m.match.items;
489 offsetof(struct kdbus_item, name_change) +
490 offsetof(struct kdbus_notify_name_change, name) +
493 item->name_change.old_id = old_owner_id;
494 item->name_change.new_id = new_owner_id;
497 strcpy(item->name_change.name, name);
499 /* If the old name is unset or empty, then
500 * this can match against added names */
501 if (!old_owner || old_owner[0] == 0) {
502 item->type = KDBUS_MATCH_NAME_ADD;
504 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
509 /* If the new name is unset or empty, then
510 * this can match against removed names */
511 if (!new_owner || new_owner[0] == 0) {
512 item->type = KDBUS_MATCH_NAME_REMOVE;
514 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
519 /* If the neither name is explicitly set to
520 * the empty string, then this can match
521 * agains changed names */
522 if (!(old_owner && old_owner[0] == 0) &&
523 !(new_owner && new_owner[0] == 0)) {
524 item->type = KDBUS_MATCH_NAME_CHANGE;
526 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
533 if (is_name_id != 0) {
535 ALIGN8(offsetof(struct kdbus_cmd_match, items) +
536 offsetof(struct kdbus_item, id_change) +
537 sizeof(struct kdbus_notify_id_change));
540 struct kdbus_cmd_match match;
543 /* If the name argument is missing or is a unique
544 * name, then add KDBUS_MATCH_ID_{ADD,REMOVE} matches
550 m.match.cookie = cookie;
551 m.match.src_id = KDBUS_SRC_ID_KERNEL;
553 item = m.match.items;
554 item->size = offsetof(struct kdbus_item, id_change) + sizeof(struct kdbus_notify_id_change);
555 item->id_change.id = name_id;
557 /* If the old name is unset or empty, then this can
558 * match against added ids */
559 if (!old_owner || old_owner[0] == 0) {
560 item->type = KDBUS_MATCH_ID_ADD;
562 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
567 /* If thew new name is unset or empty, then this can
568 match against removed ids */
569 if (!new_owner || new_owner[0] == 0) {
570 item->type = KDBUS_MATCH_ID_REMOVE;
572 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
581 static int kdbus_name_info(
586 sd_bus_creds **creds) {
588 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
589 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
590 _cleanup_free_ struct kdbus_cmd_name_info *cmd = NULL;
591 _cleanup_free_ char *unique = NULL;
592 struct kdbus_name_info *name_info;
593 struct kdbus_item *item;
594 uint64_t attach_flags, m;
598 r = kdbus_translate_attach_flags(mask, &attach_flags);
602 size = sizeof(struct kdbus_cmd_name_info) + strlen(name) + 1;
608 cmd->attach_flags = attach_flags;
609 strcpy(cmd->name, name);
611 r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_NAME_INFO, cmd);
615 name_info = (struct kdbus_name_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
617 asprintf(&unique, ":1.%llu", (unsigned long long) name_info->id);
623 KDBUS_PART_FOREACH(item, name_info, items) {
624 switch (item->type) {
625 case KDBUS_ITEM_CREDS:
626 m = (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID | SD_BUS_CREDS_PID |
627 SD_BUS_CREDS_TID | SD_BUS_CREDS_PID_STARTTIME) & mask;
630 c->uid = item->creds.uid;
631 c->pid = item->creds.pid;
632 c->gid = item->creds.gid;
633 c->tid = item->creds.tid;
634 c->pid_starttime = item->creds.starttime;
639 case KDBUS_ITEM_PID_COMM:
640 if (mask & SD_BUS_CREDS_COMM) {
641 c->comm = strdup(item->str);
645 c->mask |= SD_BUS_CREDS_COMM;
649 case KDBUS_ITEM_TID_COMM:
650 if (mask & SD_BUS_CREDS_TID_COMM) {
651 c->tid_comm = strdup(item->str);
655 c->mask |= SD_BUS_CREDS_TID_COMM;
660 if (mask & SD_BUS_CREDS_EXE) {
661 c->exe = strdup(item->str);
665 c->mask |= SD_BUS_CREDS_EXE;
669 case KDBUS_ITEM_CMDLINE:
670 if (mask & SD_BUS_CREDS_CMDLINE) {
671 c->cmdline_length = item->size - KDBUS_PART_HEADER_SIZE;
672 c->cmdline = memdup(item->data, c->cmdline_length);
676 c->mask |= SD_BUS_CREDS_CMDLINE;
680 case KDBUS_ITEM_CGROUP:
681 m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
682 SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
683 SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
686 c->cgroup = strdup(item->str);
694 case KDBUS_ITEM_CAPS:
695 m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
696 SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
699 c->capability_size = item->size - KDBUS_PART_HEADER_SIZE;
700 c->capability = memdup(item->data, c->capability_size);
708 case KDBUS_ITEM_SECLABEL:
709 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
710 c->label = strdup(item->str);
714 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
718 case KDBUS_ITEM_AUDIT:
719 m = (SD_BUS_CREDS_AUDIT_SESSION_ID | SD_BUS_CREDS_AUDIT_LOGIN_UID) & mask;
722 c->audit_session_id = item->audit.sessionid;
723 c->audit_login_uid = item->audit.loginuid;
730 r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_FREE, &cmd->offset);
747 _public_ int sd_bus_get_owner(
752 sd_bus_creds **creds) {
754 assert_return(bus, -EINVAL);
755 assert_return(name, -EINVAL);
756 assert_return(mask <= _SD_BUS_CREDS_MAX, -ENOTSUP);
757 assert_return(mask == 0 || creds, -EINVAL);
758 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
759 assert_return(!bus_pid_changed(bus), -ECHILD);
762 return kdbus_name_info(bus, name, mask, owner, creds);
764 return sd_bus_get_owner_dbus(bus, name, mask, owner, creds);
767 int bus_add_match_internal(
770 struct bus_match_component *components,
771 unsigned n_components,
779 if (bus->is_kernel) {
780 struct kdbus_cmd_match *m;
781 struct kdbus_item *item;
782 uint64_t bloom[BLOOM_SIZE/8];
784 const char *sender = NULL;
785 size_t sender_length = 0;
786 uint64_t src_id = KDBUS_MATCH_SRC_ID_ANY;
787 bool using_bloom = false;
789 bool matches_name_change = true;
790 const char *name_change_arg[3] = {};
794 sz = offsetof(struct kdbus_cmd_match, items);
796 for (i = 0; i < n_components; i++) {
797 struct bus_match_component *c = &components[i];
801 case BUS_MATCH_SENDER:
802 if (!streq(c->value_str, "org.freedesktop.DBus"))
803 matches_name_change = false;
805 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
810 sender = c->value_str;
811 sender_length = strlen(sender);
812 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
817 case BUS_MATCH_MESSAGE_TYPE:
818 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
819 matches_name_change = false;
821 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(c->value_u8));
825 case BUS_MATCH_INTERFACE:
826 if (!streq(c->value_str, "org.freedesktop.DBus"))
827 matches_name_change = false;
829 bloom_add_pair(bloom, "interface", c->value_str);
833 case BUS_MATCH_MEMBER:
834 if (!streq(c->value_str, "NameOwnerChanged"))
835 matches_name_change = false;
837 bloom_add_pair(bloom, "member", c->value_str);
842 if (!streq(c->value_str, "/org/freedesktop/DBus"))
843 matches_name_change = false;
845 bloom_add_pair(bloom, "path", c->value_str);
849 case BUS_MATCH_PATH_NAMESPACE:
850 if (!streq(c->value_str, "/")) {
851 bloom_add_pair(bloom, "path-slash-prefix", c->value_str);
856 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
857 char buf[sizeof("arg")-1 + 2 + 1];
859 if (c->type - BUS_MATCH_ARG < 3)
860 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
862 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
863 bloom_add_pair(bloom, buf, c->value_str);
868 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
869 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
871 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
872 bloom_add_pair(bloom, buf, c->value_str);
877 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
878 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
880 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
881 bloom_add_pair(bloom, buf, c->value_str);
886 case BUS_MATCH_DESTINATION:
887 /* The bloom filter does not include
888 the destination, since it is only
889 available for broadcast messages
890 which do not carry a destination
891 since they are undirected. */
895 case BUS_MATCH_VALUE:
897 case _BUS_MATCH_NODE_TYPE_MAX:
898 case _BUS_MATCH_NODE_TYPE_INVALID:
899 assert_not_reached("Invalid match type?");
904 sz += ALIGN8(offsetof(struct kdbus_item, data64) + BLOOM_SIZE);
914 item->size = offsetof(struct kdbus_item, data64) + BLOOM_SIZE;
915 item->type = KDBUS_MATCH_BLOOM;
916 memcpy(item->data64, bloom, BLOOM_SIZE);
918 item = KDBUS_PART_NEXT(item);
922 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
923 item->type = KDBUS_MATCH_SRC_NAME;
924 memcpy(item->str, sender, sender_length + 1);
927 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
931 if (matches_name_change) {
933 /* If this match could theoretically match
934 * NameOwnerChanged messages, we need to
935 * install a second non-bloom filter explitly
938 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
945 return sd_bus_call_method(
947 "org.freedesktop.DBus",
949 "org.freedesktop.DBus",
957 int bus_remove_match_internal(
967 if (bus->is_kernel) {
968 struct kdbus_cmd_match m;
971 m.size = offsetof(struct kdbus_cmd_match, items);
974 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
981 return sd_bus_call_method(
983 "org.freedesktop.DBus",
985 "org.freedesktop.DBus",
994 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
995 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
999 assert_return(bus, -EINVAL);
1000 assert_return(name, -EINVAL);
1001 assert_return(machine, -EINVAL);
1002 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
1003 assert_return(!bus_pid_changed(bus), -ECHILD);
1005 if (streq_ptr(name, bus->unique_name))
1006 return sd_id128_get_machine(machine);
1008 r = sd_bus_message_new_method_call(
1012 "org.freedesktop.DBus.Peer",
1013 "GetMachineId", &m);
1017 r = sd_bus_message_set_no_auto_start(m, true);
1021 r = sd_bus_call(bus, m, 0, NULL, &reply);
1025 r = sd_bus_message_read(reply, "s", &mid);
1029 return sd_id128_from_string(mid, machine);