2 This file is part of systemd.
4 Copyright 2013 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 #ifdef HAVE_VALGRIND_MEMCHECK_H
21 #include <valgrind/memcheck.h>
29 #include "alloc-util.h"
30 #include "bus-bloom.h"
31 #include "bus-control.h"
32 #include "bus-internal.h"
33 #include "bus-message.h"
35 #include "capability-util.h"
36 #include "stdio-util.h"
37 #include "string-util.h"
39 #include "user-util.h"
41 _public_
int sd_bus_get_unique_name(sd_bus
*bus
, const char **unique
) {
44 assert_return(bus
, -EINVAL
);
45 assert_return(unique
, -EINVAL
);
46 assert_return(!bus_pid_changed(bus
), -ECHILD
);
51 r
= bus_ensure_running(bus
);
55 *unique
= bus
->unique_name
;
59 static int bus_request_name_kernel(sd_bus
*bus
, const char *name
, uint64_t flags
) {
68 size
= offsetof(struct kdbus_cmd
, items
) + KDBUS_ITEM_SIZE(l
);
69 n
= alloca0_align(size
, 8);
71 n
->flags
= request_name_flags_to_kdbus(flags
);
73 n
->items
[0].size
= KDBUS_ITEM_HEADER_SIZE
+ l
;
74 n
->items
[0].type
= KDBUS_ITEM_NAME
;
75 memcpy(n
->items
[0].str
, name
, l
);
77 #ifdef HAVE_VALGRIND_MEMCHECK_H
78 VALGRIND_MAKE_MEM_DEFINED(n
, n
->size
);
81 r
= ioctl(bus
->input_fd
, KDBUS_CMD_NAME_ACQUIRE
, n
);
85 if (n
->return_flags
& KDBUS_NAME_IN_QUEUE
)
91 static int bus_request_name_dbus1(sd_bus
*bus
, const char *name
, uint64_t flags
) {
92 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
93 uint32_t ret
, param
= 0;
99 if (flags
& SD_BUS_NAME_ALLOW_REPLACEMENT
)
100 param
|= BUS_NAME_ALLOW_REPLACEMENT
;
101 if (flags
& SD_BUS_NAME_REPLACE_EXISTING
)
102 param
|= BUS_NAME_REPLACE_EXISTING
;
103 if (!(flags
& SD_BUS_NAME_QUEUE
))
104 param
|= BUS_NAME_DO_NOT_QUEUE
;
106 r
= sd_bus_call_method(
108 "org.freedesktop.DBus",
109 "/org/freedesktop/DBus",
110 "org.freedesktop.DBus",
120 r
= sd_bus_message_read(reply
, "u", &ret
);
124 if (ret
== BUS_NAME_ALREADY_OWNER
)
126 else if (ret
== BUS_NAME_EXISTS
)
128 else if (ret
== BUS_NAME_IN_QUEUE
)
130 else if (ret
== BUS_NAME_PRIMARY_OWNER
)
136 _public_
int sd_bus_request_name(sd_bus
*bus
, const char *name
, uint64_t flags
) {
137 assert_return(bus
, -EINVAL
);
138 assert_return(name
, -EINVAL
);
139 assert_return(!bus_pid_changed(bus
), -ECHILD
);
140 assert_return(!(flags
& ~(SD_BUS_NAME_ALLOW_REPLACEMENT
|SD_BUS_NAME_REPLACE_EXISTING
|SD_BUS_NAME_QUEUE
)), -EINVAL
);
141 assert_return(service_name_is_valid(name
), -EINVAL
);
142 assert_return(name
[0] != ':', -EINVAL
);
144 if (!bus
->bus_client
)
147 /* Don't allow requesting the special driver and local names */
148 if (STR_IN_SET(name
, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
151 if (!BUS_IS_OPEN(bus
->state
))
155 return bus_request_name_kernel(bus
, name
, flags
);
157 return bus_request_name_dbus1(bus
, name
, flags
);
160 static int bus_release_name_kernel(sd_bus
*bus
, const char *name
) {
168 l
= strlen(name
) + 1;
169 size
= offsetof(struct kdbus_cmd
, items
) + KDBUS_ITEM_SIZE(l
);
170 n
= alloca0_align(size
, 8);
173 n
->items
[0].size
= KDBUS_ITEM_HEADER_SIZE
+ l
;
174 n
->items
[0].type
= KDBUS_ITEM_NAME
;
175 memcpy(n
->items
[0].str
, name
, l
);
177 #ifdef HAVE_VALGRIND_MEMCHECK_H
178 VALGRIND_MAKE_MEM_DEFINED(n
, n
->size
);
180 r
= ioctl(bus
->input_fd
, KDBUS_CMD_NAME_RELEASE
, n
);
187 static int bus_release_name_dbus1(sd_bus
*bus
, const char *name
) {
188 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
195 r
= sd_bus_call_method(
197 "org.freedesktop.DBus",
198 "/org/freedesktop/DBus",
199 "org.freedesktop.DBus",
208 r
= sd_bus_message_read(reply
, "u", &ret
);
211 if (ret
== BUS_NAME_NON_EXISTENT
)
213 if (ret
== BUS_NAME_NOT_OWNER
)
215 if (ret
== BUS_NAME_RELEASED
)
221 _public_
int sd_bus_release_name(sd_bus
*bus
, const char *name
) {
222 assert_return(bus
, -EINVAL
);
223 assert_return(name
, -EINVAL
);
224 assert_return(!bus_pid_changed(bus
), -ECHILD
);
225 assert_return(service_name_is_valid(name
), -EINVAL
);
226 assert_return(name
[0] != ':', -EINVAL
);
228 if (!bus
->bus_client
)
231 /* Don't allow releasing the special driver and local names */
232 if (STR_IN_SET(name
, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
235 if (!BUS_IS_OPEN(bus
->state
))
239 return bus_release_name_kernel(bus
, name
);
241 return bus_release_name_dbus1(bus
, name
);
244 static int kernel_get_list(sd_bus
*bus
, uint64_t flags
, char ***x
) {
245 struct kdbus_cmd_list cmd
= {
249 struct kdbus_info
*name_list
, *name
;
250 uint64_t previous_id
= 0;
253 /* Caller will free half-constructed list on failure... */
255 r
= ioctl(bus
->input_fd
, KDBUS_CMD_LIST
, &cmd
);
259 name_list
= (struct kdbus_info
*) ((uint8_t *) bus
->kdbus_buffer
+ cmd
.offset
);
261 KDBUS_FOREACH(name
, name_list
, cmd
.list_size
) {
262 struct kdbus_item
*item
;
264 if ((flags
& KDBUS_LIST_UNIQUE
) && name
->id
!= previous_id
&& !(name
->flags
& KDBUS_HELLO_ACTIVATOR
)) {
267 #pragma GCC diagnostic push
268 #pragma GCC diagnostic ignored "-Wformat"
269 if (asprintf(&n
, ":1.%llu", name
->id
) < 0) {
273 #pragma GCC diagnostic pop
275 r
= strv_consume(x
, n
);
279 previous_id
= name
->id
;
282 KDBUS_ITEM_FOREACH(item
, name
, items
) {
283 if (item
->type
== KDBUS_ITEM_OWNED_NAME
) {
284 if (service_name_is_valid(item
->name
.name
)) {
285 r
= strv_extend(x
, item
->name
.name
);
298 bus_kernel_cmd_free(bus
, cmd
.offset
);
302 static int bus_list_names_kernel(sd_bus
*bus
, char ***acquired
, char ***activatable
) {
303 _cleanup_strv_free_
char **x
= NULL
, **y
= NULL
;
307 r
= kernel_get_list(bus
, KDBUS_LIST_UNIQUE
| KDBUS_LIST_NAMES
, &x
);
313 r
= kernel_get_list(bus
, KDBUS_LIST_ACTIVATORS
, &y
);
329 static int bus_list_names_dbus1(sd_bus
*bus
, char ***acquired
, char ***activatable
) {
330 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
331 _cleanup_strv_free_
char **x
= NULL
, **y
= NULL
;
335 r
= sd_bus_call_method(
337 "org.freedesktop.DBus",
338 "/org/freedesktop/DBus",
339 "org.freedesktop.DBus",
347 r
= sd_bus_message_read_strv(reply
, &x
);
351 reply
= sd_bus_message_unref(reply
);
355 r
= sd_bus_call_method(
357 "org.freedesktop.DBus",
358 "/org/freedesktop/DBus",
359 "org.freedesktop.DBus",
360 "ListActivatableNames",
367 r
= sd_bus_message_read_strv(reply
, &y
);
383 _public_
int sd_bus_list_names(sd_bus
*bus
, char ***acquired
, char ***activatable
) {
384 assert_return(bus
, -EINVAL
);
385 assert_return(acquired
|| activatable
, -EINVAL
);
386 assert_return(!bus_pid_changed(bus
), -ECHILD
);
388 if (!bus
->bus_client
)
391 if (!BUS_IS_OPEN(bus
->state
))
395 return bus_list_names_kernel(bus
, acquired
, activatable
);
397 return bus_list_names_dbus1(bus
, acquired
, activatable
);
400 static int bus_populate_creds_from_items(
402 struct kdbus_info
*info
,
406 struct kdbus_item
*item
;
414 KDBUS_ITEM_FOREACH(item
, info
, items
) {
416 switch (item
->type
) {
418 case KDBUS_ITEM_PIDS
:
420 if (mask
& SD_BUS_CREDS_PID
&& item
->pids
.pid
> 0) {
421 c
->pid
= (pid_t
) item
->pids
.pid
;
422 c
->mask
|= SD_BUS_CREDS_PID
;
425 if (mask
& SD_BUS_CREDS_TID
&& item
->pids
.tid
> 0) {
426 c
->tid
= (pid_t
) item
->pids
.tid
;
427 c
->mask
|= SD_BUS_CREDS_TID
;
430 if (mask
& SD_BUS_CREDS_PPID
) {
431 if (item
->pids
.ppid
> 0) {
432 c
->ppid
= (pid_t
) item
->pids
.ppid
;
433 c
->mask
|= SD_BUS_CREDS_PPID
;
434 } else if (item
->pids
.pid
== 1) {
435 /* The structure doesn't
436 * really distinguish the case
437 * where a process has no
438 * parent and where we don't
439 * know it because it could
440 * not be translated due to
441 * namespaces. However, we
442 * know that PID 1 has no
443 * parent process, hence let's
444 * patch that in, manually. */
446 c
->mask
|= SD_BUS_CREDS_PPID
;
452 case KDBUS_ITEM_CREDS
:
454 if (mask
& SD_BUS_CREDS_UID
&& (uid_t
) item
->creds
.uid
!= UID_INVALID
) {
455 c
->uid
= (uid_t
) item
->creds
.uid
;
456 c
->mask
|= SD_BUS_CREDS_UID
;
459 if (mask
& SD_BUS_CREDS_EUID
&& (uid_t
) item
->creds
.euid
!= UID_INVALID
) {
460 c
->euid
= (uid_t
) item
->creds
.euid
;
461 c
->mask
|= SD_BUS_CREDS_EUID
;
464 if (mask
& SD_BUS_CREDS_SUID
&& (uid_t
) item
->creds
.suid
!= UID_INVALID
) {
465 c
->suid
= (uid_t
) item
->creds
.suid
;
466 c
->mask
|= SD_BUS_CREDS_SUID
;
469 if (mask
& SD_BUS_CREDS_FSUID
&& (uid_t
) item
->creds
.fsuid
!= UID_INVALID
) {
470 c
->fsuid
= (uid_t
) item
->creds
.fsuid
;
471 c
->mask
|= SD_BUS_CREDS_FSUID
;
474 if (mask
& SD_BUS_CREDS_GID
&& (gid_t
) item
->creds
.gid
!= GID_INVALID
) {
475 c
->gid
= (gid_t
) item
->creds
.gid
;
476 c
->mask
|= SD_BUS_CREDS_GID
;
479 if (mask
& SD_BUS_CREDS_EGID
&& (gid_t
) item
->creds
.egid
!= GID_INVALID
) {
480 c
->egid
= (gid_t
) item
->creds
.egid
;
481 c
->mask
|= SD_BUS_CREDS_EGID
;
484 if (mask
& SD_BUS_CREDS_SGID
&& (gid_t
) item
->creds
.sgid
!= GID_INVALID
) {
485 c
->sgid
= (gid_t
) item
->creds
.sgid
;
486 c
->mask
|= SD_BUS_CREDS_SGID
;
489 if (mask
& SD_BUS_CREDS_FSGID
&& (gid_t
) item
->creds
.fsgid
!= GID_INVALID
) {
490 c
->fsgid
= (gid_t
) item
->creds
.fsgid
;
491 c
->mask
|= SD_BUS_CREDS_FSGID
;
496 case KDBUS_ITEM_PID_COMM
:
497 if (mask
& SD_BUS_CREDS_COMM
) {
498 r
= free_and_strdup(&c
->comm
, item
->str
);
502 c
->mask
|= SD_BUS_CREDS_COMM
;
506 case KDBUS_ITEM_TID_COMM
:
507 if (mask
& SD_BUS_CREDS_TID_COMM
) {
508 r
= free_and_strdup(&c
->tid_comm
, item
->str
);
512 c
->mask
|= SD_BUS_CREDS_TID_COMM
;
517 if (mask
& SD_BUS_CREDS_EXE
) {
518 r
= free_and_strdup(&c
->exe
, item
->str
);
522 c
->mask
|= SD_BUS_CREDS_EXE
;
526 case KDBUS_ITEM_CMDLINE
:
527 if (mask
& SD_BUS_CREDS_CMDLINE
) {
528 c
->cmdline_size
= item
->size
- offsetof(struct kdbus_item
, data
);
529 c
->cmdline
= memdup(item
->data
, c
->cmdline_size
);
533 c
->mask
|= SD_BUS_CREDS_CMDLINE
;
537 case KDBUS_ITEM_CGROUP
:
538 m
= (SD_BUS_CREDS_CGROUP
| SD_BUS_CREDS_UNIT
|
539 SD_BUS_CREDS_USER_UNIT
| SD_BUS_CREDS_SLICE
|
540 SD_BUS_CREDS_SESSION
| SD_BUS_CREDS_OWNER_UID
) & mask
;
543 r
= free_and_strdup(&c
->cgroup
, item
->str
);
547 r
= bus_get_root_path(bus
);
551 r
= free_and_strdup(&c
->cgroup_root
, bus
->cgroup_root
);
559 case KDBUS_ITEM_CAPS
:
560 m
= (SD_BUS_CREDS_EFFECTIVE_CAPS
| SD_BUS_CREDS_PERMITTED_CAPS
|
561 SD_BUS_CREDS_INHERITABLE_CAPS
| SD_BUS_CREDS_BOUNDING_CAPS
) & mask
;
564 if (item
->caps
.last_cap
!= cap_last_cap() ||
565 item
->size
- offsetof(struct kdbus_item
, caps
.caps
) < DIV_ROUND_UP(item
->caps
.last_cap
, 32U) * 4 * 4)
568 c
->capability
= memdup(item
->caps
.caps
, item
->size
- offsetof(struct kdbus_item
, caps
.caps
));
576 case KDBUS_ITEM_SECLABEL
:
577 if (mask
& SD_BUS_CREDS_SELINUX_CONTEXT
) {
578 r
= free_and_strdup(&c
->label
, item
->str
);
582 c
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
586 case KDBUS_ITEM_AUDIT
:
587 if (mask
& SD_BUS_CREDS_AUDIT_SESSION_ID
) {
588 c
->audit_session_id
= (uint32_t) item
->audit
.sessionid
;
589 c
->mask
|= SD_BUS_CREDS_AUDIT_SESSION_ID
;
592 if (mask
& SD_BUS_CREDS_AUDIT_LOGIN_UID
) {
593 c
->audit_login_uid
= (uid_t
) item
->audit
.loginuid
;
594 c
->mask
|= SD_BUS_CREDS_AUDIT_LOGIN_UID
;
598 case KDBUS_ITEM_OWNED_NAME
:
599 if ((mask
& SD_BUS_CREDS_WELL_KNOWN_NAMES
) && service_name_is_valid(item
->name
.name
)) {
600 r
= strv_extend(&c
->well_known_names
, item
->name
.name
);
604 c
->mask
|= SD_BUS_CREDS_WELL_KNOWN_NAMES
;
608 case KDBUS_ITEM_CONN_DESCRIPTION
:
609 if (mask
& SD_BUS_CREDS_DESCRIPTION
) {
610 r
= free_and_strdup(&c
->description
, item
->str
);
614 c
->mask
|= SD_BUS_CREDS_DESCRIPTION
;
618 case KDBUS_ITEM_AUXGROUPS
:
619 if (mask
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
) {
623 n
= (item
->size
- offsetof(struct kdbus_item
, data64
)) / sizeof(uint64_t);
628 for (i
= 0; i
< n
; i
++)
629 g
[i
] = item
->data64
[i
];
631 free(c
->supplementary_gids
);
632 c
->supplementary_gids
= g
;
633 c
->n_supplementary_gids
= n
;
635 c
->mask
|= SD_BUS_CREDS_SUPPLEMENTARY_GIDS
;
644 int bus_get_name_creds_kdbus(
648 bool allow_activator
,
649 sd_bus_creds
**creds
) {
651 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*c
= NULL
;
652 struct kdbus_cmd_info
*cmd
;
653 struct kdbus_info
*conn_info
;
658 if (streq(name
, "org.freedesktop.DBus"))
661 r
= bus_kernel_parse_unique_name(name
, &id
);
665 size
= offsetof(struct kdbus_cmd_info
, items
);
666 cmd
= alloca0_align(size
, 8);
669 l
= strlen(name
) + 1;
670 size
= offsetof(struct kdbus_cmd_info
, items
) + KDBUS_ITEM_SIZE(l
);
671 cmd
= alloca0_align(size
, 8);
672 cmd
->items
[0].size
= KDBUS_ITEM_HEADER_SIZE
+ l
;
673 cmd
->items
[0].type
= KDBUS_ITEM_NAME
;
674 memcpy(cmd
->items
[0].str
, name
, l
);
677 /* If augmentation is on, and the bus didn't provide us
678 * the bits we want, then ask for the PID/TID so that we
679 * can read the rest from /proc. */
680 if ((mask
& SD_BUS_CREDS_AUGMENT
) &&
681 (mask
& (SD_BUS_CREDS_PPID
|
682 SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
|
683 SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
|
684 SD_BUS_CREDS_SUPPLEMENTARY_GIDS
|
685 SD_BUS_CREDS_COMM
|SD_BUS_CREDS_TID_COMM
|SD_BUS_CREDS_EXE
|SD_BUS_CREDS_CMDLINE
|
686 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
|
687 SD_BUS_CREDS_EFFECTIVE_CAPS
|SD_BUS_CREDS_PERMITTED_CAPS
|SD_BUS_CREDS_INHERITABLE_CAPS
|SD_BUS_CREDS_BOUNDING_CAPS
|
688 SD_BUS_CREDS_SELINUX_CONTEXT
|
689 SD_BUS_CREDS_AUDIT_SESSION_ID
|SD_BUS_CREDS_AUDIT_LOGIN_UID
)))
690 mask
|= SD_BUS_CREDS_PID
;
693 cmd
->attach_flags
= attach_flags_to_kdbus(mask
);
695 r
= ioctl(bus
->input_fd
, KDBUS_CMD_CONN_INFO
, cmd
);
699 conn_info
= (struct kdbus_info
*) ((uint8_t *) bus
->kdbus_buffer
+ cmd
->offset
);
701 /* Non-activated names are considered not available */
702 if (!allow_activator
&& (conn_info
->flags
& KDBUS_HELLO_ACTIVATOR
)) {
716 if (mask
& SD_BUS_CREDS_UNIQUE_NAME
) {
717 #pragma GCC diagnostic push
718 #pragma GCC diagnostic ignored "-Wformat"
719 if (asprintf(&c
->unique_name
, ":1.%llu", conn_info
->id
) < 0) {
723 #pragma GCC diagnostic pop
725 c
->mask
|= SD_BUS_CREDS_UNIQUE_NAME
;
728 /* If KDBUS_ITEM_OWNED_NAME is requested then we'll get 0 of
729 them in case the service has no names. This does not mean
730 however that the list of owned names could not be
731 acquired. Hence, let's explicitly clarify that the data is
733 c
->mask
|= mask
& SD_BUS_CREDS_WELL_KNOWN_NAMES
;
735 r
= bus_populate_creds_from_items(bus
, conn_info
, mask
, c
);
739 r
= bus_creds_add_more(c
, mask
, 0, 0);
751 bus_kernel_cmd_free(bus
, cmd
->offset
);
755 static int bus_get_name_creds_dbus1(
759 sd_bus_creds
**creds
) {
761 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply_unique
= NULL
, *reply
= NULL
;
762 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*c
= NULL
;
763 const char *unique
= NULL
;
767 /* Only query the owner if the caller wants to know it or if
768 * the caller just wants to check whether a name exists */
769 if ((mask
& SD_BUS_CREDS_UNIQUE_NAME
) || mask
== 0) {
770 r
= sd_bus_call_method(
772 "org.freedesktop.DBus",
773 "/org/freedesktop/DBus",
774 "org.freedesktop.DBus",
783 r
= sd_bus_message_read(reply_unique
, "s", &unique
);
789 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
790 bool need_pid
, need_uid
, need_selinux
, need_separate_calls
;
795 if ((mask
& SD_BUS_CREDS_UNIQUE_NAME
) && unique
) {
796 c
->unique_name
= strdup(unique
);
800 c
->mask
|= SD_BUS_CREDS_UNIQUE_NAME
;
803 need_pid
= (mask
& SD_BUS_CREDS_PID
) ||
804 ((mask
& SD_BUS_CREDS_AUGMENT
) &&
805 (mask
& (SD_BUS_CREDS_UID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
|
806 SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
|
807 SD_BUS_CREDS_SUPPLEMENTARY_GIDS
|
808 SD_BUS_CREDS_COMM
|SD_BUS_CREDS_EXE
|SD_BUS_CREDS_CMDLINE
|
809 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
|
810 SD_BUS_CREDS_EFFECTIVE_CAPS
|SD_BUS_CREDS_PERMITTED_CAPS
|SD_BUS_CREDS_INHERITABLE_CAPS
|SD_BUS_CREDS_BOUNDING_CAPS
|
811 SD_BUS_CREDS_SELINUX_CONTEXT
|
812 SD_BUS_CREDS_AUDIT_SESSION_ID
|SD_BUS_CREDS_AUDIT_LOGIN_UID
)));
813 need_uid
= mask
& SD_BUS_CREDS_EUID
;
814 need_selinux
= mask
& SD_BUS_CREDS_SELINUX_CONTEXT
;
816 if (need_pid
+ need_uid
+ need_selinux
> 1) {
818 /* If we need more than one of the credentials, then use GetConnectionCredentials() */
820 r
= sd_bus_call_method(
822 "org.freedesktop.DBus",
823 "/org/freedesktop/DBus",
824 "org.freedesktop.DBus",
825 "GetConnectionCredentials",
833 if (!sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
))
836 /* If we got an unknown method error, fall back to the invidual calls... */
837 need_separate_calls
= true;
838 sd_bus_error_free(&error
);
841 need_separate_calls
= false;
843 r
= sd_bus_message_enter_container(reply
, 'a', "{sv}");
850 r
= sd_bus_message_enter_container(reply
, 'e', "sv");
856 r
= sd_bus_message_read(reply
, "s", &m
);
860 if (need_uid
&& streq(m
, "UnixUserID")) {
863 r
= sd_bus_message_read(reply
, "v", "u", &u
);
868 c
->mask
|= SD_BUS_CREDS_EUID
;
870 } else if (need_pid
&& streq(m
, "ProcessID")) {
873 r
= sd_bus_message_read(reply
, "v", "u", &p
);
878 if (mask
& SD_BUS_CREDS_PID
) {
880 c
->mask
|= SD_BUS_CREDS_PID
;
883 } else if (need_selinux
&& streq(m
, "LinuxSecurityLabel")) {
884 const void *p
= NULL
;
887 r
= sd_bus_message_enter_container(reply
, 'v', "ay");
891 r
= sd_bus_message_read_array(reply
, 'y', &p
, &sz
);
896 c
->label
= strndup(p
, sz
);
900 c
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
902 r
= sd_bus_message_exit_container(reply
);
906 r
= sd_bus_message_skip(reply
, "v");
911 r
= sd_bus_message_exit_container(reply
);
916 r
= sd_bus_message_exit_container(reply
);
920 if (need_pid
&& pid
== 0)
924 } else /* When we only need a single field, then let's use separate calls */
925 need_separate_calls
= true;
927 if (need_separate_calls
) {
931 r
= sd_bus_call_method(
933 "org.freedesktop.DBus",
934 "/org/freedesktop/DBus",
935 "org.freedesktop.DBus",
936 "GetConnectionUnixProcessID",
944 r
= sd_bus_message_read(reply
, "u", &u
);
949 if (mask
& SD_BUS_CREDS_PID
) {
951 c
->mask
|= SD_BUS_CREDS_PID
;
954 reply
= sd_bus_message_unref(reply
);
960 r
= sd_bus_call_method(
962 "org.freedesktop.DBus",
963 "/org/freedesktop/DBus",
964 "org.freedesktop.DBus",
965 "GetConnectionUnixUser",
969 unique
? unique
: name
);
973 r
= sd_bus_message_read(reply
, "u", &u
);
978 c
->mask
|= SD_BUS_CREDS_EUID
;
980 reply
= sd_bus_message_unref(reply
);
984 const void *p
= NULL
;
987 r
= sd_bus_call_method(
989 "org.freedesktop.DBus",
990 "/org/freedesktop/DBus",
991 "org.freedesktop.DBus",
992 "GetConnectionSELinuxSecurityContext",
996 unique
? unique
: name
);
998 if (!sd_bus_error_has_name(&error
, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
1001 /* no data is fine */
1003 r
= sd_bus_message_read_array(reply
, 'y', &p
, &sz
);
1007 c
->label
= strndup(p
, sz
);
1011 c
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
1016 r
= bus_creds_add_more(c
, mask
, pid
, 0);
1029 _public_
int sd_bus_get_name_creds(
1033 sd_bus_creds
**creds
) {
1035 assert_return(bus
, -EINVAL
);
1036 assert_return(name
, -EINVAL
);
1037 assert_return((mask
& ~SD_BUS_CREDS_AUGMENT
) <= _SD_BUS_CREDS_ALL
, -EOPNOTSUPP
);
1038 assert_return(mask
== 0 || creds
, -EINVAL
);
1039 assert_return(!bus_pid_changed(bus
), -ECHILD
);
1040 assert_return(service_name_is_valid(name
), -EINVAL
);
1042 if (!bus
->bus_client
)
1045 if (streq(name
, "org.freedesktop.DBus.Local"))
1048 if (streq(name
, "org.freedesktop.DBus"))
1049 return sd_bus_get_owner_creds(bus
, mask
, creds
);
1051 if (!BUS_IS_OPEN(bus
->state
))
1055 return bus_get_name_creds_kdbus(bus
, name
, mask
, false, creds
);
1057 return bus_get_name_creds_dbus1(bus
, name
, mask
, creds
);
1060 static int bus_get_owner_creds_kdbus(sd_bus
*bus
, uint64_t mask
, sd_bus_creds
**ret
) {
1061 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*c
= NULL
;
1062 struct kdbus_cmd_info cmd
= {
1063 .size
= sizeof(struct kdbus_cmd_info
),
1065 struct kdbus_info
*creator_info
;
1069 c
= bus_creds_new();
1073 /* If augmentation is on, and the bus doesn't didn't allow us
1074 * to get the bits we want, then ask for the PID/TID so that we
1075 * can read the rest from /proc. */
1076 if ((mask
& SD_BUS_CREDS_AUGMENT
) &&
1077 (mask
& (SD_BUS_CREDS_PPID
|
1078 SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
|
1079 SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
|
1080 SD_BUS_CREDS_SUPPLEMENTARY_GIDS
|
1081 SD_BUS_CREDS_COMM
|SD_BUS_CREDS_TID_COMM
|SD_BUS_CREDS_EXE
|SD_BUS_CREDS_CMDLINE
|
1082 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
|
1083 SD_BUS_CREDS_EFFECTIVE_CAPS
|SD_BUS_CREDS_PERMITTED_CAPS
|SD_BUS_CREDS_INHERITABLE_CAPS
|SD_BUS_CREDS_BOUNDING_CAPS
|
1084 SD_BUS_CREDS_SELINUX_CONTEXT
|
1085 SD_BUS_CREDS_AUDIT_SESSION_ID
|SD_BUS_CREDS_AUDIT_LOGIN_UID
)))
1086 mask
|= SD_BUS_CREDS_PID
;
1088 cmd
.attach_flags
= attach_flags_to_kdbus(mask
);
1090 r
= ioctl(bus
->input_fd
, KDBUS_CMD_BUS_CREATOR_INFO
, &cmd
);
1094 creator_info
= (struct kdbus_info
*) ((uint8_t *) bus
->kdbus_buffer
+ cmd
.offset
);
1096 r
= bus_populate_creds_from_items(bus
, creator_info
, mask
, c
);
1097 bus_kernel_cmd_free(bus
, cmd
.offset
);
1101 r
= bus_creds_add_more(c
, mask
, pid
, 0);
1110 static int bus_get_owner_creds_dbus1(sd_bus
*bus
, uint64_t mask
, sd_bus_creds
**ret
) {
1111 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*c
= NULL
;
1118 do_label
= bus
->label
&& (mask
& SD_BUS_CREDS_SELINUX_CONTEXT
);
1120 /* Avoid allocating anything if we have no chance of returning useful data */
1121 if (!bus
->ucred_valid
&& !do_label
)
1124 c
= bus_creds_new();
1128 if (bus
->ucred_valid
) {
1129 if (bus
->ucred
.pid
> 0) {
1130 pid
= c
->pid
= bus
->ucred
.pid
;
1131 c
->mask
|= SD_BUS_CREDS_PID
& mask
;
1134 if (bus
->ucred
.uid
!= UID_INVALID
) {
1135 c
->euid
= bus
->ucred
.uid
;
1136 c
->mask
|= SD_BUS_CREDS_EUID
& mask
;
1139 if (bus
->ucred
.gid
!= GID_INVALID
) {
1140 c
->egid
= bus
->ucred
.gid
;
1141 c
->mask
|= SD_BUS_CREDS_EGID
& mask
;
1146 c
->label
= strdup(bus
->label
);
1150 c
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
1153 r
= bus_creds_add_more(c
, mask
, pid
, 0);
1162 _public_
int sd_bus_get_owner_creds(sd_bus
*bus
, uint64_t mask
, sd_bus_creds
**ret
) {
1163 assert_return(bus
, -EINVAL
);
1164 assert_return((mask
& ~SD_BUS_CREDS_AUGMENT
) <= _SD_BUS_CREDS_ALL
, -EOPNOTSUPP
);
1165 assert_return(ret
, -EINVAL
);
1166 assert_return(!bus_pid_changed(bus
), -ECHILD
);
1168 if (!BUS_IS_OPEN(bus
->state
))
1172 return bus_get_owner_creds_kdbus(bus
, mask
, ret
);
1174 return bus_get_owner_creds_dbus1(bus
, mask
, ret
);
1177 static int add_name_change_match(sd_bus
*bus
,
1180 const char *old_owner
,
1181 const char *new_owner
) {
1183 uint64_t name_id
= KDBUS_MATCH_ID_ANY
, old_owner_id
= 0, new_owner_id
= 0;
1184 int is_name_id
= -1, r
;
1185 struct kdbus_item
*item
;
1189 /* If we encounter a match that could match against
1190 * NameOwnerChanged messages, then we need to create
1191 * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
1192 * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
1193 * multiple if the match is underspecified.
1195 * The NameOwnerChanged signals take three parameters with
1196 * unique or well-known names, but only some forms actually
1199 * WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD
1200 * WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE
1201 * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE
1202 * UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD
1203 * UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE
1205 * For the latter two the two unique names must be identical.
1210 is_name_id
= bus_kernel_parse_unique_name(name
, &name_id
);
1215 if (!isempty(old_owner
)) {
1216 r
= bus_kernel_parse_unique_name(old_owner
, &old_owner_id
);
1221 if (is_name_id
> 0 && old_owner_id
!= name_id
)
1224 old_owner_id
= KDBUS_MATCH_ID_ANY
;
1226 if (!isempty(new_owner
)) {
1227 r
= bus_kernel_parse_unique_name(new_owner
, &new_owner_id
);
1232 if (is_name_id
> 0 && new_owner_id
!= name_id
)
1235 new_owner_id
= KDBUS_MATCH_ID_ANY
;
1237 if (is_name_id
<= 0) {
1238 struct kdbus_cmd_match
*m
;
1241 /* If the name argument is missing or is a well-known
1242 * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
1245 l
= name
? strlen(name
) + 1 : 0;
1247 sz
= ALIGN8(offsetof(struct kdbus_cmd_match
, items
) +
1248 offsetof(struct kdbus_item
, name_change
) +
1249 offsetof(struct kdbus_notify_name_change
, name
) +
1252 m
= alloca0_align(sz
, 8);
1258 offsetof(struct kdbus_item
, name_change
) +
1259 offsetof(struct kdbus_notify_name_change
, name
) +
1262 item
->name_change
.old_id
.id
= old_owner_id
;
1263 item
->name_change
.new_id
.id
= new_owner_id
;
1265 memcpy_safe(item
->name_change
.name
, name
, l
);
1267 /* If the old name is unset or empty, then
1268 * this can match against added names */
1269 if (isempty(old_owner
)) {
1270 item
->type
= KDBUS_ITEM_NAME_ADD
;
1272 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1277 /* If the new name is unset or empty, then
1278 * this can match against removed names */
1279 if (isempty(new_owner
)) {
1280 item
->type
= KDBUS_ITEM_NAME_REMOVE
;
1282 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1287 /* The CHANGE match we need in either case, because
1288 * what is reported as a name change by the kernel
1289 * might just be an owner change between starter and
1290 * normal clients. For userspace such a change should
1291 * be considered a removal/addition, hence let's
1292 * subscribe to this unconditionally. */
1293 item
->type
= KDBUS_ITEM_NAME_CHANGE
;
1294 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1299 if (is_name_id
!= 0) {
1300 struct kdbus_cmd_match
*m
;
1303 /* If the name argument is missing or is a unique
1304 * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
1307 sz
= ALIGN8(offsetof(struct kdbus_cmd_match
, items
) +
1308 offsetof(struct kdbus_item
, id_change
) +
1309 sizeof(struct kdbus_notify_id_change
));
1311 m
= alloca0_align(sz
, 8);
1317 offsetof(struct kdbus_item
, id_change
) +
1318 sizeof(struct kdbus_notify_id_change
);
1319 item
->id_change
.id
= name_id
;
1321 /* If the old name is unset or empty, then this can
1322 * match against added ids */
1323 if (isempty(old_owner
)) {
1324 item
->type
= KDBUS_ITEM_ID_ADD
;
1325 if (!isempty(new_owner
))
1326 item
->id_change
.id
= new_owner_id
;
1328 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1333 /* If thew new name is unset or empty, then this can
1334 * match against removed ids */
1335 if (isempty(new_owner
)) {
1336 item
->type
= KDBUS_ITEM_ID_REMOVE
;
1337 if (!isempty(old_owner
))
1338 item
->id_change
.id
= old_owner_id
;
1340 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1349 int bus_add_match_internal_kernel(
1351 struct bus_match_component
*components
,
1352 unsigned n_components
,
1355 struct kdbus_cmd_match
*m
;
1356 struct kdbus_item
*item
;
1359 const char *sender
= NULL
;
1360 size_t sender_length
= 0;
1361 uint64_t src_id
= KDBUS_MATCH_ID_ANY
, dst_id
= KDBUS_MATCH_ID_ANY
;
1362 bool using_bloom
= false;
1364 bool matches_name_change
= true;
1365 const char *name_change_arg
[3] = {};
1370 /* Monitor streams don't support matches, make this a NOP */
1371 if (bus
->hello_flags
& KDBUS_HELLO_MONITOR
)
1374 bloom
= alloca0(bus
->bloom_size
);
1376 sz
= ALIGN8(offsetof(struct kdbus_cmd_match
, items
));
1378 for (i
= 0; i
< n_components
; i
++) {
1379 struct bus_match_component
*c
= &components
[i
];
1383 case BUS_MATCH_SENDER
:
1384 if (!streq(c
->value_str
, "org.freedesktop.DBus"))
1385 matches_name_change
= false;
1387 r
= bus_kernel_parse_unique_name(c
->value_str
, &src_id
);
1391 sz
+= ALIGN8(offsetof(struct kdbus_item
, id
) + sizeof(uint64_t));
1393 sender
= c
->value_str
;
1394 sender_length
= strlen(sender
);
1395 sz
+= ALIGN8(offsetof(struct kdbus_item
, str
) + sender_length
+ 1);
1400 case BUS_MATCH_MESSAGE_TYPE
:
1401 if (c
->value_u8
!= SD_BUS_MESSAGE_SIGNAL
)
1402 matches_name_change
= false;
1404 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, "message-type", bus_message_type_to_string(c
->value_u8
));
1408 case BUS_MATCH_INTERFACE
:
1409 if (!streq(c
->value_str
, "org.freedesktop.DBus"))
1410 matches_name_change
= false;
1412 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, "interface", c
->value_str
);
1416 case BUS_MATCH_MEMBER
:
1417 if (!streq(c
->value_str
, "NameOwnerChanged"))
1418 matches_name_change
= false;
1420 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, "member", c
->value_str
);
1424 case BUS_MATCH_PATH
:
1425 if (!streq(c
->value_str
, "/org/freedesktop/DBus"))
1426 matches_name_change
= false;
1428 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, "path", c
->value_str
);
1432 case BUS_MATCH_PATH_NAMESPACE
:
1433 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, "path-slash-prefix", c
->value_str
);
1437 case BUS_MATCH_ARG
...BUS_MATCH_ARG_LAST
: {
1438 char buf
[sizeof("arg")-1 + 2 + 1];
1440 if (c
->type
- BUS_MATCH_ARG
< 3)
1441 name_change_arg
[c
->type
- BUS_MATCH_ARG
] = c
->value_str
;
1443 xsprintf(buf
, "arg%i", c
->type
- BUS_MATCH_ARG
);
1444 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, buf
, c
->value_str
);
1449 case BUS_MATCH_ARG_HAS
...BUS_MATCH_ARG_HAS_LAST
: {
1450 char buf
[sizeof("arg")-1 + 2 + sizeof("-has")];
1452 xsprintf(buf
, "arg%i-has", c
->type
- BUS_MATCH_ARG_HAS
);
1453 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, buf
, c
->value_str
);
1458 case BUS_MATCH_ARG_PATH
...BUS_MATCH_ARG_PATH_LAST
:
1460 * XXX: DBus spec defines arg[0..63]path= matching to be
1461 * a two-way glob. That is, if either string is a prefix
1462 * of the other, it matches.
1463 * This is really hard to realize in bloom-filters, as
1464 * we would have to create a bloom-match for each prefix
1465 * of @c->value_str. This is excessive, hence we just
1466 * ignore all those matches and accept everything from
1467 * the kernel. People should really avoid those matches.
1468 * If they're used in real-life some day, we will have
1469 * to properly support multiple-matches here.
1473 case BUS_MATCH_ARG_NAMESPACE
...BUS_MATCH_ARG_NAMESPACE_LAST
: {
1474 char buf
[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1476 xsprintf(buf
, "arg%i-dot-prefix", c
->type
- BUS_MATCH_ARG_NAMESPACE
);
1477 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, buf
, c
->value_str
);
1482 case BUS_MATCH_DESTINATION
:
1484 * Kernel only supports matching on destination IDs, but
1485 * not on destination names. So just skip the
1486 * destination name restriction and verify it in
1487 * user-space on retrieval.
1489 r
= bus_kernel_parse_unique_name(c
->value_str
, &dst_id
);
1493 sz
+= ALIGN8(offsetof(struct kdbus_item
, id
) + sizeof(uint64_t));
1495 /* if not a broadcast, it cannot be a name-change */
1496 if (r
<= 0 || dst_id
!= KDBUS_DST_ID_BROADCAST
)
1497 matches_name_change
= false;
1501 case BUS_MATCH_ROOT
:
1502 case BUS_MATCH_VALUE
:
1503 case BUS_MATCH_LEAF
:
1504 case _BUS_MATCH_NODE_TYPE_MAX
:
1505 case _BUS_MATCH_NODE_TYPE_INVALID
:
1506 assert_not_reached("Invalid match type?");
1511 sz
+= ALIGN8(offsetof(struct kdbus_item
, data64
) + bus
->bloom_size
);
1513 m
= alloca0_align(sz
, 8);
1519 if (src_id
!= KDBUS_MATCH_ID_ANY
) {
1520 item
->size
= offsetof(struct kdbus_item
, id
) + sizeof(uint64_t);
1521 item
->type
= KDBUS_ITEM_ID
;
1523 item
= KDBUS_ITEM_NEXT(item
);
1526 if (dst_id
!= KDBUS_MATCH_ID_ANY
) {
1527 item
->size
= offsetof(struct kdbus_item
, id
) + sizeof(uint64_t);
1528 item
->type
= KDBUS_ITEM_DST_ID
;
1530 item
= KDBUS_ITEM_NEXT(item
);
1534 item
->size
= offsetof(struct kdbus_item
, data64
) + bus
->bloom_size
;
1535 item
->type
= KDBUS_ITEM_BLOOM_MASK
;
1536 memcpy(item
->data64
, bloom
, bus
->bloom_size
);
1537 item
= KDBUS_ITEM_NEXT(item
);
1541 item
->size
= offsetof(struct kdbus_item
, str
) + sender_length
+ 1;
1542 item
->type
= KDBUS_ITEM_NAME
;
1543 memcpy(item
->str
, sender
, sender_length
+ 1);
1546 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1550 if (matches_name_change
) {
1552 /* If this match could theoretically match
1553 * NameOwnerChanged messages, we need to
1554 * install a second non-bloom filter explitly
1557 r
= add_name_change_match(bus
, cookie
, name_change_arg
[0], name_change_arg
[1], name_change_arg
[2]);
1565 #define internal_match(bus, m) \
1566 ((bus)->hello_flags & KDBUS_HELLO_MONITOR \
1567 ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
1570 static int bus_add_match_internal_dbus1(
1572 const char *match
) {
1579 e
= internal_match(bus
, match
);
1581 return sd_bus_call_method(
1583 "org.freedesktop.DBus",
1584 "/org/freedesktop/DBus",
1585 "org.freedesktop.DBus",
1593 int bus_add_match_internal(
1596 struct bus_match_component
*components
,
1597 unsigned n_components
,
1602 if (!bus
->bus_client
)
1606 return bus_add_match_internal_kernel(bus
, components
, n_components
, cookie
);
1608 return bus_add_match_internal_dbus1(bus
, match
);
1611 int bus_remove_match_internal_kernel(
1615 struct kdbus_cmd_match m
= {
1616 .size
= offsetof(struct kdbus_cmd_match
, items
),
1623 /* Monitor streams don't support matches, make this a NOP */
1624 if (bus
->hello_flags
& KDBUS_HELLO_MONITOR
)
1627 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_REMOVE
, &m
);
1634 static int bus_remove_match_internal_dbus1(
1636 const char *match
) {
1643 e
= internal_match(bus
, match
);
1645 return sd_bus_call_method(
1647 "org.freedesktop.DBus",
1648 "/org/freedesktop/DBus",
1649 "org.freedesktop.DBus",
1657 int bus_remove_match_internal(
1664 if (!bus
->bus_client
)
1668 return bus_remove_match_internal_kernel(bus
, cookie
);
1670 return bus_remove_match_internal_dbus1(bus
, match
);
1673 _public_
int sd_bus_get_name_machine_id(sd_bus
*bus
, const char *name
, sd_id128_t
*machine
) {
1674 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
1678 assert_return(bus
, -EINVAL
);
1679 assert_return(name
, -EINVAL
);
1680 assert_return(machine
, -EINVAL
);
1681 assert_return(!bus_pid_changed(bus
), -ECHILD
);
1682 assert_return(service_name_is_valid(name
), -EINVAL
);
1684 if (!bus
->bus_client
)
1687 if (!BUS_IS_OPEN(bus
->state
))
1690 if (streq_ptr(name
, bus
->unique_name
))
1691 return sd_id128_get_machine(machine
);
1693 r
= sd_bus_message_new_method_call(
1698 "org.freedesktop.DBus.Peer",
1703 r
= sd_bus_message_set_auto_start(m
, false);
1707 r
= sd_bus_call(bus
, m
, 0, NULL
, &reply
);
1711 r
= sd_bus_message_read(reply
, "s", &mid
);
1715 return sd_id128_from_string(mid
, machine
);