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
;
985 bool do_label
= bus
->label
&& (mask
& SD_BUS_CREDS_SELINUX_CONTEXT
);
987 /* Avoid allocating anything if we have no chance of returning useful data */
988 if (!bus
->ucred_valid
&& !do_label
)
995 if (bus
->ucred_valid
) {
996 if (bus
->ucred
.pid
> 0) {
997 pid
= c
->pid
= bus
->ucred
.pid
;
998 c
->mask
|= SD_BUS_CREDS_PID
& mask
;
1001 if (bus
->ucred
.uid
!= UID_INVALID
) {
1002 c
->euid
= bus
->ucred
.uid
;
1003 c
->mask
|= SD_BUS_CREDS_EUID
& mask
;
1006 if (bus
->ucred
.gid
!= GID_INVALID
) {
1007 c
->egid
= bus
->ucred
.gid
;
1008 c
->mask
|= SD_BUS_CREDS_EGID
& mask
;
1013 c
->label
= strdup(bus
->label
);
1017 c
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
1020 r
= bus_creds_add_more(c
, mask
, pid
, 0);
1029 _public_
int sd_bus_get_owner_creds(sd_bus
*bus
, uint64_t mask
, sd_bus_creds
**ret
) {
1030 assert_return(bus
, -EINVAL
);
1031 assert_return((mask
& ~SD_BUS_CREDS_AUGMENT
) <= _SD_BUS_CREDS_ALL
, -EOPNOTSUPP
);
1032 assert_return(ret
, -EINVAL
);
1033 assert_return(!bus_pid_changed(bus
), -ECHILD
);
1035 if (!BUS_IS_OPEN(bus
->state
))
1039 return bus_get_owner_creds_kdbus(bus
, mask
, ret
);
1041 return bus_get_owner_creds_dbus1(bus
, mask
, ret
);
1044 static int add_name_change_match(sd_bus
*bus
,
1047 const char *old_owner
,
1048 const char *new_owner
) {
1050 uint64_t name_id
= KDBUS_MATCH_ID_ANY
, old_owner_id
= 0, new_owner_id
= 0;
1051 int is_name_id
= -1, r
;
1052 struct kdbus_item
*item
;
1056 /* If we encounter a match that could match against
1057 * NameOwnerChanged messages, then we need to create
1058 * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
1059 * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
1060 * multiple if the match is underspecified.
1062 * The NameOwnerChanged signals take three parameters with
1063 * unique or well-known names, but only some forms actually
1066 * WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD
1067 * WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE
1068 * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE
1069 * UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD
1070 * UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE
1072 * For the latter two the two unique names must be identical.
1077 is_name_id
= bus_kernel_parse_unique_name(name
, &name_id
);
1082 if (!isempty(old_owner
)) {
1083 r
= bus_kernel_parse_unique_name(old_owner
, &old_owner_id
);
1088 if (is_name_id
> 0 && old_owner_id
!= name_id
)
1091 old_owner_id
= KDBUS_MATCH_ID_ANY
;
1093 if (!isempty(new_owner
)) {
1094 r
= bus_kernel_parse_unique_name(new_owner
, &new_owner_id
);
1099 if (is_name_id
> 0 && new_owner_id
!= name_id
)
1102 new_owner_id
= KDBUS_MATCH_ID_ANY
;
1104 if (is_name_id
<= 0) {
1105 struct kdbus_cmd_match
*m
;
1108 /* If the name argument is missing or is a well-known
1109 * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
1112 l
= name
? strlen(name
) + 1 : 0;
1114 sz
= ALIGN8(offsetof(struct kdbus_cmd_match
, items
) +
1115 offsetof(struct kdbus_item
, name_change
) +
1116 offsetof(struct kdbus_notify_name_change
, name
) +
1119 m
= alloca0_align(sz
, 8);
1125 offsetof(struct kdbus_item
, name_change
) +
1126 offsetof(struct kdbus_notify_name_change
, name
) +
1129 item
->name_change
.old_id
.id
= old_owner_id
;
1130 item
->name_change
.new_id
.id
= new_owner_id
;
1133 memcpy(item
->name_change
.name
, name
, l
);
1135 /* If the old name is unset or empty, then
1136 * this can match against added names */
1137 if (isempty(old_owner
)) {
1138 item
->type
= KDBUS_ITEM_NAME_ADD
;
1140 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1145 /* If the new name is unset or empty, then
1146 * this can match against removed names */
1147 if (isempty(new_owner
)) {
1148 item
->type
= KDBUS_ITEM_NAME_REMOVE
;
1150 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1155 /* The CHANGE match we need in either case, because
1156 * what is reported as a name change by the kernel
1157 * might just be an owner change between starter and
1158 * normal clients. For userspace such a change should
1159 * be considered a removal/addition, hence let's
1160 * subscribe to this unconditionally. */
1161 item
->type
= KDBUS_ITEM_NAME_CHANGE
;
1162 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1167 if (is_name_id
!= 0) {
1168 struct kdbus_cmd_match
*m
;
1171 /* If the name argument is missing or is a unique
1172 * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
1175 sz
= ALIGN8(offsetof(struct kdbus_cmd_match
, items
) +
1176 offsetof(struct kdbus_item
, id_change
) +
1177 sizeof(struct kdbus_notify_id_change
));
1179 m
= alloca0_align(sz
, 8);
1185 offsetof(struct kdbus_item
, id_change
) +
1186 sizeof(struct kdbus_notify_id_change
);
1187 item
->id_change
.id
= name_id
;
1189 /* If the old name is unset or empty, then this can
1190 * match against added ids */
1191 if (isempty(old_owner
)) {
1192 item
->type
= KDBUS_ITEM_ID_ADD
;
1193 if (!isempty(new_owner
))
1194 item
->id_change
.id
= new_owner_id
;
1196 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1201 /* If thew new name is unset or empty, then this can
1202 * match against removed ids */
1203 if (isempty(new_owner
)) {
1204 item
->type
= KDBUS_ITEM_ID_REMOVE
;
1205 if (!isempty(old_owner
))
1206 item
->id_change
.id
= old_owner_id
;
1208 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1217 int bus_add_match_internal_kernel(
1219 struct bus_match_component
*components
,
1220 unsigned n_components
,
1223 struct kdbus_cmd_match
*m
;
1224 struct kdbus_item
*item
;
1227 const char *sender
= NULL
;
1228 size_t sender_length
= 0;
1229 uint64_t src_id
= KDBUS_MATCH_ID_ANY
, dst_id
= KDBUS_MATCH_ID_ANY
;
1230 bool using_bloom
= false;
1232 bool matches_name_change
= true;
1233 const char *name_change_arg
[3] = {};
1238 /* Monitor streams don't support matches, make this a NOP */
1239 if (bus
->hello_flags
& KDBUS_HELLO_MONITOR
)
1242 bloom
= alloca0(bus
->bloom_size
);
1244 sz
= ALIGN8(offsetof(struct kdbus_cmd_match
, items
));
1246 for (i
= 0; i
< n_components
; i
++) {
1247 struct bus_match_component
*c
= &components
[i
];
1251 case BUS_MATCH_SENDER
:
1252 if (!streq(c
->value_str
, "org.freedesktop.DBus"))
1253 matches_name_change
= false;
1255 r
= bus_kernel_parse_unique_name(c
->value_str
, &src_id
);
1259 sz
+= ALIGN8(offsetof(struct kdbus_item
, id
) + sizeof(uint64_t));
1261 sender
= c
->value_str
;
1262 sender_length
= strlen(sender
);
1263 sz
+= ALIGN8(offsetof(struct kdbus_item
, str
) + sender_length
+ 1);
1268 case BUS_MATCH_MESSAGE_TYPE
:
1269 if (c
->value_u8
!= SD_BUS_MESSAGE_SIGNAL
)
1270 matches_name_change
= false;
1272 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, "message-type", bus_message_type_to_string(c
->value_u8
));
1276 case BUS_MATCH_INTERFACE
:
1277 if (!streq(c
->value_str
, "org.freedesktop.DBus"))
1278 matches_name_change
= false;
1280 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, "interface", c
->value_str
);
1284 case BUS_MATCH_MEMBER
:
1285 if (!streq(c
->value_str
, "NameOwnerChanged"))
1286 matches_name_change
= false;
1288 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, "member", c
->value_str
);
1292 case BUS_MATCH_PATH
:
1293 if (!streq(c
->value_str
, "/org/freedesktop/DBus"))
1294 matches_name_change
= false;
1296 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, "path", c
->value_str
);
1300 case BUS_MATCH_PATH_NAMESPACE
:
1301 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, "path-slash-prefix", c
->value_str
);
1305 case BUS_MATCH_ARG
...BUS_MATCH_ARG_LAST
: {
1306 char buf
[sizeof("arg")-1 + 2 + 1];
1308 if (c
->type
- BUS_MATCH_ARG
< 3)
1309 name_change_arg
[c
->type
- BUS_MATCH_ARG
] = c
->value_str
;
1311 xsprintf(buf
, "arg%i", c
->type
- BUS_MATCH_ARG
);
1312 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, buf
, c
->value_str
);
1317 case BUS_MATCH_ARG_HAS
...BUS_MATCH_ARG_HAS_LAST
: {
1318 char buf
[sizeof("arg")-1 + 2 + sizeof("-has")];
1320 xsprintf(buf
, "arg%i-has", c
->type
- BUS_MATCH_ARG_HAS
);
1321 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, buf
, c
->value_str
);
1326 case BUS_MATCH_ARG_PATH
...BUS_MATCH_ARG_PATH_LAST
:
1328 * XXX: DBus spec defines arg[0..63]path= matching to be
1329 * a two-way glob. That is, if either string is a prefix
1330 * of the other, it matches.
1331 * This is really hard to realize in bloom-filters, as
1332 * we would have to create a bloom-match for each prefix
1333 * of @c->value_str. This is excessive, hence we just
1334 * ignore all those matches and accept everything from
1335 * the kernel. People should really avoid those matches.
1336 * If they're used in real-life some day, we will have
1337 * to properly support multiple-matches here.
1341 case BUS_MATCH_ARG_NAMESPACE
...BUS_MATCH_ARG_NAMESPACE_LAST
: {
1342 char buf
[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1344 xsprintf(buf
, "arg%i-dot-prefix", c
->type
- BUS_MATCH_ARG_NAMESPACE
);
1345 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, buf
, c
->value_str
);
1350 case BUS_MATCH_DESTINATION
:
1352 * Kernel only supports matching on destination IDs, but
1353 * not on destination names. So just skip the
1354 * destination name restriction and verify it in
1355 * user-space on retrieval.
1357 r
= bus_kernel_parse_unique_name(c
->value_str
, &dst_id
);
1361 sz
+= ALIGN8(offsetof(struct kdbus_item
, id
) + sizeof(uint64_t));
1363 /* if not a broadcast, it cannot be a name-change */
1364 if (r
<= 0 || dst_id
!= KDBUS_DST_ID_BROADCAST
)
1365 matches_name_change
= false;
1369 case BUS_MATCH_ROOT
:
1370 case BUS_MATCH_VALUE
:
1371 case BUS_MATCH_LEAF
:
1372 case _BUS_MATCH_NODE_TYPE_MAX
:
1373 case _BUS_MATCH_NODE_TYPE_INVALID
:
1374 assert_not_reached("Invalid match type?");
1379 sz
+= ALIGN8(offsetof(struct kdbus_item
, data64
) + bus
->bloom_size
);
1381 m
= alloca0_align(sz
, 8);
1387 if (src_id
!= KDBUS_MATCH_ID_ANY
) {
1388 item
->size
= offsetof(struct kdbus_item
, id
) + sizeof(uint64_t);
1389 item
->type
= KDBUS_ITEM_ID
;
1391 item
= KDBUS_ITEM_NEXT(item
);
1394 if (dst_id
!= KDBUS_MATCH_ID_ANY
) {
1395 item
->size
= offsetof(struct kdbus_item
, id
) + sizeof(uint64_t);
1396 item
->type
= KDBUS_ITEM_DST_ID
;
1398 item
= KDBUS_ITEM_NEXT(item
);
1402 item
->size
= offsetof(struct kdbus_item
, data64
) + bus
->bloom_size
;
1403 item
->type
= KDBUS_ITEM_BLOOM_MASK
;
1404 memcpy(item
->data64
, bloom
, bus
->bloom_size
);
1405 item
= KDBUS_ITEM_NEXT(item
);
1409 item
->size
= offsetof(struct kdbus_item
, str
) + sender_length
+ 1;
1410 item
->type
= KDBUS_ITEM_NAME
;
1411 memcpy(item
->str
, sender
, sender_length
+ 1);
1414 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1418 if (matches_name_change
) {
1420 /* If this match could theoretically match
1421 * NameOwnerChanged messages, we need to
1422 * install a second non-bloom filter explitly
1425 r
= add_name_change_match(bus
, cookie
, name_change_arg
[0], name_change_arg
[1], name_change_arg
[2]);
1433 #define internal_match(bus, m) \
1434 ((bus)->hello_flags & KDBUS_HELLO_MONITOR \
1435 ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
1438 static int bus_add_match_internal_dbus1(
1440 const char *match
) {
1447 e
= internal_match(bus
, match
);
1449 return sd_bus_call_method(
1451 "org.freedesktop.DBus",
1452 "/org/freedesktop/DBus",
1453 "org.freedesktop.DBus",
1461 int bus_add_match_internal(
1464 struct bus_match_component
*components
,
1465 unsigned n_components
,
1470 if (!bus
->bus_client
)
1474 return bus_add_match_internal_kernel(bus
, components
, n_components
, cookie
);
1476 return bus_add_match_internal_dbus1(bus
, match
);
1479 int bus_remove_match_internal_kernel(
1483 struct kdbus_cmd_match m
= {
1484 .size
= offsetof(struct kdbus_cmd_match
, items
),
1491 /* Monitor streams don't support matches, make this a NOP */
1492 if (bus
->hello_flags
& KDBUS_HELLO_MONITOR
)
1495 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_REMOVE
, &m
);
1502 static int bus_remove_match_internal_dbus1(
1504 const char *match
) {
1511 e
= internal_match(bus
, match
);
1513 return sd_bus_call_method(
1515 "org.freedesktop.DBus",
1516 "/org/freedesktop/DBus",
1517 "org.freedesktop.DBus",
1525 int bus_remove_match_internal(
1532 if (!bus
->bus_client
)
1536 return bus_remove_match_internal_kernel(bus
, cookie
);
1538 return bus_remove_match_internal_dbus1(bus
, match
);
1541 _public_
int sd_bus_get_name_machine_id(sd_bus
*bus
, const char *name
, sd_id128_t
*machine
) {
1542 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
, *m
= NULL
;
1546 assert_return(bus
, -EINVAL
);
1547 assert_return(name
, -EINVAL
);
1548 assert_return(machine
, -EINVAL
);
1549 assert_return(!bus_pid_changed(bus
), -ECHILD
);
1550 assert_return(service_name_is_valid(name
), -EINVAL
);
1552 if (!bus
->bus_client
)
1555 if (!BUS_IS_OPEN(bus
->state
))
1558 if (streq_ptr(name
, bus
->unique_name
))
1559 return sd_id128_get_machine(machine
);
1561 r
= sd_bus_message_new_method_call(
1566 "org.freedesktop.DBus.Peer",
1571 r
= sd_bus_message_set_auto_start(m
, false);
1575 r
= sd_bus_call(bus
, m
, 0, NULL
, &reply
);
1579 r
= sd_bus_message_read(reply
, "s", &mid
);
1583 return sd_id128_from_string(mid
, machine
);