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 "alloc-util.h"
32 #include "bus-bloom.h"
33 #include "bus-control.h"
34 #include "bus-internal.h"
35 #include "bus-message.h"
37 #include "capability-util.h"
38 #include "stdio-util.h"
39 #include "string-util.h"
41 #include "user-util.h"
43 _public_
int sd_bus_get_unique_name(sd_bus
*bus
, const char **unique
) {
46 assert_return(bus
, -EINVAL
);
47 assert_return(unique
, -EINVAL
);
48 assert_return(!bus_pid_changed(bus
), -ECHILD
);
53 r
= bus_ensure_running(bus
);
57 *unique
= bus
->unique_name
;
61 static int bus_request_name_kernel(sd_bus
*bus
, const char *name
, uint64_t flags
) {
70 size
= offsetof(struct kdbus_cmd
, items
) + KDBUS_ITEM_SIZE(l
);
71 n
= alloca0_align(size
, 8);
73 n
->flags
= request_name_flags_to_kdbus(flags
);
75 n
->items
[0].size
= KDBUS_ITEM_HEADER_SIZE
+ l
;
76 n
->items
[0].type
= KDBUS_ITEM_NAME
;
77 memcpy(n
->items
[0].str
, name
, l
);
79 #ifdef HAVE_VALGRIND_MEMCHECK_H
80 VALGRIND_MAKE_MEM_DEFINED(n
, n
->size
);
83 r
= ioctl(bus
->input_fd
, KDBUS_CMD_NAME_ACQUIRE
, n
);
87 if (n
->return_flags
& KDBUS_NAME_IN_QUEUE
)
93 static int bus_request_name_dbus1(sd_bus
*bus
, const char *name
, uint64_t flags
) {
94 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
95 uint32_t ret
, param
= 0;
101 if (flags
& SD_BUS_NAME_ALLOW_REPLACEMENT
)
102 param
|= BUS_NAME_ALLOW_REPLACEMENT
;
103 if (flags
& SD_BUS_NAME_REPLACE_EXISTING
)
104 param
|= BUS_NAME_REPLACE_EXISTING
;
105 if (!(flags
& SD_BUS_NAME_QUEUE
))
106 param
|= BUS_NAME_DO_NOT_QUEUE
;
108 r
= sd_bus_call_method(
110 "org.freedesktop.DBus",
111 "/org/freedesktop/DBus",
112 "org.freedesktop.DBus",
122 r
= sd_bus_message_read(reply
, "u", &ret
);
126 if (ret
== BUS_NAME_ALREADY_OWNER
)
128 else if (ret
== BUS_NAME_EXISTS
)
130 else if (ret
== BUS_NAME_IN_QUEUE
)
132 else if (ret
== BUS_NAME_PRIMARY_OWNER
)
138 _public_
int sd_bus_request_name(sd_bus
*bus
, const char *name
, uint64_t flags
) {
139 assert_return(bus
, -EINVAL
);
140 assert_return(name
, -EINVAL
);
141 assert_return(!bus_pid_changed(bus
), -ECHILD
);
142 assert_return(!(flags
& ~(SD_BUS_NAME_ALLOW_REPLACEMENT
|SD_BUS_NAME_REPLACE_EXISTING
|SD_BUS_NAME_QUEUE
)), -EINVAL
);
143 assert_return(service_name_is_valid(name
), -EINVAL
);
144 assert_return(name
[0] != ':', -EINVAL
);
146 if (!bus
->bus_client
)
149 /* Don't allow requesting the special driver and local names */
150 if (STR_IN_SET(name
, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
153 if (!BUS_IS_OPEN(bus
->state
))
157 return bus_request_name_kernel(bus
, name
, flags
);
159 return bus_request_name_dbus1(bus
, name
, flags
);
162 static int bus_release_name_kernel(sd_bus
*bus
, const char *name
) {
170 l
= strlen(name
) + 1;
171 size
= offsetof(struct kdbus_cmd
, items
) + KDBUS_ITEM_SIZE(l
);
172 n
= alloca0_align(size
, 8);
175 n
->items
[0].size
= KDBUS_ITEM_HEADER_SIZE
+ l
;
176 n
->items
[0].type
= KDBUS_ITEM_NAME
;
177 memcpy(n
->items
[0].str
, name
, l
);
179 #ifdef HAVE_VALGRIND_MEMCHECK_H
180 VALGRIND_MAKE_MEM_DEFINED(n
, n
->size
);
182 r
= ioctl(bus
->input_fd
, KDBUS_CMD_NAME_RELEASE
, n
);
189 static int bus_release_name_dbus1(sd_bus
*bus
, const char *name
) {
190 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
197 r
= sd_bus_call_method(
199 "org.freedesktop.DBus",
200 "/org/freedesktop/DBus",
201 "org.freedesktop.DBus",
210 r
= sd_bus_message_read(reply
, "u", &ret
);
213 if (ret
== BUS_NAME_NON_EXISTENT
)
215 if (ret
== BUS_NAME_NOT_OWNER
)
217 if (ret
== BUS_NAME_RELEASED
)
223 _public_
int sd_bus_release_name(sd_bus
*bus
, const char *name
) {
224 assert_return(bus
, -EINVAL
);
225 assert_return(name
, -EINVAL
);
226 assert_return(!bus_pid_changed(bus
), -ECHILD
);
227 assert_return(service_name_is_valid(name
), -EINVAL
);
228 assert_return(name
[0] != ':', -EINVAL
);
230 if (!bus
->bus_client
)
233 /* Don't allow releasing the special driver and local names */
234 if (STR_IN_SET(name
, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
237 if (!BUS_IS_OPEN(bus
->state
))
241 return bus_release_name_kernel(bus
, name
);
243 return bus_release_name_dbus1(bus
, name
);
246 static int kernel_get_list(sd_bus
*bus
, uint64_t flags
, char ***x
) {
247 struct kdbus_cmd_list cmd
= {
251 struct kdbus_info
*name_list
, *name
;
252 uint64_t previous_id
= 0;
255 /* Caller will free half-constructed list on failure... */
257 r
= ioctl(bus
->input_fd
, KDBUS_CMD_LIST
, &cmd
);
261 name_list
= (struct kdbus_info
*) ((uint8_t *) bus
->kdbus_buffer
+ cmd
.offset
);
263 KDBUS_FOREACH(name
, name_list
, cmd
.list_size
) {
264 struct kdbus_item
*item
;
266 if ((flags
& KDBUS_LIST_UNIQUE
) && name
->id
!= previous_id
&& !(name
->flags
& KDBUS_HELLO_ACTIVATOR
)) {
269 if (asprintf(&n
, ":1.%llu", (unsigned long long) name
->id
) < 0) {
274 r
= strv_consume(x
, n
);
278 previous_id
= name
->id
;
281 KDBUS_ITEM_FOREACH(item
, name
, items
) {
282 if (item
->type
== KDBUS_ITEM_OWNED_NAME
) {
283 if (service_name_is_valid(item
->name
.name
)) {
284 r
= strv_extend(x
, item
->name
.name
);
297 bus_kernel_cmd_free(bus
, cmd
.offset
);
301 static int bus_list_names_kernel(sd_bus
*bus
, char ***acquired
, char ***activatable
) {
302 _cleanup_strv_free_
char **x
= NULL
, **y
= NULL
;
306 r
= kernel_get_list(bus
, KDBUS_LIST_UNIQUE
| KDBUS_LIST_NAMES
, &x
);
312 r
= kernel_get_list(bus
, KDBUS_LIST_ACTIVATORS
, &y
);
328 static int bus_list_names_dbus1(sd_bus
*bus
, char ***acquired
, char ***activatable
) {
329 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
330 _cleanup_strv_free_
char **x
= NULL
, **y
= NULL
;
334 r
= sd_bus_call_method(
336 "org.freedesktop.DBus",
337 "/org/freedesktop/DBus",
338 "org.freedesktop.DBus",
346 r
= sd_bus_message_read_strv(reply
, &x
);
350 reply
= sd_bus_message_unref(reply
);
354 r
= sd_bus_call_method(
356 "org.freedesktop.DBus",
357 "/org/freedesktop/DBus",
358 "org.freedesktop.DBus",
359 "ListActivatableNames",
366 r
= sd_bus_message_read_strv(reply
, &y
);
382 _public_
int sd_bus_list_names(sd_bus
*bus
, char ***acquired
, char ***activatable
) {
383 assert_return(bus
, -EINVAL
);
384 assert_return(acquired
|| activatable
, -EINVAL
);
385 assert_return(!bus_pid_changed(bus
), -ECHILD
);
387 if (!bus
->bus_client
)
390 if (!BUS_IS_OPEN(bus
->state
))
394 return bus_list_names_kernel(bus
, acquired
, activatable
);
396 return bus_list_names_dbus1(bus
, acquired
, activatable
);
399 static int bus_populate_creds_from_items(
401 struct kdbus_info
*info
,
405 struct kdbus_item
*item
;
413 KDBUS_ITEM_FOREACH(item
, info
, items
) {
415 switch (item
->type
) {
417 case KDBUS_ITEM_PIDS
:
419 if (mask
& SD_BUS_CREDS_PID
&& item
->pids
.pid
> 0) {
420 c
->pid
= (pid_t
) item
->pids
.pid
;
421 c
->mask
|= SD_BUS_CREDS_PID
;
424 if (mask
& SD_BUS_CREDS_TID
&& item
->pids
.tid
> 0) {
425 c
->tid
= (pid_t
) item
->pids
.tid
;
426 c
->mask
|= SD_BUS_CREDS_TID
;
429 if (mask
& SD_BUS_CREDS_PPID
) {
430 if (item
->pids
.ppid
> 0) {
431 c
->ppid
= (pid_t
) item
->pids
.ppid
;
432 c
->mask
|= SD_BUS_CREDS_PPID
;
433 } else if (item
->pids
.pid
== 1) {
434 /* The structure doesn't
435 * really distinguish the case
436 * where a process has no
437 * parent and where we don't
438 * know it because it could
439 * not be translated due to
440 * namespaces. However, we
441 * know that PID 1 has no
442 * parent process, hence let's
443 * patch that in, manually. */
445 c
->mask
|= SD_BUS_CREDS_PPID
;
451 case KDBUS_ITEM_CREDS
:
453 if (mask
& SD_BUS_CREDS_UID
&& (uid_t
) item
->creds
.uid
!= UID_INVALID
) {
454 c
->uid
= (uid_t
) item
->creds
.uid
;
455 c
->mask
|= SD_BUS_CREDS_UID
;
458 if (mask
& SD_BUS_CREDS_EUID
&& (uid_t
) item
->creds
.euid
!= UID_INVALID
) {
459 c
->euid
= (uid_t
) item
->creds
.euid
;
460 c
->mask
|= SD_BUS_CREDS_EUID
;
463 if (mask
& SD_BUS_CREDS_SUID
&& (uid_t
) item
->creds
.suid
!= UID_INVALID
) {
464 c
->suid
= (uid_t
) item
->creds
.suid
;
465 c
->mask
|= SD_BUS_CREDS_SUID
;
468 if (mask
& SD_BUS_CREDS_FSUID
&& (uid_t
) item
->creds
.fsuid
!= UID_INVALID
) {
469 c
->fsuid
= (uid_t
) item
->creds
.fsuid
;
470 c
->mask
|= SD_BUS_CREDS_FSUID
;
473 if (mask
& SD_BUS_CREDS_GID
&& (gid_t
) item
->creds
.gid
!= GID_INVALID
) {
474 c
->gid
= (gid_t
) item
->creds
.gid
;
475 c
->mask
|= SD_BUS_CREDS_GID
;
478 if (mask
& SD_BUS_CREDS_EGID
&& (gid_t
) item
->creds
.egid
!= GID_INVALID
) {
479 c
->egid
= (gid_t
) item
->creds
.egid
;
480 c
->mask
|= SD_BUS_CREDS_EGID
;
483 if (mask
& SD_BUS_CREDS_SGID
&& (gid_t
) item
->creds
.sgid
!= GID_INVALID
) {
484 c
->sgid
= (gid_t
) item
->creds
.sgid
;
485 c
->mask
|= SD_BUS_CREDS_SGID
;
488 if (mask
& SD_BUS_CREDS_FSGID
&& (gid_t
) item
->creds
.fsgid
!= GID_INVALID
) {
489 c
->fsgid
= (gid_t
) item
->creds
.fsgid
;
490 c
->mask
|= SD_BUS_CREDS_FSGID
;
495 case KDBUS_ITEM_PID_COMM
:
496 if (mask
& SD_BUS_CREDS_COMM
) {
497 r
= free_and_strdup(&c
->comm
, item
->str
);
501 c
->mask
|= SD_BUS_CREDS_COMM
;
505 case KDBUS_ITEM_TID_COMM
:
506 if (mask
& SD_BUS_CREDS_TID_COMM
) {
507 r
= free_and_strdup(&c
->tid_comm
, item
->str
);
511 c
->mask
|= SD_BUS_CREDS_TID_COMM
;
516 if (mask
& SD_BUS_CREDS_EXE
) {
517 r
= free_and_strdup(&c
->exe
, item
->str
);
521 c
->mask
|= SD_BUS_CREDS_EXE
;
525 case KDBUS_ITEM_CMDLINE
:
526 if (mask
& SD_BUS_CREDS_CMDLINE
) {
527 c
->cmdline_size
= item
->size
- offsetof(struct kdbus_item
, data
);
528 c
->cmdline
= memdup(item
->data
, c
->cmdline_size
);
532 c
->mask
|= SD_BUS_CREDS_CMDLINE
;
536 case KDBUS_ITEM_CGROUP
:
537 m
= (SD_BUS_CREDS_CGROUP
| SD_BUS_CREDS_UNIT
|
538 SD_BUS_CREDS_USER_UNIT
| SD_BUS_CREDS_SLICE
|
539 SD_BUS_CREDS_SESSION
| SD_BUS_CREDS_OWNER_UID
) & mask
;
542 r
= free_and_strdup(&c
->cgroup
, item
->str
);
546 r
= bus_get_root_path(bus
);
550 r
= free_and_strdup(&c
->cgroup_root
, bus
->cgroup_root
);
558 case KDBUS_ITEM_CAPS
:
559 m
= (SD_BUS_CREDS_EFFECTIVE_CAPS
| SD_BUS_CREDS_PERMITTED_CAPS
|
560 SD_BUS_CREDS_INHERITABLE_CAPS
| SD_BUS_CREDS_BOUNDING_CAPS
) & mask
;
563 if (item
->caps
.last_cap
!= cap_last_cap() ||
564 item
->size
- offsetof(struct kdbus_item
, caps
.caps
) < DIV_ROUND_UP(item
->caps
.last_cap
, 32U) * 4 * 4)
567 c
->capability
= memdup(item
->caps
.caps
, item
->size
- offsetof(struct kdbus_item
, caps
.caps
));
575 case KDBUS_ITEM_SECLABEL
:
576 if (mask
& SD_BUS_CREDS_SELINUX_CONTEXT
) {
577 r
= free_and_strdup(&c
->label
, item
->str
);
581 c
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
585 case KDBUS_ITEM_AUDIT
:
586 if (mask
& SD_BUS_CREDS_AUDIT_SESSION_ID
) {
587 c
->audit_session_id
= (uint32_t) item
->audit
.sessionid
;
588 c
->mask
|= SD_BUS_CREDS_AUDIT_SESSION_ID
;
591 if (mask
& SD_BUS_CREDS_AUDIT_LOGIN_UID
) {
592 c
->audit_login_uid
= (uid_t
) item
->audit
.loginuid
;
593 c
->mask
|= SD_BUS_CREDS_AUDIT_LOGIN_UID
;
597 case KDBUS_ITEM_OWNED_NAME
:
598 if ((mask
& SD_BUS_CREDS_WELL_KNOWN_NAMES
) && service_name_is_valid(item
->name
.name
)) {
599 r
= strv_extend(&c
->well_known_names
, item
->name
.name
);
603 c
->mask
|= SD_BUS_CREDS_WELL_KNOWN_NAMES
;
607 case KDBUS_ITEM_CONN_DESCRIPTION
:
608 if (mask
& SD_BUS_CREDS_DESCRIPTION
) {
609 r
= free_and_strdup(&c
->description
, item
->str
);
613 c
->mask
|= SD_BUS_CREDS_DESCRIPTION
;
617 case KDBUS_ITEM_AUXGROUPS
:
618 if (mask
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
) {
622 n
= (item
->size
- offsetof(struct kdbus_item
, data64
)) / sizeof(uint64_t);
627 for (i
= 0; i
< n
; i
++)
628 g
[i
] = item
->data64
[i
];
630 free(c
->supplementary_gids
);
631 c
->supplementary_gids
= g
;
632 c
->n_supplementary_gids
= n
;
634 c
->mask
|= SD_BUS_CREDS_SUPPLEMENTARY_GIDS
;
643 int bus_get_name_creds_kdbus(
647 bool allow_activator
,
648 sd_bus_creds
**creds
) {
650 _cleanup_bus_creds_unref_ sd_bus_creds
*c
= NULL
;
651 struct kdbus_cmd_info
*cmd
;
652 struct kdbus_info
*conn_info
;
657 if (streq(name
, "org.freedesktop.DBus"))
660 r
= bus_kernel_parse_unique_name(name
, &id
);
664 size
= offsetof(struct kdbus_cmd_info
, items
);
665 cmd
= alloca0_align(size
, 8);
668 l
= strlen(name
) + 1;
669 size
= offsetof(struct kdbus_cmd_info
, items
) + KDBUS_ITEM_SIZE(l
);
670 cmd
= alloca0_align(size
, 8);
671 cmd
->items
[0].size
= KDBUS_ITEM_HEADER_SIZE
+ l
;
672 cmd
->items
[0].type
= KDBUS_ITEM_NAME
;
673 memcpy(cmd
->items
[0].str
, name
, l
);
676 /* If augmentation is on, and the bus didn't provide us
677 * the bits we want, then ask for the PID/TID so that we
678 * can read the rest from /proc. */
679 if ((mask
& SD_BUS_CREDS_AUGMENT
) &&
680 (mask
& (SD_BUS_CREDS_PPID
|
681 SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
|
682 SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
|
683 SD_BUS_CREDS_COMM
|SD_BUS_CREDS_TID_COMM
|SD_BUS_CREDS_EXE
|SD_BUS_CREDS_CMDLINE
|
684 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
|
685 SD_BUS_CREDS_EFFECTIVE_CAPS
|SD_BUS_CREDS_PERMITTED_CAPS
|SD_BUS_CREDS_INHERITABLE_CAPS
|SD_BUS_CREDS_BOUNDING_CAPS
|
686 SD_BUS_CREDS_SELINUX_CONTEXT
|
687 SD_BUS_CREDS_AUDIT_SESSION_ID
|SD_BUS_CREDS_AUDIT_LOGIN_UID
)))
688 mask
|= SD_BUS_CREDS_PID
;
691 cmd
->attach_flags
= attach_flags_to_kdbus(mask
);
693 r
= ioctl(bus
->input_fd
, KDBUS_CMD_CONN_INFO
, cmd
);
697 conn_info
= (struct kdbus_info
*) ((uint8_t *) bus
->kdbus_buffer
+ cmd
->offset
);
699 /* Non-activated names are considered not available */
700 if (!allow_activator
&& (conn_info
->flags
& KDBUS_HELLO_ACTIVATOR
)) {
714 if (mask
& SD_BUS_CREDS_UNIQUE_NAME
) {
715 if (asprintf(&c
->unique_name
, ":1.%llu", (unsigned long long) conn_info
->id
) < 0) {
720 c
->mask
|= SD_BUS_CREDS_UNIQUE_NAME
;
723 /* If KDBUS_ITEM_OWNED_NAME is requested then we'll get 0 of
724 them in case the service has no names. This does not mean
725 however that the list of owned names could not be
726 acquired. Hence, let's explicitly clarify that the data is
728 c
->mask
|= mask
& SD_BUS_CREDS_WELL_KNOWN_NAMES
;
730 r
= bus_populate_creds_from_items(bus
, conn_info
, mask
, c
);
734 r
= bus_creds_add_more(c
, mask
, 0, 0);
746 bus_kernel_cmd_free(bus
, cmd
->offset
);
750 static int bus_get_name_creds_dbus1(
754 sd_bus_creds
**creds
) {
756 _cleanup_bus_message_unref_ sd_bus_message
*reply_unique
= NULL
, *reply
= NULL
;
757 _cleanup_bus_creds_unref_ sd_bus_creds
*c
= NULL
;
758 const char *unique
= NULL
;
762 /* Only query the owner if the caller wants to know it or if
763 * the caller just wants to check whether a name exists */
764 if ((mask
& SD_BUS_CREDS_UNIQUE_NAME
) || mask
== 0) {
765 r
= sd_bus_call_method(
767 "org.freedesktop.DBus",
768 "/org/freedesktop/DBus",
769 "org.freedesktop.DBus",
778 r
= sd_bus_message_read(reply_unique
, "s", &unique
);
788 if ((mask
& SD_BUS_CREDS_UNIQUE_NAME
) && unique
) {
789 c
->unique_name
= strdup(unique
);
793 c
->mask
|= SD_BUS_CREDS_UNIQUE_NAME
;
796 if ((mask
& SD_BUS_CREDS_PID
) ||
797 ((mask
& SD_BUS_CREDS_AUGMENT
) &&
798 (mask
& (SD_BUS_CREDS_UID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
|
799 SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
|
800 SD_BUS_CREDS_COMM
|SD_BUS_CREDS_EXE
|SD_BUS_CREDS_CMDLINE
|
801 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
|
802 SD_BUS_CREDS_EFFECTIVE_CAPS
|SD_BUS_CREDS_PERMITTED_CAPS
|SD_BUS_CREDS_INHERITABLE_CAPS
|SD_BUS_CREDS_BOUNDING_CAPS
|
803 SD_BUS_CREDS_SELINUX_CONTEXT
|
804 SD_BUS_CREDS_AUDIT_SESSION_ID
|SD_BUS_CREDS_AUDIT_LOGIN_UID
)))) {
808 r
= sd_bus_call_method(
810 "org.freedesktop.DBus",
811 "/org/freedesktop/DBus",
812 "org.freedesktop.DBus",
813 "GetConnectionUnixProcessID",
817 unique
? unique
: name
);
821 r
= sd_bus_message_read(reply
, "u", &u
);
826 if (mask
& SD_BUS_CREDS_PID
) {
828 c
->mask
|= SD_BUS_CREDS_PID
;
831 reply
= sd_bus_message_unref(reply
);
834 if (mask
& SD_BUS_CREDS_EUID
) {
837 r
= sd_bus_call_method(
839 "org.freedesktop.DBus",
840 "/org/freedesktop/DBus",
841 "org.freedesktop.DBus",
842 "GetConnectionUnixUser",
846 unique
? unique
: name
);
850 r
= sd_bus_message_read(reply
, "u", &u
);
855 c
->mask
|= SD_BUS_CREDS_EUID
;
857 reply
= sd_bus_message_unref(reply
);
860 if (mask
& SD_BUS_CREDS_SELINUX_CONTEXT
) {
861 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
862 const void *p
= NULL
;
865 r
= sd_bus_call_method(
867 "org.freedesktop.DBus",
868 "/org/freedesktop/DBus",
869 "org.freedesktop.DBus",
870 "GetConnectionSELinuxSecurityContext",
874 unique
? unique
: name
);
876 if (!sd_bus_error_has_name(&error
, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
879 r
= sd_bus_message_read_array(reply
, 'y', &p
, &sz
);
883 c
->label
= strndup(p
, sz
);
887 c
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
891 r
= bus_creds_add_more(c
, mask
, pid
, 0);
904 _public_
int sd_bus_get_name_creds(
908 sd_bus_creds
**creds
) {
910 assert_return(bus
, -EINVAL
);
911 assert_return(name
, -EINVAL
);
912 assert_return((mask
& ~SD_BUS_CREDS_AUGMENT
) <= _SD_BUS_CREDS_ALL
, -EOPNOTSUPP
);
913 assert_return(mask
== 0 || creds
, -EINVAL
);
914 assert_return(!bus_pid_changed(bus
), -ECHILD
);
915 assert_return(service_name_is_valid(name
), -EINVAL
);
917 if (!bus
->bus_client
)
920 if (streq(name
, "org.freedesktop.DBus.Local"))
923 if (!BUS_IS_OPEN(bus
->state
))
927 return bus_get_name_creds_kdbus(bus
, name
, mask
, false, creds
);
929 return bus_get_name_creds_dbus1(bus
, name
, mask
, creds
);
932 static int bus_get_owner_creds_kdbus(sd_bus
*bus
, uint64_t mask
, sd_bus_creds
**ret
) {
933 _cleanup_bus_creds_unref_ sd_bus_creds
*c
= NULL
;
934 struct kdbus_cmd_info cmd
= {
935 .size
= sizeof(struct kdbus_cmd_info
),
937 struct kdbus_info
*creator_info
;
945 /* If augmentation is on, and the bus doesn't didn't allow us
946 * to get the bits we want, then ask for the PID/TID so that we
947 * can read the rest from /proc. */
948 if ((mask
& SD_BUS_CREDS_AUGMENT
) &&
949 (mask
& (SD_BUS_CREDS_PPID
|
950 SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
|
951 SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
|
952 SD_BUS_CREDS_COMM
|SD_BUS_CREDS_TID_COMM
|SD_BUS_CREDS_EXE
|SD_BUS_CREDS_CMDLINE
|
953 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
|
954 SD_BUS_CREDS_EFFECTIVE_CAPS
|SD_BUS_CREDS_PERMITTED_CAPS
|SD_BUS_CREDS_INHERITABLE_CAPS
|SD_BUS_CREDS_BOUNDING_CAPS
|
955 SD_BUS_CREDS_SELINUX_CONTEXT
|
956 SD_BUS_CREDS_AUDIT_SESSION_ID
|SD_BUS_CREDS_AUDIT_LOGIN_UID
)))
957 mask
|= SD_BUS_CREDS_PID
;
959 cmd
.attach_flags
= attach_flags_to_kdbus(mask
);
961 r
= ioctl(bus
->input_fd
, KDBUS_CMD_BUS_CREATOR_INFO
, &cmd
);
965 creator_info
= (struct kdbus_info
*) ((uint8_t *) bus
->kdbus_buffer
+ cmd
.offset
);
967 r
= bus_populate_creds_from_items(bus
, creator_info
, mask
, c
);
968 bus_kernel_cmd_free(bus
, cmd
.offset
);
972 r
= bus_creds_add_more(c
, mask
, pid
, 0);
981 static int bus_get_owner_creds_dbus1(sd_bus
*bus
, uint64_t mask
, sd_bus_creds
**ret
) {
982 _cleanup_bus_creds_unref_ sd_bus_creds
*c
= NULL
;
989 do_label
= bus
->label
&& (mask
& SD_BUS_CREDS_SELINUX_CONTEXT
);
991 /* Avoid allocating anything if we have no chance of returning useful data */
992 if (!bus
->ucred_valid
&& !do_label
)
999 if (bus
->ucred_valid
) {
1000 if (bus
->ucred
.pid
> 0) {
1001 pid
= c
->pid
= bus
->ucred
.pid
;
1002 c
->mask
|= SD_BUS_CREDS_PID
& mask
;
1005 if (bus
->ucred
.uid
!= UID_INVALID
) {
1006 c
->euid
= bus
->ucred
.uid
;
1007 c
->mask
|= SD_BUS_CREDS_EUID
& mask
;
1010 if (bus
->ucred
.gid
!= GID_INVALID
) {
1011 c
->egid
= bus
->ucred
.gid
;
1012 c
->mask
|= SD_BUS_CREDS_EGID
& mask
;
1017 c
->label
= strdup(bus
->label
);
1021 c
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
1024 r
= bus_creds_add_more(c
, mask
, pid
, 0);
1033 _public_
int sd_bus_get_owner_creds(sd_bus
*bus
, uint64_t mask
, sd_bus_creds
**ret
) {
1034 assert_return(bus
, -EINVAL
);
1035 assert_return((mask
& ~SD_BUS_CREDS_AUGMENT
) <= _SD_BUS_CREDS_ALL
, -EOPNOTSUPP
);
1036 assert_return(ret
, -EINVAL
);
1037 assert_return(!bus_pid_changed(bus
), -ECHILD
);
1039 if (!BUS_IS_OPEN(bus
->state
))
1043 return bus_get_owner_creds_kdbus(bus
, mask
, ret
);
1045 return bus_get_owner_creds_dbus1(bus
, mask
, ret
);
1048 static int add_name_change_match(sd_bus
*bus
,
1051 const char *old_owner
,
1052 const char *new_owner
) {
1054 uint64_t name_id
= KDBUS_MATCH_ID_ANY
, old_owner_id
= 0, new_owner_id
= 0;
1055 int is_name_id
= -1, r
;
1056 struct kdbus_item
*item
;
1060 /* If we encounter a match that could match against
1061 * NameOwnerChanged messages, then we need to create
1062 * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
1063 * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
1064 * multiple if the match is underspecified.
1066 * The NameOwnerChanged signals take three parameters with
1067 * unique or well-known names, but only some forms actually
1070 * WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD
1071 * WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE
1072 * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE
1073 * UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD
1074 * UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE
1076 * For the latter two the two unique names must be identical.
1081 is_name_id
= bus_kernel_parse_unique_name(name
, &name_id
);
1086 if (!isempty(old_owner
)) {
1087 r
= bus_kernel_parse_unique_name(old_owner
, &old_owner_id
);
1092 if (is_name_id
> 0 && old_owner_id
!= name_id
)
1095 old_owner_id
= KDBUS_MATCH_ID_ANY
;
1097 if (!isempty(new_owner
)) {
1098 r
= bus_kernel_parse_unique_name(new_owner
, &new_owner_id
);
1103 if (is_name_id
> 0 && new_owner_id
!= name_id
)
1106 new_owner_id
= KDBUS_MATCH_ID_ANY
;
1108 if (is_name_id
<= 0) {
1109 struct kdbus_cmd_match
*m
;
1112 /* If the name argument is missing or is a well-known
1113 * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
1116 l
= name
? strlen(name
) + 1 : 0;
1118 sz
= ALIGN8(offsetof(struct kdbus_cmd_match
, items
) +
1119 offsetof(struct kdbus_item
, name_change
) +
1120 offsetof(struct kdbus_notify_name_change
, name
) +
1123 m
= alloca0_align(sz
, 8);
1129 offsetof(struct kdbus_item
, name_change
) +
1130 offsetof(struct kdbus_notify_name_change
, name
) +
1133 item
->name_change
.old_id
.id
= old_owner_id
;
1134 item
->name_change
.new_id
.id
= new_owner_id
;
1137 memcpy(item
->name_change
.name
, name
, l
);
1139 /* If the old name is unset or empty, then
1140 * this can match against added names */
1141 if (isempty(old_owner
)) {
1142 item
->type
= KDBUS_ITEM_NAME_ADD
;
1144 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1149 /* If the new name is unset or empty, then
1150 * this can match against removed names */
1151 if (isempty(new_owner
)) {
1152 item
->type
= KDBUS_ITEM_NAME_REMOVE
;
1154 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1159 /* The CHANGE match we need in either case, because
1160 * what is reported as a name change by the kernel
1161 * might just be an owner change between starter and
1162 * normal clients. For userspace such a change should
1163 * be considered a removal/addition, hence let's
1164 * subscribe to this unconditionally. */
1165 item
->type
= KDBUS_ITEM_NAME_CHANGE
;
1166 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1171 if (is_name_id
!= 0) {
1172 struct kdbus_cmd_match
*m
;
1175 /* If the name argument is missing or is a unique
1176 * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
1179 sz
= ALIGN8(offsetof(struct kdbus_cmd_match
, items
) +
1180 offsetof(struct kdbus_item
, id_change
) +
1181 sizeof(struct kdbus_notify_id_change
));
1183 m
= alloca0_align(sz
, 8);
1189 offsetof(struct kdbus_item
, id_change
) +
1190 sizeof(struct kdbus_notify_id_change
);
1191 item
->id_change
.id
= name_id
;
1193 /* If the old name is unset or empty, then this can
1194 * match against added ids */
1195 if (isempty(old_owner
)) {
1196 item
->type
= KDBUS_ITEM_ID_ADD
;
1197 if (!isempty(new_owner
))
1198 item
->id_change
.id
= new_owner_id
;
1200 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1205 /* If thew new name is unset or empty, then this can
1206 * match against removed ids */
1207 if (isempty(new_owner
)) {
1208 item
->type
= KDBUS_ITEM_ID_REMOVE
;
1209 if (!isempty(old_owner
))
1210 item
->id_change
.id
= old_owner_id
;
1212 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1221 int bus_add_match_internal_kernel(
1223 struct bus_match_component
*components
,
1224 unsigned n_components
,
1227 struct kdbus_cmd_match
*m
;
1228 struct kdbus_item
*item
;
1231 const char *sender
= NULL
;
1232 size_t sender_length
= 0;
1233 uint64_t src_id
= KDBUS_MATCH_ID_ANY
, dst_id
= KDBUS_MATCH_ID_ANY
;
1234 bool using_bloom
= false;
1236 bool matches_name_change
= true;
1237 const char *name_change_arg
[3] = {};
1242 /* Monitor streams don't support matches, make this a NOP */
1243 if (bus
->hello_flags
& KDBUS_HELLO_MONITOR
)
1246 bloom
= alloca0(bus
->bloom_size
);
1248 sz
= ALIGN8(offsetof(struct kdbus_cmd_match
, items
));
1250 for (i
= 0; i
< n_components
; i
++) {
1251 struct bus_match_component
*c
= &components
[i
];
1255 case BUS_MATCH_SENDER
:
1256 if (!streq(c
->value_str
, "org.freedesktop.DBus"))
1257 matches_name_change
= false;
1259 r
= bus_kernel_parse_unique_name(c
->value_str
, &src_id
);
1263 sz
+= ALIGN8(offsetof(struct kdbus_item
, id
) + sizeof(uint64_t));
1265 sender
= c
->value_str
;
1266 sender_length
= strlen(sender
);
1267 sz
+= ALIGN8(offsetof(struct kdbus_item
, str
) + sender_length
+ 1);
1272 case BUS_MATCH_MESSAGE_TYPE
:
1273 if (c
->value_u8
!= SD_BUS_MESSAGE_SIGNAL
)
1274 matches_name_change
= false;
1276 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, "message-type", bus_message_type_to_string(c
->value_u8
));
1280 case BUS_MATCH_INTERFACE
:
1281 if (!streq(c
->value_str
, "org.freedesktop.DBus"))
1282 matches_name_change
= false;
1284 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, "interface", c
->value_str
);
1288 case BUS_MATCH_MEMBER
:
1289 if (!streq(c
->value_str
, "NameOwnerChanged"))
1290 matches_name_change
= false;
1292 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, "member", c
->value_str
);
1296 case BUS_MATCH_PATH
:
1297 if (!streq(c
->value_str
, "/org/freedesktop/DBus"))
1298 matches_name_change
= false;
1300 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, "path", c
->value_str
);
1304 case BUS_MATCH_PATH_NAMESPACE
:
1305 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, "path-slash-prefix", c
->value_str
);
1309 case BUS_MATCH_ARG
...BUS_MATCH_ARG_LAST
: {
1310 char buf
[sizeof("arg")-1 + 2 + 1];
1312 if (c
->type
- BUS_MATCH_ARG
< 3)
1313 name_change_arg
[c
->type
- BUS_MATCH_ARG
] = c
->value_str
;
1315 xsprintf(buf
, "arg%i", c
->type
- BUS_MATCH_ARG
);
1316 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, buf
, c
->value_str
);
1321 case BUS_MATCH_ARG_HAS
...BUS_MATCH_ARG_HAS_LAST
: {
1322 char buf
[sizeof("arg")-1 + 2 + sizeof("-has")];
1324 xsprintf(buf
, "arg%i-has", c
->type
- BUS_MATCH_ARG_HAS
);
1325 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, buf
, c
->value_str
);
1330 case BUS_MATCH_ARG_PATH
...BUS_MATCH_ARG_PATH_LAST
:
1332 * XXX: DBus spec defines arg[0..63]path= matching to be
1333 * a two-way glob. That is, if either string is a prefix
1334 * of the other, it matches.
1335 * This is really hard to realize in bloom-filters, as
1336 * we would have to create a bloom-match for each prefix
1337 * of @c->value_str. This is excessive, hence we just
1338 * ignore all those matches and accept everything from
1339 * the kernel. People should really avoid those matches.
1340 * If they're used in real-life some day, we will have
1341 * to properly support multiple-matches here.
1345 case BUS_MATCH_ARG_NAMESPACE
...BUS_MATCH_ARG_NAMESPACE_LAST
: {
1346 char buf
[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1348 xsprintf(buf
, "arg%i-dot-prefix", c
->type
- BUS_MATCH_ARG_NAMESPACE
);
1349 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, buf
, c
->value_str
);
1354 case BUS_MATCH_DESTINATION
:
1356 * Kernel only supports matching on destination IDs, but
1357 * not on destination names. So just skip the
1358 * destination name restriction and verify it in
1359 * user-space on retrieval.
1361 r
= bus_kernel_parse_unique_name(c
->value_str
, &dst_id
);
1365 sz
+= ALIGN8(offsetof(struct kdbus_item
, id
) + sizeof(uint64_t));
1367 /* if not a broadcast, it cannot be a name-change */
1368 if (r
<= 0 || dst_id
!= KDBUS_DST_ID_BROADCAST
)
1369 matches_name_change
= false;
1373 case BUS_MATCH_ROOT
:
1374 case BUS_MATCH_VALUE
:
1375 case BUS_MATCH_LEAF
:
1376 case _BUS_MATCH_NODE_TYPE_MAX
:
1377 case _BUS_MATCH_NODE_TYPE_INVALID
:
1378 assert_not_reached("Invalid match type?");
1383 sz
+= ALIGN8(offsetof(struct kdbus_item
, data64
) + bus
->bloom_size
);
1385 m
= alloca0_align(sz
, 8);
1391 if (src_id
!= KDBUS_MATCH_ID_ANY
) {
1392 item
->size
= offsetof(struct kdbus_item
, id
) + sizeof(uint64_t);
1393 item
->type
= KDBUS_ITEM_ID
;
1395 item
= KDBUS_ITEM_NEXT(item
);
1398 if (dst_id
!= KDBUS_MATCH_ID_ANY
) {
1399 item
->size
= offsetof(struct kdbus_item
, id
) + sizeof(uint64_t);
1400 item
->type
= KDBUS_ITEM_DST_ID
;
1402 item
= KDBUS_ITEM_NEXT(item
);
1406 item
->size
= offsetof(struct kdbus_item
, data64
) + bus
->bloom_size
;
1407 item
->type
= KDBUS_ITEM_BLOOM_MASK
;
1408 memcpy(item
->data64
, bloom
, bus
->bloom_size
);
1409 item
= KDBUS_ITEM_NEXT(item
);
1413 item
->size
= offsetof(struct kdbus_item
, str
) + sender_length
+ 1;
1414 item
->type
= KDBUS_ITEM_NAME
;
1415 memcpy(item
->str
, sender
, sender_length
+ 1);
1418 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1422 if (matches_name_change
) {
1424 /* If this match could theoretically match
1425 * NameOwnerChanged messages, we need to
1426 * install a second non-bloom filter explitly
1429 r
= add_name_change_match(bus
, cookie
, name_change_arg
[0], name_change_arg
[1], name_change_arg
[2]);
1437 #define internal_match(bus, m) \
1438 ((bus)->hello_flags & KDBUS_HELLO_MONITOR \
1439 ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
1442 static int bus_add_match_internal_dbus1(
1444 const char *match
) {
1451 e
= internal_match(bus
, match
);
1453 return sd_bus_call_method(
1455 "org.freedesktop.DBus",
1456 "/org/freedesktop/DBus",
1457 "org.freedesktop.DBus",
1465 int bus_add_match_internal(
1468 struct bus_match_component
*components
,
1469 unsigned n_components
,
1474 if (!bus
->bus_client
)
1478 return bus_add_match_internal_kernel(bus
, components
, n_components
, cookie
);
1480 return bus_add_match_internal_dbus1(bus
, match
);
1483 int bus_remove_match_internal_kernel(
1487 struct kdbus_cmd_match m
= {
1488 .size
= offsetof(struct kdbus_cmd_match
, items
),
1495 /* Monitor streams don't support matches, make this a NOP */
1496 if (bus
->hello_flags
& KDBUS_HELLO_MONITOR
)
1499 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_REMOVE
, &m
);
1506 static int bus_remove_match_internal_dbus1(
1508 const char *match
) {
1515 e
= internal_match(bus
, match
);
1517 return sd_bus_call_method(
1519 "org.freedesktop.DBus",
1520 "/org/freedesktop/DBus",
1521 "org.freedesktop.DBus",
1529 int bus_remove_match_internal(
1536 if (!bus
->bus_client
)
1540 return bus_remove_match_internal_kernel(bus
, cookie
);
1542 return bus_remove_match_internal_dbus1(bus
, match
);
1545 _public_
int sd_bus_get_name_machine_id(sd_bus
*bus
, const char *name
, sd_id128_t
*machine
) {
1546 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
, *m
= NULL
;
1550 assert_return(bus
, -EINVAL
);
1551 assert_return(name
, -EINVAL
);
1552 assert_return(machine
, -EINVAL
);
1553 assert_return(!bus_pid_changed(bus
), -ECHILD
);
1554 assert_return(service_name_is_valid(name
), -EINVAL
);
1556 if (!bus
->bus_client
)
1559 if (!BUS_IS_OPEN(bus
->state
))
1562 if (streq_ptr(name
, bus
->unique_name
))
1563 return sd_id128_get_machine(machine
);
1565 r
= sd_bus_message_new_method_call(
1570 "org.freedesktop.DBus.Peer",
1575 r
= sd_bus_message_set_auto_start(m
, false);
1579 r
= sd_bus_call(bus
, m
, 0, NULL
, &reply
);
1583 r
= sd_bus_message_read(reply
, "s", &mid
);
1587 return sd_id128_from_string(mid
, machine
);