1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #ifdef HAVE_VALGRIND_MEMCHECK_H
23 #include <valgrind/memcheck.h>
31 #include "bus-internal.h"
32 #include "bus-message.h"
33 #include "bus-control.h"
34 #include "bus-bloom.h"
35 #include "capability.h"
37 _public_
int sd_bus_get_unique_name(sd_bus
*bus
, const char **unique
) {
40 assert_return(bus
, -EINVAL
);
41 assert_return(unique
, -EINVAL
);
42 assert_return(!bus_pid_changed(bus
), -ECHILD
);
47 r
= bus_ensure_running(bus
);
51 *unique
= bus
->unique_name
;
55 static int bus_request_name_kernel(sd_bus
*bus
, const char *name
, uint64_t flags
) {
64 size
= offsetof(struct kdbus_cmd
, items
) + KDBUS_ITEM_SIZE(l
);
65 n
= alloca0_align(size
, 8);
67 n
->flags
= request_name_flags_to_kdbus(flags
);
69 n
->items
[0].size
= KDBUS_ITEM_HEADER_SIZE
+ l
;
70 n
->items
[0].type
= KDBUS_ITEM_NAME
;
71 memcpy(n
->items
[0].str
, name
, l
);
73 #ifdef HAVE_VALGRIND_MEMCHECK_H
74 VALGRIND_MAKE_MEM_DEFINED(n
, n
->size
);
77 r
= ioctl(bus
->input_fd
, KDBUS_CMD_NAME_ACQUIRE
, n
);
81 if (n
->return_flags
& KDBUS_NAME_IN_QUEUE
)
87 static int bus_request_name_dbus1(sd_bus
*bus
, const char *name
, uint64_t flags
) {
88 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
89 uint32_t ret
, param
= 0;
95 if (flags
& SD_BUS_NAME_ALLOW_REPLACEMENT
)
96 param
|= BUS_NAME_ALLOW_REPLACEMENT
;
97 if (flags
& SD_BUS_NAME_REPLACE_EXISTING
)
98 param
|= BUS_NAME_REPLACE_EXISTING
;
99 if (!(flags
& SD_BUS_NAME_QUEUE
))
100 param
|= BUS_NAME_DO_NOT_QUEUE
;
102 r
= sd_bus_call_method(
104 "org.freedesktop.DBus",
105 "/org/freedesktop/DBus",
106 "org.freedesktop.DBus",
116 r
= sd_bus_message_read(reply
, "u", &ret
);
120 if (ret
== BUS_NAME_ALREADY_OWNER
)
122 else if (ret
== BUS_NAME_EXISTS
)
124 else if (ret
== BUS_NAME_IN_QUEUE
)
126 else if (ret
== BUS_NAME_PRIMARY_OWNER
)
132 _public_
int sd_bus_request_name(sd_bus
*bus
, const char *name
, uint64_t flags
) {
133 assert_return(bus
, -EINVAL
);
134 assert_return(name
, -EINVAL
);
135 assert_return(!bus_pid_changed(bus
), -ECHILD
);
136 assert_return(!(flags
& ~(SD_BUS_NAME_ALLOW_REPLACEMENT
|SD_BUS_NAME_REPLACE_EXISTING
|SD_BUS_NAME_QUEUE
)), -EINVAL
);
137 assert_return(service_name_is_valid(name
), -EINVAL
);
138 assert_return(name
[0] != ':', -EINVAL
);
140 if (!bus
->bus_client
)
143 /* Don't allow requesting the special driver and local names */
144 if (STR_IN_SET(name
, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
147 if (!BUS_IS_OPEN(bus
->state
))
151 return bus_request_name_kernel(bus
, name
, flags
);
153 return bus_request_name_dbus1(bus
, name
, flags
);
156 static int bus_release_name_kernel(sd_bus
*bus
, const char *name
) {
164 l
= strlen(name
) + 1;
165 size
= offsetof(struct kdbus_cmd
, items
) + KDBUS_ITEM_SIZE(l
);
166 n
= alloca0_align(size
, 8);
169 n
->items
[0].size
= KDBUS_ITEM_HEADER_SIZE
+ l
;
170 n
->items
[0].type
= KDBUS_ITEM_NAME
;
171 memcpy(n
->items
[0].str
, name
, l
);
173 #ifdef HAVE_VALGRIND_MEMCHECK_H
174 VALGRIND_MAKE_MEM_DEFINED(n
, n
->size
);
176 r
= ioctl(bus
->input_fd
, KDBUS_CMD_NAME_RELEASE
, n
);
183 static int bus_release_name_dbus1(sd_bus
*bus
, const char *name
) {
184 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
191 r
= sd_bus_call_method(
193 "org.freedesktop.DBus",
194 "/org/freedesktop/DBus",
195 "org.freedesktop.DBus",
204 r
= sd_bus_message_read(reply
, "u", &ret
);
207 if (ret
== BUS_NAME_NON_EXISTENT
)
209 if (ret
== BUS_NAME_NOT_OWNER
)
211 if (ret
== BUS_NAME_RELEASED
)
217 _public_
int sd_bus_release_name(sd_bus
*bus
, const char *name
) {
218 assert_return(bus
, -EINVAL
);
219 assert_return(name
, -EINVAL
);
220 assert_return(!bus_pid_changed(bus
), -ECHILD
);
221 assert_return(service_name_is_valid(name
), -EINVAL
);
222 assert_return(name
[0] != ':', -EINVAL
);
224 if (!bus
->bus_client
)
227 /* Don't allow releasing the special driver and local names */
228 if (STR_IN_SET(name
, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
231 if (!BUS_IS_OPEN(bus
->state
))
235 return bus_release_name_kernel(bus
, name
);
237 return bus_release_name_dbus1(bus
, name
);
240 static int kernel_get_list(sd_bus
*bus
, uint64_t flags
, char ***x
) {
241 struct kdbus_cmd_list cmd
= {
245 struct kdbus_info
*name_list
, *name
;
246 uint64_t previous_id
= 0;
249 /* Caller will free half-constructed list on failure... */
251 r
= ioctl(bus
->input_fd
, KDBUS_CMD_LIST
, &cmd
);
255 name_list
= (struct kdbus_info
*) ((uint8_t *) bus
->kdbus_buffer
+ cmd
.offset
);
257 KDBUS_FOREACH(name
, name_list
, cmd
.list_size
) {
258 struct kdbus_item
*item
;
260 if ((flags
& KDBUS_LIST_UNIQUE
) && name
->id
!= previous_id
) {
263 if (asprintf(&n
, ":1.%llu", (unsigned long long) name
->id
) < 0) {
268 r
= strv_consume(x
, n
);
272 previous_id
= name
->id
;
275 KDBUS_ITEM_FOREACH(item
, name
, items
) {
276 if (item
->type
== KDBUS_ITEM_OWNED_NAME
) {
277 if (service_name_is_valid(item
->name
.name
)) {
278 r
= strv_extend(x
, item
->name
.name
);
291 bus_kernel_cmd_free(bus
, cmd
.offset
);
295 static int bus_list_names_kernel(sd_bus
*bus
, char ***acquired
, char ***activatable
) {
296 _cleanup_strv_free_
char **x
= NULL
, **y
= NULL
;
300 r
= kernel_get_list(bus
, KDBUS_LIST_UNIQUE
| KDBUS_LIST_NAMES
, &x
);
306 r
= kernel_get_list(bus
, KDBUS_LIST_ACTIVATORS
, &y
);
322 static int bus_list_names_dbus1(sd_bus
*bus
, char ***acquired
, char ***activatable
) {
323 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
324 _cleanup_strv_free_
char **x
= NULL
, **y
= NULL
;
328 r
= sd_bus_call_method(
330 "org.freedesktop.DBus",
331 "/org/freedesktop/DBus",
332 "org.freedesktop.DBus",
340 r
= sd_bus_message_read_strv(reply
, &x
);
344 reply
= sd_bus_message_unref(reply
);
348 r
= sd_bus_call_method(
350 "org.freedesktop.DBus",
351 "/org/freedesktop/DBus",
352 "org.freedesktop.DBus",
353 "ListActivatableNames",
360 r
= sd_bus_message_read_strv(reply
, &y
);
376 _public_
int sd_bus_list_names(sd_bus
*bus
, char ***acquired
, char ***activatable
) {
377 assert_return(bus
, -EINVAL
);
378 assert_return(acquired
|| activatable
, -EINVAL
);
379 assert_return(!bus_pid_changed(bus
), -ECHILD
);
381 if (!bus
->bus_client
)
384 if (!BUS_IS_OPEN(bus
->state
))
388 return bus_list_names_kernel(bus
, acquired
, activatable
);
390 return bus_list_names_dbus1(bus
, acquired
, activatable
);
393 static int bus_populate_creds_from_items(
395 struct kdbus_info
*info
,
399 struct kdbus_item
*item
;
407 KDBUS_ITEM_FOREACH(item
, info
, items
) {
409 switch (item
->type
) {
411 case KDBUS_ITEM_PIDS
:
413 if (mask
& SD_BUS_CREDS_PID
&& item
->pids
.pid
> 0) {
414 c
->pid
= (pid_t
) item
->pids
.pid
;
415 c
->mask
|= SD_BUS_CREDS_PID
;
418 if (mask
& SD_BUS_CREDS_TID
&& item
->pids
.tid
> 0) {
419 c
->tid
= (pid_t
) item
->pids
.tid
;
420 c
->mask
|= SD_BUS_CREDS_TID
;
423 if (mask
& SD_BUS_CREDS_PPID
) {
424 if (item
->pids
.ppid
> 0) {
425 c
->ppid
= (pid_t
) item
->pids
.ppid
;
426 c
->mask
|= SD_BUS_CREDS_PPID
;
427 } else if (item
->pids
.pid
== 1) {
428 /* The structure doesn't
429 * really distinguish the case
430 * where a process has no
431 * parent and where we don't
432 * know it because it could
433 * not be translated due to
434 * namespaces. However, we
435 * know that PID 1 has no
436 * parent process, hence let's
437 * patch that in, manually. */
439 c
->mask
|= SD_BUS_CREDS_PPID
;
445 case KDBUS_ITEM_CREDS
:
447 if (mask
& SD_BUS_CREDS_UID
&& (uid_t
) item
->creds
.uid
!= UID_INVALID
) {
448 c
->uid
= (uid_t
) item
->creds
.uid
;
449 c
->mask
|= SD_BUS_CREDS_UID
;
452 if (mask
& SD_BUS_CREDS_EUID
&& (uid_t
) item
->creds
.euid
!= UID_INVALID
) {
453 c
->euid
= (uid_t
) item
->creds
.euid
;
454 c
->mask
|= SD_BUS_CREDS_EUID
;
457 if (mask
& SD_BUS_CREDS_SUID
&& (uid_t
) item
->creds
.suid
!= UID_INVALID
) {
458 c
->suid
= (uid_t
) item
->creds
.suid
;
459 c
->mask
|= SD_BUS_CREDS_SUID
;
462 if (mask
& SD_BUS_CREDS_FSUID
&& (uid_t
) item
->creds
.fsuid
!= UID_INVALID
) {
463 c
->fsuid
= (uid_t
) item
->creds
.fsuid
;
464 c
->mask
|= SD_BUS_CREDS_FSUID
;
467 if (mask
& SD_BUS_CREDS_GID
&& (gid_t
) item
->creds
.gid
!= GID_INVALID
) {
468 c
->gid
= (gid_t
) item
->creds
.gid
;
469 c
->mask
|= SD_BUS_CREDS_GID
;
472 if (mask
& SD_BUS_CREDS_EGID
&& (gid_t
) item
->creds
.egid
!= GID_INVALID
) {
473 c
->egid
= (gid_t
) item
->creds
.egid
;
474 c
->mask
|= SD_BUS_CREDS_EGID
;
477 if (mask
& SD_BUS_CREDS_SGID
&& (gid_t
) item
->creds
.sgid
!= GID_INVALID
) {
478 c
->sgid
= (gid_t
) item
->creds
.sgid
;
479 c
->mask
|= SD_BUS_CREDS_SGID
;
482 if (mask
& SD_BUS_CREDS_FSGID
&& (gid_t
) item
->creds
.fsgid
!= GID_INVALID
) {
483 c
->fsgid
= (gid_t
) item
->creds
.fsgid
;
484 c
->mask
|= SD_BUS_CREDS_FSGID
;
489 case KDBUS_ITEM_PID_COMM
:
490 if (mask
& SD_BUS_CREDS_COMM
) {
491 r
= free_and_strdup(&c
->comm
, item
->str
);
495 c
->mask
|= SD_BUS_CREDS_COMM
;
499 case KDBUS_ITEM_TID_COMM
:
500 if (mask
& SD_BUS_CREDS_TID_COMM
) {
501 r
= free_and_strdup(&c
->tid_comm
, item
->str
);
505 c
->mask
|= SD_BUS_CREDS_TID_COMM
;
510 if (mask
& SD_BUS_CREDS_EXE
) {
511 r
= free_and_strdup(&c
->exe
, item
->str
);
515 c
->mask
|= SD_BUS_CREDS_EXE
;
519 case KDBUS_ITEM_CMDLINE
:
520 if (mask
& SD_BUS_CREDS_CMDLINE
) {
521 c
->cmdline_size
= item
->size
- offsetof(struct kdbus_item
, data
);
522 c
->cmdline
= memdup(item
->data
, c
->cmdline_size
);
526 c
->mask
|= SD_BUS_CREDS_CMDLINE
;
530 case KDBUS_ITEM_CGROUP
:
531 m
= (SD_BUS_CREDS_CGROUP
| SD_BUS_CREDS_UNIT
|
532 SD_BUS_CREDS_USER_UNIT
| SD_BUS_CREDS_SLICE
|
533 SD_BUS_CREDS_SESSION
| SD_BUS_CREDS_OWNER_UID
) & mask
;
536 r
= free_and_strdup(&c
->cgroup
, item
->str
);
540 r
= bus_get_root_path(bus
);
544 r
= free_and_strdup(&c
->cgroup_root
, bus
->cgroup_root
);
552 case KDBUS_ITEM_CAPS
:
553 m
= (SD_BUS_CREDS_EFFECTIVE_CAPS
| SD_BUS_CREDS_PERMITTED_CAPS
|
554 SD_BUS_CREDS_INHERITABLE_CAPS
| SD_BUS_CREDS_BOUNDING_CAPS
) & mask
;
557 if (item
->caps
.last_cap
!= cap_last_cap() ||
558 item
->size
- offsetof(struct kdbus_item
, caps
.caps
) < DIV_ROUND_UP(item
->caps
.last_cap
, 32U) * 4 * 4)
561 c
->capability
= memdup(item
->caps
.caps
, item
->size
- offsetof(struct kdbus_item
, caps
.caps
));
569 case KDBUS_ITEM_SECLABEL
:
570 if (mask
& SD_BUS_CREDS_SELINUX_CONTEXT
) {
571 r
= free_and_strdup(&c
->label
, item
->str
);
575 c
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
579 case KDBUS_ITEM_AUDIT
:
580 if (mask
& SD_BUS_CREDS_AUDIT_SESSION_ID
) {
581 c
->audit_session_id
= (uint32_t) item
->audit
.sessionid
;
582 c
->mask
|= SD_BUS_CREDS_AUDIT_SESSION_ID
;
585 if (mask
& SD_BUS_CREDS_AUDIT_LOGIN_UID
) {
586 c
->audit_login_uid
= (uid_t
) item
->audit
.loginuid
;
587 c
->mask
|= SD_BUS_CREDS_AUDIT_LOGIN_UID
;
591 case KDBUS_ITEM_OWNED_NAME
:
592 if ((mask
& SD_BUS_CREDS_WELL_KNOWN_NAMES
) && service_name_is_valid(item
->name
.name
)) {
593 r
= strv_extend(&c
->well_known_names
, item
->name
.name
);
597 c
->mask
|= SD_BUS_CREDS_WELL_KNOWN_NAMES
;
601 case KDBUS_ITEM_CONN_DESCRIPTION
:
602 if (mask
& SD_BUS_CREDS_DESCRIPTION
) {
603 r
= free_and_strdup(&c
->description
, item
->str
);
607 c
->mask
|= SD_BUS_CREDS_DESCRIPTION
;
611 case KDBUS_ITEM_AUXGROUPS
:
612 if (mask
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
) {
616 n
= (item
->size
- offsetof(struct kdbus_item
, data64
)) / sizeof(uint64_t);
621 for (i
= 0; i
< n
; i
++)
622 g
[i
] = item
->data64
[i
];
624 free(c
->supplementary_gids
);
625 c
->supplementary_gids
= g
;
626 c
->n_supplementary_gids
= n
;
628 c
->mask
|= SD_BUS_CREDS_SUPPLEMENTARY_GIDS
;
637 int bus_get_name_creds_kdbus(
641 bool allow_activator
,
642 sd_bus_creds
**creds
) {
644 _cleanup_bus_creds_unref_ sd_bus_creds
*c
= NULL
;
645 struct kdbus_cmd_info
*cmd
;
646 struct kdbus_info
*conn_info
;
651 if (streq(name
, "org.freedesktop.DBus"))
654 r
= bus_kernel_parse_unique_name(name
, &id
);
658 size
= offsetof(struct kdbus_cmd_info
, items
);
659 cmd
= alloca0_align(size
, 8);
662 l
= strlen(name
) + 1;
663 size
= offsetof(struct kdbus_cmd_info
, items
) + KDBUS_ITEM_SIZE(l
);
664 cmd
= alloca0_align(size
, 8);
665 cmd
->items
[0].size
= KDBUS_ITEM_HEADER_SIZE
+ l
;
666 cmd
->items
[0].type
= KDBUS_ITEM_NAME
;
667 memcpy(cmd
->items
[0].str
, name
, l
);
670 /* If augmentation is on, and the bus didn't provide us
671 * the bits we want, then ask for the PID/TID so that we
672 * can read the rest from /proc. */
673 if ((mask
& SD_BUS_CREDS_AUGMENT
) &&
674 (mask
& (SD_BUS_CREDS_PPID
|
675 SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
|
676 SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
|
677 SD_BUS_CREDS_COMM
|SD_BUS_CREDS_TID_COMM
|SD_BUS_CREDS_EXE
|SD_BUS_CREDS_CMDLINE
|
678 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
|
679 SD_BUS_CREDS_EFFECTIVE_CAPS
|SD_BUS_CREDS_PERMITTED_CAPS
|SD_BUS_CREDS_INHERITABLE_CAPS
|SD_BUS_CREDS_BOUNDING_CAPS
|
680 SD_BUS_CREDS_SELINUX_CONTEXT
|
681 SD_BUS_CREDS_AUDIT_SESSION_ID
|SD_BUS_CREDS_AUDIT_LOGIN_UID
)))
682 mask
|= SD_BUS_CREDS_PID
;
685 cmd
->attach_flags
= attach_flags_to_kdbus(mask
);
687 r
= ioctl(bus
->input_fd
, KDBUS_CMD_CONN_INFO
, cmd
);
691 conn_info
= (struct kdbus_info
*) ((uint8_t *) bus
->kdbus_buffer
+ cmd
->offset
);
693 /* Non-activated names are considered not available */
694 if (!allow_activator
&& (conn_info
->flags
& KDBUS_HELLO_ACTIVATOR
)) {
708 if (mask
& SD_BUS_CREDS_UNIQUE_NAME
) {
709 if (asprintf(&c
->unique_name
, ":1.%llu", (unsigned long long) conn_info
->id
) < 0) {
714 c
->mask
|= SD_BUS_CREDS_UNIQUE_NAME
;
717 /* If KDBUS_ITEM_OWNED_NAME is requested then we'll get 0 of
718 them in case the service has no names. This does not mean
719 however that the list of owned names could not be
720 acquired. Hence, let's explicitly clarify that the data is
722 c
->mask
|= mask
& SD_BUS_CREDS_WELL_KNOWN_NAMES
;
724 r
= bus_populate_creds_from_items(bus
, conn_info
, mask
, c
);
728 r
= bus_creds_add_more(c
, mask
, 0, 0);
740 bus_kernel_cmd_free(bus
, cmd
->offset
);
744 static int bus_get_name_creds_dbus1(
748 sd_bus_creds
**creds
) {
750 _cleanup_bus_message_unref_ sd_bus_message
*reply_unique
= NULL
, *reply
= NULL
;
751 _cleanup_bus_creds_unref_ sd_bus_creds
*c
= NULL
;
752 const char *unique
= NULL
;
756 /* Only query the owner if the caller wants to know it or if
757 * the caller just wants to check whether a name exists */
758 if ((mask
& SD_BUS_CREDS_UNIQUE_NAME
) || mask
== 0) {
759 r
= sd_bus_call_method(
761 "org.freedesktop.DBus",
762 "/org/freedesktop/DBus",
763 "org.freedesktop.DBus",
772 r
= sd_bus_message_read(reply_unique
, "s", &unique
);
782 if ((mask
& SD_BUS_CREDS_UNIQUE_NAME
) && unique
) {
783 c
->unique_name
= strdup(unique
);
787 c
->mask
|= SD_BUS_CREDS_UNIQUE_NAME
;
790 if ((mask
& SD_BUS_CREDS_PID
) ||
791 ((mask
& SD_BUS_CREDS_AUGMENT
) &&
792 (mask
& (SD_BUS_CREDS_UID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
|
793 SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
|
794 SD_BUS_CREDS_COMM
|SD_BUS_CREDS_EXE
|SD_BUS_CREDS_CMDLINE
|
795 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
|
796 SD_BUS_CREDS_EFFECTIVE_CAPS
|SD_BUS_CREDS_PERMITTED_CAPS
|SD_BUS_CREDS_INHERITABLE_CAPS
|SD_BUS_CREDS_BOUNDING_CAPS
|
797 SD_BUS_CREDS_SELINUX_CONTEXT
|
798 SD_BUS_CREDS_AUDIT_SESSION_ID
|SD_BUS_CREDS_AUDIT_LOGIN_UID
)))) {
802 r
= sd_bus_call_method(
804 "org.freedesktop.DBus",
805 "/org/freedesktop/DBus",
806 "org.freedesktop.DBus",
807 "GetConnectionUnixProcessID",
811 unique
? unique
: name
);
815 r
= sd_bus_message_read(reply
, "u", &u
);
820 if (mask
& SD_BUS_CREDS_PID
) {
822 c
->mask
|= SD_BUS_CREDS_PID
;
825 reply
= sd_bus_message_unref(reply
);
828 if (mask
& SD_BUS_CREDS_EUID
) {
831 r
= sd_bus_call_method(
833 "org.freedesktop.DBus",
834 "/org/freedesktop/DBus",
835 "org.freedesktop.DBus",
836 "GetConnectionUnixUser",
840 unique
? unique
: name
);
844 r
= sd_bus_message_read(reply
, "u", &u
);
849 c
->mask
|= SD_BUS_CREDS_EUID
;
851 reply
= sd_bus_message_unref(reply
);
854 if (mask
& SD_BUS_CREDS_SELINUX_CONTEXT
) {
855 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
856 const void *p
= NULL
;
859 r
= sd_bus_call_method(
861 "org.freedesktop.DBus",
862 "/org/freedesktop/DBus",
863 "org.freedesktop.DBus",
864 "GetConnectionSELinuxSecurityContext",
868 unique
? unique
: name
);
870 if (!sd_bus_error_has_name(&error
, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
873 r
= sd_bus_message_read_array(reply
, 'y', &p
, &sz
);
877 c
->label
= strndup(p
, sz
);
881 c
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
885 r
= bus_creds_add_more(c
, mask
, pid
, 0);
898 _public_
int sd_bus_get_name_creds(
902 sd_bus_creds
**creds
) {
904 assert_return(bus
, -EINVAL
);
905 assert_return(name
, -EINVAL
);
906 assert_return((mask
& ~SD_BUS_CREDS_AUGMENT
) <= _SD_BUS_CREDS_ALL
, -EOPNOTSUPP
);
907 assert_return(mask
== 0 || creds
, -EINVAL
);
908 assert_return(!bus_pid_changed(bus
), -ECHILD
);
909 assert_return(service_name_is_valid(name
), -EINVAL
);
911 if (!bus
->bus_client
)
914 if (streq(name
, "org.freedesktop.DBus.Local"))
917 if (!BUS_IS_OPEN(bus
->state
))
921 return bus_get_name_creds_kdbus(bus
, name
, mask
, false, creds
);
923 return bus_get_name_creds_dbus1(bus
, name
, mask
, creds
);
926 static int bus_get_owner_creds_kdbus(sd_bus
*bus
, uint64_t mask
, sd_bus_creds
**ret
) {
927 _cleanup_bus_creds_unref_ sd_bus_creds
*c
= NULL
;
928 struct kdbus_cmd_info cmd
= {
929 .size
= sizeof(struct kdbus_cmd_info
),
931 struct kdbus_info
*creator_info
;
939 /* If augmentation is on, and the bus doesn't didn't allow us
940 * to get the bits we want, then ask for the PID/TID so that we
941 * can read the rest from /proc. */
942 if ((mask
& SD_BUS_CREDS_AUGMENT
) &&
943 (mask
& (SD_BUS_CREDS_PPID
|
944 SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
|
945 SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
|
946 SD_BUS_CREDS_COMM
|SD_BUS_CREDS_TID_COMM
|SD_BUS_CREDS_EXE
|SD_BUS_CREDS_CMDLINE
|
947 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
|
948 SD_BUS_CREDS_EFFECTIVE_CAPS
|SD_BUS_CREDS_PERMITTED_CAPS
|SD_BUS_CREDS_INHERITABLE_CAPS
|SD_BUS_CREDS_BOUNDING_CAPS
|
949 SD_BUS_CREDS_SELINUX_CONTEXT
|
950 SD_BUS_CREDS_AUDIT_SESSION_ID
|SD_BUS_CREDS_AUDIT_LOGIN_UID
)))
951 mask
|= SD_BUS_CREDS_PID
;
953 cmd
.attach_flags
= attach_flags_to_kdbus(mask
);
955 r
= ioctl(bus
->input_fd
, KDBUS_CMD_BUS_CREATOR_INFO
, &cmd
);
959 creator_info
= (struct kdbus_info
*) ((uint8_t *) bus
->kdbus_buffer
+ cmd
.offset
);
961 r
= bus_populate_creds_from_items(bus
, creator_info
, mask
, c
);
962 bus_kernel_cmd_free(bus
, cmd
.offset
);
966 r
= bus_creds_add_more(c
, mask
, pid
, 0);
975 static int bus_get_owner_creds_dbus1(sd_bus
*bus
, uint64_t mask
, sd_bus_creds
**ret
) {
976 _cleanup_bus_creds_unref_ sd_bus_creds
*c
= NULL
;
979 bool do_label
= bus
->label
&& (mask
& SD_BUS_CREDS_SELINUX_CONTEXT
);
981 /* Avoid allocating anything if we have no chance of returning useful data */
982 if (!bus
->ucred_valid
&& !do_label
)
989 if (bus
->ucred_valid
) {
990 if (bus
->ucred
.pid
> 0) {
991 pid
= c
->pid
= bus
->ucred
.pid
;
992 c
->mask
|= SD_BUS_CREDS_PID
& mask
;
995 if (bus
->ucred
.uid
!= UID_INVALID
) {
996 c
->euid
= bus
->ucred
.uid
;
997 c
->mask
|= SD_BUS_CREDS_EUID
& mask
;
1000 if (bus
->ucred
.gid
!= GID_INVALID
) {
1001 c
->egid
= bus
->ucred
.gid
;
1002 c
->mask
|= SD_BUS_CREDS_EGID
& mask
;
1007 c
->label
= strdup(bus
->label
);
1011 c
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
1014 r
= bus_creds_add_more(c
, mask
, pid
, 0);
1023 _public_
int sd_bus_get_owner_creds(sd_bus
*bus
, uint64_t mask
, sd_bus_creds
**ret
) {
1024 assert_return(bus
, -EINVAL
);
1025 assert_return((mask
& ~SD_BUS_CREDS_AUGMENT
) <= _SD_BUS_CREDS_ALL
, -EOPNOTSUPP
);
1026 assert_return(ret
, -EINVAL
);
1027 assert_return(!bus_pid_changed(bus
), -ECHILD
);
1029 if (!BUS_IS_OPEN(bus
->state
))
1033 return bus_get_owner_creds_kdbus(bus
, mask
, ret
);
1035 return bus_get_owner_creds_dbus1(bus
, mask
, ret
);
1038 static int add_name_change_match(sd_bus
*bus
,
1041 const char *old_owner
,
1042 const char *new_owner
) {
1044 uint64_t name_id
= KDBUS_MATCH_ID_ANY
, old_owner_id
= 0, new_owner_id
= 0;
1045 int is_name_id
= -1, r
;
1046 struct kdbus_item
*item
;
1050 /* If we encounter a match that could match against
1051 * NameOwnerChanged messages, then we need to create
1052 * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
1053 * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
1054 * multiple if the match is underspecified.
1056 * The NameOwnerChanged signals take three parameters with
1057 * unique or well-known names, but only some forms actually
1060 * WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD
1061 * WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE
1062 * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE
1063 * UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD
1064 * UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE
1066 * For the latter two the two unique names must be identical.
1071 is_name_id
= bus_kernel_parse_unique_name(name
, &name_id
);
1076 if (!isempty(old_owner
)) {
1077 r
= bus_kernel_parse_unique_name(old_owner
, &old_owner_id
);
1082 if (is_name_id
> 0 && old_owner_id
!= name_id
)
1085 old_owner_id
= KDBUS_MATCH_ID_ANY
;
1087 if (!isempty(new_owner
)) {
1088 r
= bus_kernel_parse_unique_name(new_owner
, &new_owner_id
);
1093 if (is_name_id
> 0 && new_owner_id
!= name_id
)
1096 new_owner_id
= KDBUS_MATCH_ID_ANY
;
1098 if (is_name_id
<= 0) {
1099 struct kdbus_cmd_match
*m
;
1102 /* If the name argument is missing or is a well-known
1103 * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
1106 l
= name
? strlen(name
) + 1 : 0;
1108 sz
= ALIGN8(offsetof(struct kdbus_cmd_match
, items
) +
1109 offsetof(struct kdbus_item
, name_change
) +
1110 offsetof(struct kdbus_notify_name_change
, name
) +
1113 m
= alloca0_align(sz
, 8);
1119 offsetof(struct kdbus_item
, name_change
) +
1120 offsetof(struct kdbus_notify_name_change
, name
) +
1123 item
->name_change
.old_id
.id
= old_owner_id
;
1124 item
->name_change
.new_id
.id
= new_owner_id
;
1127 memcpy(item
->name_change
.name
, name
, l
);
1129 /* If the old name is unset or empty, then
1130 * this can match against added names */
1131 if (isempty(old_owner
)) {
1132 item
->type
= KDBUS_ITEM_NAME_ADD
;
1134 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1139 /* If the new name is unset or empty, then
1140 * this can match against removed names */
1141 if (isempty(new_owner
)) {
1142 item
->type
= KDBUS_ITEM_NAME_REMOVE
;
1144 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1149 /* The CHANGE match we need in either case, because
1150 * what is reported as a name change by the kernel
1151 * might just be an owner change between starter and
1152 * normal clients. For userspace such a change should
1153 * be considered a removal/addition, hence let's
1154 * subscribe to this unconditionally. */
1155 item
->type
= KDBUS_ITEM_NAME_CHANGE
;
1156 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1161 if (is_name_id
!= 0) {
1162 struct kdbus_cmd_match
*m
;
1165 /* If the name argument is missing or is a unique
1166 * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
1169 sz
= ALIGN8(offsetof(struct kdbus_cmd_match
, items
) +
1170 offsetof(struct kdbus_item
, id_change
) +
1171 sizeof(struct kdbus_notify_id_change
));
1173 m
= alloca0_align(sz
, 8);
1179 offsetof(struct kdbus_item
, id_change
) +
1180 sizeof(struct kdbus_notify_id_change
);
1181 item
->id_change
.id
= name_id
;
1183 /* If the old name is unset or empty, then this can
1184 * match against added ids */
1185 if (isempty(old_owner
)) {
1186 item
->type
= KDBUS_ITEM_ID_ADD
;
1187 if (!isempty(new_owner
))
1188 item
->id_change
.id
= new_owner_id
;
1190 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1195 /* If thew new name is unset or empty, then this can
1196 * match against removed ids */
1197 if (isempty(new_owner
)) {
1198 item
->type
= KDBUS_ITEM_ID_REMOVE
;
1199 if (!isempty(old_owner
))
1200 item
->id_change
.id
= old_owner_id
;
1202 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1211 int bus_add_match_internal_kernel(
1213 struct bus_match_component
*components
,
1214 unsigned n_components
,
1217 struct kdbus_cmd_match
*m
;
1218 struct kdbus_item
*item
;
1221 const char *sender
= NULL
;
1222 size_t sender_length
= 0;
1223 uint64_t src_id
= KDBUS_MATCH_ID_ANY
, dst_id
= KDBUS_MATCH_ID_ANY
;
1224 bool using_bloom
= false;
1226 bool matches_name_change
= true;
1227 const char *name_change_arg
[3] = {};
1232 /* Monitor streams don't support matches, make this a NOP */
1233 if (bus
->hello_flags
& KDBUS_HELLO_MONITOR
)
1236 bloom
= alloca0(bus
->bloom_size
);
1238 sz
= ALIGN8(offsetof(struct kdbus_cmd_match
, items
));
1240 for (i
= 0; i
< n_components
; i
++) {
1241 struct bus_match_component
*c
= &components
[i
];
1245 case BUS_MATCH_SENDER
:
1246 if (!streq(c
->value_str
, "org.freedesktop.DBus"))
1247 matches_name_change
= false;
1249 r
= bus_kernel_parse_unique_name(c
->value_str
, &src_id
);
1253 sz
+= ALIGN8(offsetof(struct kdbus_item
, id
) + sizeof(uint64_t));
1255 sender
= c
->value_str
;
1256 sender_length
= strlen(sender
);
1257 sz
+= ALIGN8(offsetof(struct kdbus_item
, str
) + sender_length
+ 1);
1262 case BUS_MATCH_MESSAGE_TYPE
:
1263 if (c
->value_u8
!= SD_BUS_MESSAGE_SIGNAL
)
1264 matches_name_change
= false;
1266 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, "message-type", bus_message_type_to_string(c
->value_u8
));
1270 case BUS_MATCH_INTERFACE
:
1271 if (!streq(c
->value_str
, "org.freedesktop.DBus"))
1272 matches_name_change
= false;
1274 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, "interface", c
->value_str
);
1278 case BUS_MATCH_MEMBER
:
1279 if (!streq(c
->value_str
, "NameOwnerChanged"))
1280 matches_name_change
= false;
1282 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, "member", c
->value_str
);
1286 case BUS_MATCH_PATH
:
1287 if (!streq(c
->value_str
, "/org/freedesktop/DBus"))
1288 matches_name_change
= false;
1290 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, "path", c
->value_str
);
1294 case BUS_MATCH_PATH_NAMESPACE
:
1295 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, "path-slash-prefix", c
->value_str
);
1299 case BUS_MATCH_ARG
...BUS_MATCH_ARG_LAST
: {
1300 char buf
[sizeof("arg")-1 + 2 + 1];
1302 if (c
->type
- BUS_MATCH_ARG
< 3)
1303 name_change_arg
[c
->type
- BUS_MATCH_ARG
] = c
->value_str
;
1305 xsprintf(buf
, "arg%i", c
->type
- BUS_MATCH_ARG
);
1306 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, buf
, c
->value_str
);
1311 case BUS_MATCH_ARG_PATH
...BUS_MATCH_ARG_PATH_LAST
: {
1313 * XXX: DBus spec defines arg[0..63]path= matching to be
1314 * a two-way glob. That is, if either string is a prefix
1315 * of the other, it matches.
1316 * This is really hard to realize in bloom-filters, as
1317 * we would have to create a bloom-match for each prefix
1318 * of @c->value_str. This is excessive, hence we just
1319 * ignore all those matches and accept everything from
1320 * the kernel. People should really avoid those matches.
1321 * If they're used in real-life some day, we will have
1322 * to properly support multiple-matches here.
1327 case BUS_MATCH_ARG_NAMESPACE
...BUS_MATCH_ARG_NAMESPACE_LAST
: {
1328 char buf
[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1330 xsprintf(buf
, "arg%i-dot-prefix", c
->type
- BUS_MATCH_ARG_NAMESPACE
);
1331 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, buf
, c
->value_str
);
1336 case BUS_MATCH_DESTINATION
: {
1338 * Kernel only supports matching on destination IDs, but
1339 * not on destination names. So just skip the
1340 * destination name restriction and verify it in
1341 * user-space on retrieval.
1343 r
= bus_kernel_parse_unique_name(c
->value_str
, &dst_id
);
1347 sz
+= ALIGN8(offsetof(struct kdbus_item
, id
) + sizeof(uint64_t));
1349 /* if not a broadcast, it cannot be a name-change */
1350 if (r
<= 0 || dst_id
!= KDBUS_DST_ID_BROADCAST
)
1351 matches_name_change
= false;
1356 case BUS_MATCH_ROOT
:
1357 case BUS_MATCH_VALUE
:
1358 case BUS_MATCH_LEAF
:
1359 case _BUS_MATCH_NODE_TYPE_MAX
:
1360 case _BUS_MATCH_NODE_TYPE_INVALID
:
1361 assert_not_reached("Invalid match type?");
1366 sz
+= ALIGN8(offsetof(struct kdbus_item
, data64
) + bus
->bloom_size
);
1368 m
= alloca0_align(sz
, 8);
1374 if (src_id
!= KDBUS_MATCH_ID_ANY
) {
1375 item
->size
= offsetof(struct kdbus_item
, id
) + sizeof(uint64_t);
1376 item
->type
= KDBUS_ITEM_ID
;
1378 item
= KDBUS_ITEM_NEXT(item
);
1381 if (dst_id
!= KDBUS_MATCH_ID_ANY
) {
1382 item
->size
= offsetof(struct kdbus_item
, id
) + sizeof(uint64_t);
1383 item
->type
= KDBUS_ITEM_DST_ID
;
1385 item
= KDBUS_ITEM_NEXT(item
);
1389 item
->size
= offsetof(struct kdbus_item
, data64
) + bus
->bloom_size
;
1390 item
->type
= KDBUS_ITEM_BLOOM_MASK
;
1391 memcpy(item
->data64
, bloom
, bus
->bloom_size
);
1392 item
= KDBUS_ITEM_NEXT(item
);
1396 item
->size
= offsetof(struct kdbus_item
, str
) + sender_length
+ 1;
1397 item
->type
= KDBUS_ITEM_NAME
;
1398 memcpy(item
->str
, sender
, sender_length
+ 1);
1401 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1405 if (matches_name_change
) {
1407 /* If this match could theoretically match
1408 * NameOwnerChanged messages, we need to
1409 * install a second non-bloom filter explitly
1412 r
= add_name_change_match(bus
, cookie
, name_change_arg
[0], name_change_arg
[1], name_change_arg
[2]);
1420 #define internal_match(bus, m) \
1421 ((bus)->hello_flags & KDBUS_HELLO_MONITOR \
1422 ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
1425 static int bus_add_match_internal_dbus1(
1427 const char *match
) {
1434 e
= internal_match(bus
, match
);
1436 return sd_bus_call_method(
1438 "org.freedesktop.DBus",
1439 "/org/freedesktop/DBus",
1440 "org.freedesktop.DBus",
1448 int bus_add_match_internal(
1451 struct bus_match_component
*components
,
1452 unsigned n_components
,
1457 if (!bus
->bus_client
)
1461 return bus_add_match_internal_kernel(bus
, components
, n_components
, cookie
);
1463 return bus_add_match_internal_dbus1(bus
, match
);
1466 int bus_remove_match_internal_kernel(
1470 struct kdbus_cmd_match m
= {
1471 .size
= offsetof(struct kdbus_cmd_match
, items
),
1478 /* Monitor streams don't support matches, make this a NOP */
1479 if (bus
->hello_flags
& KDBUS_HELLO_MONITOR
)
1482 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_REMOVE
, &m
);
1489 static int bus_remove_match_internal_dbus1(
1491 const char *match
) {
1498 e
= internal_match(bus
, match
);
1500 return sd_bus_call_method(
1502 "org.freedesktop.DBus",
1503 "/org/freedesktop/DBus",
1504 "org.freedesktop.DBus",
1512 int bus_remove_match_internal(
1519 if (!bus
->bus_client
)
1523 return bus_remove_match_internal_kernel(bus
, cookie
);
1525 return bus_remove_match_internal_dbus1(bus
, match
);
1528 _public_
int sd_bus_get_name_machine_id(sd_bus
*bus
, const char *name
, sd_id128_t
*machine
) {
1529 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
, *m
= NULL
;
1533 assert_return(bus
, -EINVAL
);
1534 assert_return(name
, -EINVAL
);
1535 assert_return(machine
, -EINVAL
);
1536 assert_return(!bus_pid_changed(bus
), -ECHILD
);
1537 assert_return(service_name_is_valid(name
), -EINVAL
);
1539 if (!bus
->bus_client
)
1542 if (!BUS_IS_OPEN(bus
->state
))
1545 if (streq_ptr(name
, bus
->unique_name
))
1546 return sd_id128_get_machine(machine
);
1548 r
= sd_bus_message_new_method_call(
1553 "org.freedesktop.DBus.Peer",
1558 r
= sd_bus_message_set_auto_start(m
, false);
1562 r
= sd_bus_call(bus
, m
, 0, NULL
, &reply
);
1566 r
= sd_bus_message_read(reply
, "s", &mid
);
1570 return sd_id128_from_string(mid
, machine
);