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-bloom.h"
32 #include "bus-internal.h"
33 #include "bus-message.h"
35 #include "capability.h"
36 #include "string-util.h"
38 #include "bus-control.h"
40 _public_
int sd_bus_get_unique_name(sd_bus
*bus
, const char **unique
) {
43 assert_return(bus
, -EINVAL
);
44 assert_return(unique
, -EINVAL
);
45 assert_return(!bus_pid_changed(bus
), -ECHILD
);
50 r
= bus_ensure_running(bus
);
54 *unique
= bus
->unique_name
;
58 static int bus_request_name_kernel(sd_bus
*bus
, const char *name
, uint64_t flags
) {
67 size
= offsetof(struct kdbus_cmd
, items
) + KDBUS_ITEM_SIZE(l
);
68 n
= alloca0_align(size
, 8);
70 n
->flags
= request_name_flags_to_kdbus(flags
);
72 n
->items
[0].size
= KDBUS_ITEM_HEADER_SIZE
+ l
;
73 n
->items
[0].type
= KDBUS_ITEM_NAME
;
74 memcpy(n
->items
[0].str
, name
, l
);
76 #ifdef HAVE_VALGRIND_MEMCHECK_H
77 VALGRIND_MAKE_MEM_DEFINED(n
, n
->size
);
80 r
= ioctl(bus
->input_fd
, KDBUS_CMD_NAME_ACQUIRE
, n
);
84 if (n
->return_flags
& KDBUS_NAME_IN_QUEUE
)
90 static int bus_request_name_dbus1(sd_bus
*bus
, const char *name
, uint64_t flags
) {
91 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
92 uint32_t ret
, param
= 0;
98 if (flags
& SD_BUS_NAME_ALLOW_REPLACEMENT
)
99 param
|= BUS_NAME_ALLOW_REPLACEMENT
;
100 if (flags
& SD_BUS_NAME_REPLACE_EXISTING
)
101 param
|= BUS_NAME_REPLACE_EXISTING
;
102 if (!(flags
& SD_BUS_NAME_QUEUE
))
103 param
|= BUS_NAME_DO_NOT_QUEUE
;
105 r
= sd_bus_call_method(
107 "org.freedesktop.DBus",
108 "/org/freedesktop/DBus",
109 "org.freedesktop.DBus",
119 r
= sd_bus_message_read(reply
, "u", &ret
);
123 if (ret
== BUS_NAME_ALREADY_OWNER
)
125 else if (ret
== BUS_NAME_EXISTS
)
127 else if (ret
== BUS_NAME_IN_QUEUE
)
129 else if (ret
== BUS_NAME_PRIMARY_OWNER
)
135 _public_
int sd_bus_request_name(sd_bus
*bus
, const char *name
, uint64_t flags
) {
136 assert_return(bus
, -EINVAL
);
137 assert_return(name
, -EINVAL
);
138 assert_return(!bus_pid_changed(bus
), -ECHILD
);
139 assert_return(!(flags
& ~(SD_BUS_NAME_ALLOW_REPLACEMENT
|SD_BUS_NAME_REPLACE_EXISTING
|SD_BUS_NAME_QUEUE
)), -EINVAL
);
140 assert_return(service_name_is_valid(name
), -EINVAL
);
141 assert_return(name
[0] != ':', -EINVAL
);
143 if (!bus
->bus_client
)
146 /* Don't allow requesting the special driver and local names */
147 if (STR_IN_SET(name
, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
150 if (!BUS_IS_OPEN(bus
->state
))
154 return bus_request_name_kernel(bus
, name
, flags
);
156 return bus_request_name_dbus1(bus
, name
, flags
);
159 static int bus_release_name_kernel(sd_bus
*bus
, const char *name
) {
167 l
= strlen(name
) + 1;
168 size
= offsetof(struct kdbus_cmd
, items
) + KDBUS_ITEM_SIZE(l
);
169 n
= alloca0_align(size
, 8);
172 n
->items
[0].size
= KDBUS_ITEM_HEADER_SIZE
+ l
;
173 n
->items
[0].type
= KDBUS_ITEM_NAME
;
174 memcpy(n
->items
[0].str
, name
, l
);
176 #ifdef HAVE_VALGRIND_MEMCHECK_H
177 VALGRIND_MAKE_MEM_DEFINED(n
, n
->size
);
179 r
= ioctl(bus
->input_fd
, KDBUS_CMD_NAME_RELEASE
, n
);
186 static int bus_release_name_dbus1(sd_bus
*bus
, const char *name
) {
187 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
194 r
= sd_bus_call_method(
196 "org.freedesktop.DBus",
197 "/org/freedesktop/DBus",
198 "org.freedesktop.DBus",
207 r
= sd_bus_message_read(reply
, "u", &ret
);
210 if (ret
== BUS_NAME_NON_EXISTENT
)
212 if (ret
== BUS_NAME_NOT_OWNER
)
214 if (ret
== BUS_NAME_RELEASED
)
220 _public_
int sd_bus_release_name(sd_bus
*bus
, const char *name
) {
221 assert_return(bus
, -EINVAL
);
222 assert_return(name
, -EINVAL
);
223 assert_return(!bus_pid_changed(bus
), -ECHILD
);
224 assert_return(service_name_is_valid(name
), -EINVAL
);
225 assert_return(name
[0] != ':', -EINVAL
);
227 if (!bus
->bus_client
)
230 /* Don't allow releasing the special driver and local names */
231 if (STR_IN_SET(name
, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
234 if (!BUS_IS_OPEN(bus
->state
))
238 return bus_release_name_kernel(bus
, name
);
240 return bus_release_name_dbus1(bus
, name
);
243 static int kernel_get_list(sd_bus
*bus
, uint64_t flags
, char ***x
) {
244 struct kdbus_cmd_list cmd
= {
248 struct kdbus_info
*name_list
, *name
;
249 uint64_t previous_id
= 0;
252 /* Caller will free half-constructed list on failure... */
254 r
= ioctl(bus
->input_fd
, KDBUS_CMD_LIST
, &cmd
);
258 name_list
= (struct kdbus_info
*) ((uint8_t *) bus
->kdbus_buffer
+ cmd
.offset
);
260 KDBUS_FOREACH(name
, name_list
, cmd
.list_size
) {
261 struct kdbus_item
*item
;
263 if ((flags
& KDBUS_LIST_UNIQUE
) && name
->id
!= previous_id
&& !(name
->flags
& KDBUS_HELLO_ACTIVATOR
)) {
266 if (asprintf(&n
, ":1.%llu", (unsigned long long) name
->id
) < 0) {
271 r
= strv_consume(x
, n
);
275 previous_id
= name
->id
;
278 KDBUS_ITEM_FOREACH(item
, name
, items
) {
279 if (item
->type
== KDBUS_ITEM_OWNED_NAME
) {
280 if (service_name_is_valid(item
->name
.name
)) {
281 r
= strv_extend(x
, item
->name
.name
);
294 bus_kernel_cmd_free(bus
, cmd
.offset
);
298 static int bus_list_names_kernel(sd_bus
*bus
, char ***acquired
, char ***activatable
) {
299 _cleanup_strv_free_
char **x
= NULL
, **y
= NULL
;
303 r
= kernel_get_list(bus
, KDBUS_LIST_UNIQUE
| KDBUS_LIST_NAMES
, &x
);
309 r
= kernel_get_list(bus
, KDBUS_LIST_ACTIVATORS
, &y
);
325 static int bus_list_names_dbus1(sd_bus
*bus
, char ***acquired
, char ***activatable
) {
326 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
327 _cleanup_strv_free_
char **x
= NULL
, **y
= NULL
;
331 r
= sd_bus_call_method(
333 "org.freedesktop.DBus",
334 "/org/freedesktop/DBus",
335 "org.freedesktop.DBus",
343 r
= sd_bus_message_read_strv(reply
, &x
);
347 reply
= sd_bus_message_unref(reply
);
351 r
= sd_bus_call_method(
353 "org.freedesktop.DBus",
354 "/org/freedesktop/DBus",
355 "org.freedesktop.DBus",
356 "ListActivatableNames",
363 r
= sd_bus_message_read_strv(reply
, &y
);
379 _public_
int sd_bus_list_names(sd_bus
*bus
, char ***acquired
, char ***activatable
) {
380 assert_return(bus
, -EINVAL
);
381 assert_return(acquired
|| activatable
, -EINVAL
);
382 assert_return(!bus_pid_changed(bus
), -ECHILD
);
384 if (!bus
->bus_client
)
387 if (!BUS_IS_OPEN(bus
->state
))
391 return bus_list_names_kernel(bus
, acquired
, activatable
);
393 return bus_list_names_dbus1(bus
, acquired
, activatable
);
396 static int bus_populate_creds_from_items(
398 struct kdbus_info
*info
,
402 struct kdbus_item
*item
;
410 KDBUS_ITEM_FOREACH(item
, info
, items
) {
412 switch (item
->type
) {
414 case KDBUS_ITEM_PIDS
:
416 if (mask
& SD_BUS_CREDS_PID
&& item
->pids
.pid
> 0) {
417 c
->pid
= (pid_t
) item
->pids
.pid
;
418 c
->mask
|= SD_BUS_CREDS_PID
;
421 if (mask
& SD_BUS_CREDS_TID
&& item
->pids
.tid
> 0) {
422 c
->tid
= (pid_t
) item
->pids
.tid
;
423 c
->mask
|= SD_BUS_CREDS_TID
;
426 if (mask
& SD_BUS_CREDS_PPID
) {
427 if (item
->pids
.ppid
> 0) {
428 c
->ppid
= (pid_t
) item
->pids
.ppid
;
429 c
->mask
|= SD_BUS_CREDS_PPID
;
430 } else if (item
->pids
.pid
== 1) {
431 /* The structure doesn't
432 * really distinguish the case
433 * where a process has no
434 * parent and where we don't
435 * know it because it could
436 * not be translated due to
437 * namespaces. However, we
438 * know that PID 1 has no
439 * parent process, hence let's
440 * patch that in, manually. */
442 c
->mask
|= SD_BUS_CREDS_PPID
;
448 case KDBUS_ITEM_CREDS
:
450 if (mask
& SD_BUS_CREDS_UID
&& (uid_t
) item
->creds
.uid
!= UID_INVALID
) {
451 c
->uid
= (uid_t
) item
->creds
.uid
;
452 c
->mask
|= SD_BUS_CREDS_UID
;
455 if (mask
& SD_BUS_CREDS_EUID
&& (uid_t
) item
->creds
.euid
!= UID_INVALID
) {
456 c
->euid
= (uid_t
) item
->creds
.euid
;
457 c
->mask
|= SD_BUS_CREDS_EUID
;
460 if (mask
& SD_BUS_CREDS_SUID
&& (uid_t
) item
->creds
.suid
!= UID_INVALID
) {
461 c
->suid
= (uid_t
) item
->creds
.suid
;
462 c
->mask
|= SD_BUS_CREDS_SUID
;
465 if (mask
& SD_BUS_CREDS_FSUID
&& (uid_t
) item
->creds
.fsuid
!= UID_INVALID
) {
466 c
->fsuid
= (uid_t
) item
->creds
.fsuid
;
467 c
->mask
|= SD_BUS_CREDS_FSUID
;
470 if (mask
& SD_BUS_CREDS_GID
&& (gid_t
) item
->creds
.gid
!= GID_INVALID
) {
471 c
->gid
= (gid_t
) item
->creds
.gid
;
472 c
->mask
|= SD_BUS_CREDS_GID
;
475 if (mask
& SD_BUS_CREDS_EGID
&& (gid_t
) item
->creds
.egid
!= GID_INVALID
) {
476 c
->egid
= (gid_t
) item
->creds
.egid
;
477 c
->mask
|= SD_BUS_CREDS_EGID
;
480 if (mask
& SD_BUS_CREDS_SGID
&& (gid_t
) item
->creds
.sgid
!= GID_INVALID
) {
481 c
->sgid
= (gid_t
) item
->creds
.sgid
;
482 c
->mask
|= SD_BUS_CREDS_SGID
;
485 if (mask
& SD_BUS_CREDS_FSGID
&& (gid_t
) item
->creds
.fsgid
!= GID_INVALID
) {
486 c
->fsgid
= (gid_t
) item
->creds
.fsgid
;
487 c
->mask
|= SD_BUS_CREDS_FSGID
;
492 case KDBUS_ITEM_PID_COMM
:
493 if (mask
& SD_BUS_CREDS_COMM
) {
494 r
= free_and_strdup(&c
->comm
, item
->str
);
498 c
->mask
|= SD_BUS_CREDS_COMM
;
502 case KDBUS_ITEM_TID_COMM
:
503 if (mask
& SD_BUS_CREDS_TID_COMM
) {
504 r
= free_and_strdup(&c
->tid_comm
, item
->str
);
508 c
->mask
|= SD_BUS_CREDS_TID_COMM
;
513 if (mask
& SD_BUS_CREDS_EXE
) {
514 r
= free_and_strdup(&c
->exe
, item
->str
);
518 c
->mask
|= SD_BUS_CREDS_EXE
;
522 case KDBUS_ITEM_CMDLINE
:
523 if (mask
& SD_BUS_CREDS_CMDLINE
) {
524 c
->cmdline_size
= item
->size
- offsetof(struct kdbus_item
, data
);
525 c
->cmdline
= memdup(item
->data
, c
->cmdline_size
);
529 c
->mask
|= SD_BUS_CREDS_CMDLINE
;
533 case KDBUS_ITEM_CGROUP
:
534 m
= (SD_BUS_CREDS_CGROUP
| SD_BUS_CREDS_UNIT
|
535 SD_BUS_CREDS_USER_UNIT
| SD_BUS_CREDS_SLICE
|
536 SD_BUS_CREDS_SESSION
| SD_BUS_CREDS_OWNER_UID
) & mask
;
539 r
= free_and_strdup(&c
->cgroup
, item
->str
);
543 r
= bus_get_root_path(bus
);
547 r
= free_and_strdup(&c
->cgroup_root
, bus
->cgroup_root
);
555 case KDBUS_ITEM_CAPS
:
556 m
= (SD_BUS_CREDS_EFFECTIVE_CAPS
| SD_BUS_CREDS_PERMITTED_CAPS
|
557 SD_BUS_CREDS_INHERITABLE_CAPS
| SD_BUS_CREDS_BOUNDING_CAPS
) & mask
;
560 if (item
->caps
.last_cap
!= cap_last_cap() ||
561 item
->size
- offsetof(struct kdbus_item
, caps
.caps
) < DIV_ROUND_UP(item
->caps
.last_cap
, 32U) * 4 * 4)
564 c
->capability
= memdup(item
->caps
.caps
, item
->size
- offsetof(struct kdbus_item
, caps
.caps
));
572 case KDBUS_ITEM_SECLABEL
:
573 if (mask
& SD_BUS_CREDS_SELINUX_CONTEXT
) {
574 r
= free_and_strdup(&c
->label
, item
->str
);
578 c
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
582 case KDBUS_ITEM_AUDIT
:
583 if (mask
& SD_BUS_CREDS_AUDIT_SESSION_ID
) {
584 c
->audit_session_id
= (uint32_t) item
->audit
.sessionid
;
585 c
->mask
|= SD_BUS_CREDS_AUDIT_SESSION_ID
;
588 if (mask
& SD_BUS_CREDS_AUDIT_LOGIN_UID
) {
589 c
->audit_login_uid
= (uid_t
) item
->audit
.loginuid
;
590 c
->mask
|= SD_BUS_CREDS_AUDIT_LOGIN_UID
;
594 case KDBUS_ITEM_OWNED_NAME
:
595 if ((mask
& SD_BUS_CREDS_WELL_KNOWN_NAMES
) && service_name_is_valid(item
->name
.name
)) {
596 r
= strv_extend(&c
->well_known_names
, item
->name
.name
);
600 c
->mask
|= SD_BUS_CREDS_WELL_KNOWN_NAMES
;
604 case KDBUS_ITEM_CONN_DESCRIPTION
:
605 if (mask
& SD_BUS_CREDS_DESCRIPTION
) {
606 r
= free_and_strdup(&c
->description
, item
->str
);
610 c
->mask
|= SD_BUS_CREDS_DESCRIPTION
;
614 case KDBUS_ITEM_AUXGROUPS
:
615 if (mask
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
) {
619 n
= (item
->size
- offsetof(struct kdbus_item
, data64
)) / sizeof(uint64_t);
624 for (i
= 0; i
< n
; i
++)
625 g
[i
] = item
->data64
[i
];
627 free(c
->supplementary_gids
);
628 c
->supplementary_gids
= g
;
629 c
->n_supplementary_gids
= n
;
631 c
->mask
|= SD_BUS_CREDS_SUPPLEMENTARY_GIDS
;
640 int bus_get_name_creds_kdbus(
644 bool allow_activator
,
645 sd_bus_creds
**creds
) {
647 _cleanup_bus_creds_unref_ sd_bus_creds
*c
= NULL
;
648 struct kdbus_cmd_info
*cmd
;
649 struct kdbus_info
*conn_info
;
654 if (streq(name
, "org.freedesktop.DBus"))
657 r
= bus_kernel_parse_unique_name(name
, &id
);
661 size
= offsetof(struct kdbus_cmd_info
, items
);
662 cmd
= alloca0_align(size
, 8);
665 l
= strlen(name
) + 1;
666 size
= offsetof(struct kdbus_cmd_info
, items
) + KDBUS_ITEM_SIZE(l
);
667 cmd
= alloca0_align(size
, 8);
668 cmd
->items
[0].size
= KDBUS_ITEM_HEADER_SIZE
+ l
;
669 cmd
->items
[0].type
= KDBUS_ITEM_NAME
;
670 memcpy(cmd
->items
[0].str
, name
, l
);
673 /* If augmentation is on, and the bus didn't provide us
674 * the bits we want, then ask for the PID/TID so that we
675 * can read the rest from /proc. */
676 if ((mask
& SD_BUS_CREDS_AUGMENT
) &&
677 (mask
& (SD_BUS_CREDS_PPID
|
678 SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
|
679 SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
|
680 SD_BUS_CREDS_COMM
|SD_BUS_CREDS_TID_COMM
|SD_BUS_CREDS_EXE
|SD_BUS_CREDS_CMDLINE
|
681 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
|
682 SD_BUS_CREDS_EFFECTIVE_CAPS
|SD_BUS_CREDS_PERMITTED_CAPS
|SD_BUS_CREDS_INHERITABLE_CAPS
|SD_BUS_CREDS_BOUNDING_CAPS
|
683 SD_BUS_CREDS_SELINUX_CONTEXT
|
684 SD_BUS_CREDS_AUDIT_SESSION_ID
|SD_BUS_CREDS_AUDIT_LOGIN_UID
)))
685 mask
|= SD_BUS_CREDS_PID
;
688 cmd
->attach_flags
= attach_flags_to_kdbus(mask
);
690 r
= ioctl(bus
->input_fd
, KDBUS_CMD_CONN_INFO
, cmd
);
694 conn_info
= (struct kdbus_info
*) ((uint8_t *) bus
->kdbus_buffer
+ cmd
->offset
);
696 /* Non-activated names are considered not available */
697 if (!allow_activator
&& (conn_info
->flags
& KDBUS_HELLO_ACTIVATOR
)) {
711 if (mask
& SD_BUS_CREDS_UNIQUE_NAME
) {
712 if (asprintf(&c
->unique_name
, ":1.%llu", (unsigned long long) conn_info
->id
) < 0) {
717 c
->mask
|= SD_BUS_CREDS_UNIQUE_NAME
;
720 /* If KDBUS_ITEM_OWNED_NAME is requested then we'll get 0 of
721 them in case the service has no names. This does not mean
722 however that the list of owned names could not be
723 acquired. Hence, let's explicitly clarify that the data is
725 c
->mask
|= mask
& SD_BUS_CREDS_WELL_KNOWN_NAMES
;
727 r
= bus_populate_creds_from_items(bus
, conn_info
, mask
, c
);
731 r
= bus_creds_add_more(c
, mask
, 0, 0);
743 bus_kernel_cmd_free(bus
, cmd
->offset
);
747 static int bus_get_name_creds_dbus1(
751 sd_bus_creds
**creds
) {
753 _cleanup_bus_message_unref_ sd_bus_message
*reply_unique
= NULL
, *reply
= NULL
;
754 _cleanup_bus_creds_unref_ sd_bus_creds
*c
= NULL
;
755 const char *unique
= NULL
;
759 /* Only query the owner if the caller wants to know it or if
760 * the caller just wants to check whether a name exists */
761 if ((mask
& SD_BUS_CREDS_UNIQUE_NAME
) || mask
== 0) {
762 r
= sd_bus_call_method(
764 "org.freedesktop.DBus",
765 "/org/freedesktop/DBus",
766 "org.freedesktop.DBus",
775 r
= sd_bus_message_read(reply_unique
, "s", &unique
);
785 if ((mask
& SD_BUS_CREDS_UNIQUE_NAME
) && unique
) {
786 c
->unique_name
= strdup(unique
);
790 c
->mask
|= SD_BUS_CREDS_UNIQUE_NAME
;
793 if ((mask
& SD_BUS_CREDS_PID
) ||
794 ((mask
& SD_BUS_CREDS_AUGMENT
) &&
795 (mask
& (SD_BUS_CREDS_UID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
|
796 SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
|
797 SD_BUS_CREDS_COMM
|SD_BUS_CREDS_EXE
|SD_BUS_CREDS_CMDLINE
|
798 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
|
799 SD_BUS_CREDS_EFFECTIVE_CAPS
|SD_BUS_CREDS_PERMITTED_CAPS
|SD_BUS_CREDS_INHERITABLE_CAPS
|SD_BUS_CREDS_BOUNDING_CAPS
|
800 SD_BUS_CREDS_SELINUX_CONTEXT
|
801 SD_BUS_CREDS_AUDIT_SESSION_ID
|SD_BUS_CREDS_AUDIT_LOGIN_UID
)))) {
805 r
= sd_bus_call_method(
807 "org.freedesktop.DBus",
808 "/org/freedesktop/DBus",
809 "org.freedesktop.DBus",
810 "GetConnectionUnixProcessID",
814 unique
? unique
: name
);
818 r
= sd_bus_message_read(reply
, "u", &u
);
823 if (mask
& SD_BUS_CREDS_PID
) {
825 c
->mask
|= SD_BUS_CREDS_PID
;
828 reply
= sd_bus_message_unref(reply
);
831 if (mask
& SD_BUS_CREDS_EUID
) {
834 r
= sd_bus_call_method(
836 "org.freedesktop.DBus",
837 "/org/freedesktop/DBus",
838 "org.freedesktop.DBus",
839 "GetConnectionUnixUser",
843 unique
? unique
: name
);
847 r
= sd_bus_message_read(reply
, "u", &u
);
852 c
->mask
|= SD_BUS_CREDS_EUID
;
854 reply
= sd_bus_message_unref(reply
);
857 if (mask
& SD_BUS_CREDS_SELINUX_CONTEXT
) {
858 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
859 const void *p
= NULL
;
862 r
= sd_bus_call_method(
864 "org.freedesktop.DBus",
865 "/org/freedesktop/DBus",
866 "org.freedesktop.DBus",
867 "GetConnectionSELinuxSecurityContext",
871 unique
? unique
: name
);
873 if (!sd_bus_error_has_name(&error
, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
876 r
= sd_bus_message_read_array(reply
, 'y', &p
, &sz
);
880 c
->label
= strndup(p
, sz
);
884 c
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
888 r
= bus_creds_add_more(c
, mask
, pid
, 0);
901 _public_
int sd_bus_get_name_creds(
905 sd_bus_creds
**creds
) {
907 assert_return(bus
, -EINVAL
);
908 assert_return(name
, -EINVAL
);
909 assert_return((mask
& ~SD_BUS_CREDS_AUGMENT
) <= _SD_BUS_CREDS_ALL
, -EOPNOTSUPP
);
910 assert_return(mask
== 0 || creds
, -EINVAL
);
911 assert_return(!bus_pid_changed(bus
), -ECHILD
);
912 assert_return(service_name_is_valid(name
), -EINVAL
);
914 if (!bus
->bus_client
)
917 if (streq(name
, "org.freedesktop.DBus.Local"))
920 if (!BUS_IS_OPEN(bus
->state
))
924 return bus_get_name_creds_kdbus(bus
, name
, mask
, false, creds
);
926 return bus_get_name_creds_dbus1(bus
, name
, mask
, creds
);
929 static int bus_get_owner_creds_kdbus(sd_bus
*bus
, uint64_t mask
, sd_bus_creds
**ret
) {
930 _cleanup_bus_creds_unref_ sd_bus_creds
*c
= NULL
;
931 struct kdbus_cmd_info cmd
= {
932 .size
= sizeof(struct kdbus_cmd_info
),
934 struct kdbus_info
*creator_info
;
942 /* If augmentation is on, and the bus doesn't didn't allow us
943 * to get the bits we want, then ask for the PID/TID so that we
944 * can read the rest from /proc. */
945 if ((mask
& SD_BUS_CREDS_AUGMENT
) &&
946 (mask
& (SD_BUS_CREDS_PPID
|
947 SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
|
948 SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
|
949 SD_BUS_CREDS_COMM
|SD_BUS_CREDS_TID_COMM
|SD_BUS_CREDS_EXE
|SD_BUS_CREDS_CMDLINE
|
950 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
|
951 SD_BUS_CREDS_EFFECTIVE_CAPS
|SD_BUS_CREDS_PERMITTED_CAPS
|SD_BUS_CREDS_INHERITABLE_CAPS
|SD_BUS_CREDS_BOUNDING_CAPS
|
952 SD_BUS_CREDS_SELINUX_CONTEXT
|
953 SD_BUS_CREDS_AUDIT_SESSION_ID
|SD_BUS_CREDS_AUDIT_LOGIN_UID
)))
954 mask
|= SD_BUS_CREDS_PID
;
956 cmd
.attach_flags
= attach_flags_to_kdbus(mask
);
958 r
= ioctl(bus
->input_fd
, KDBUS_CMD_BUS_CREATOR_INFO
, &cmd
);
962 creator_info
= (struct kdbus_info
*) ((uint8_t *) bus
->kdbus_buffer
+ cmd
.offset
);
964 r
= bus_populate_creds_from_items(bus
, creator_info
, mask
, c
);
965 bus_kernel_cmd_free(bus
, cmd
.offset
);
969 r
= bus_creds_add_more(c
, mask
, pid
, 0);
978 static int bus_get_owner_creds_dbus1(sd_bus
*bus
, uint64_t mask
, sd_bus_creds
**ret
) {
979 _cleanup_bus_creds_unref_ sd_bus_creds
*c
= NULL
;
982 bool do_label
= bus
->label
&& (mask
& SD_BUS_CREDS_SELINUX_CONTEXT
);
984 /* Avoid allocating anything if we have no chance of returning useful data */
985 if (!bus
->ucred_valid
&& !do_label
)
992 if (bus
->ucred_valid
) {
993 if (bus
->ucred
.pid
> 0) {
994 pid
= c
->pid
= bus
->ucred
.pid
;
995 c
->mask
|= SD_BUS_CREDS_PID
& mask
;
998 if (bus
->ucred
.uid
!= UID_INVALID
) {
999 c
->euid
= bus
->ucred
.uid
;
1000 c
->mask
|= SD_BUS_CREDS_EUID
& mask
;
1003 if (bus
->ucred
.gid
!= GID_INVALID
) {
1004 c
->egid
= bus
->ucred
.gid
;
1005 c
->mask
|= SD_BUS_CREDS_EGID
& mask
;
1010 c
->label
= strdup(bus
->label
);
1014 c
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
1017 r
= bus_creds_add_more(c
, mask
, pid
, 0);
1026 _public_
int sd_bus_get_owner_creds(sd_bus
*bus
, uint64_t mask
, sd_bus_creds
**ret
) {
1027 assert_return(bus
, -EINVAL
);
1028 assert_return((mask
& ~SD_BUS_CREDS_AUGMENT
) <= _SD_BUS_CREDS_ALL
, -EOPNOTSUPP
);
1029 assert_return(ret
, -EINVAL
);
1030 assert_return(!bus_pid_changed(bus
), -ECHILD
);
1032 if (!BUS_IS_OPEN(bus
->state
))
1036 return bus_get_owner_creds_kdbus(bus
, mask
, ret
);
1038 return bus_get_owner_creds_dbus1(bus
, mask
, ret
);
1041 static int add_name_change_match(sd_bus
*bus
,
1044 const char *old_owner
,
1045 const char *new_owner
) {
1047 uint64_t name_id
= KDBUS_MATCH_ID_ANY
, old_owner_id
= 0, new_owner_id
= 0;
1048 int is_name_id
= -1, r
;
1049 struct kdbus_item
*item
;
1053 /* If we encounter a match that could match against
1054 * NameOwnerChanged messages, then we need to create
1055 * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
1056 * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
1057 * multiple if the match is underspecified.
1059 * The NameOwnerChanged signals take three parameters with
1060 * unique or well-known names, but only some forms actually
1063 * WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD
1064 * WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE
1065 * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE
1066 * UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD
1067 * UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE
1069 * For the latter two the two unique names must be identical.
1074 is_name_id
= bus_kernel_parse_unique_name(name
, &name_id
);
1079 if (!isempty(old_owner
)) {
1080 r
= bus_kernel_parse_unique_name(old_owner
, &old_owner_id
);
1085 if (is_name_id
> 0 && old_owner_id
!= name_id
)
1088 old_owner_id
= KDBUS_MATCH_ID_ANY
;
1090 if (!isempty(new_owner
)) {
1091 r
= bus_kernel_parse_unique_name(new_owner
, &new_owner_id
);
1096 if (is_name_id
> 0 && new_owner_id
!= name_id
)
1099 new_owner_id
= KDBUS_MATCH_ID_ANY
;
1101 if (is_name_id
<= 0) {
1102 struct kdbus_cmd_match
*m
;
1105 /* If the name argument is missing or is a well-known
1106 * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
1109 l
= name
? strlen(name
) + 1 : 0;
1111 sz
= ALIGN8(offsetof(struct kdbus_cmd_match
, items
) +
1112 offsetof(struct kdbus_item
, name_change
) +
1113 offsetof(struct kdbus_notify_name_change
, name
) +
1116 m
= alloca0_align(sz
, 8);
1122 offsetof(struct kdbus_item
, name_change
) +
1123 offsetof(struct kdbus_notify_name_change
, name
) +
1126 item
->name_change
.old_id
.id
= old_owner_id
;
1127 item
->name_change
.new_id
.id
= new_owner_id
;
1130 memcpy(item
->name_change
.name
, name
, l
);
1132 /* If the old name is unset or empty, then
1133 * this can match against added names */
1134 if (isempty(old_owner
)) {
1135 item
->type
= KDBUS_ITEM_NAME_ADD
;
1137 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1142 /* If the new name is unset or empty, then
1143 * this can match against removed names */
1144 if (isempty(new_owner
)) {
1145 item
->type
= KDBUS_ITEM_NAME_REMOVE
;
1147 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1152 /* The CHANGE match we need in either case, because
1153 * what is reported as a name change by the kernel
1154 * might just be an owner change between starter and
1155 * normal clients. For userspace such a change should
1156 * be considered a removal/addition, hence let's
1157 * subscribe to this unconditionally. */
1158 item
->type
= KDBUS_ITEM_NAME_CHANGE
;
1159 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1164 if (is_name_id
!= 0) {
1165 struct kdbus_cmd_match
*m
;
1168 /* If the name argument is missing or is a unique
1169 * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
1172 sz
= ALIGN8(offsetof(struct kdbus_cmd_match
, items
) +
1173 offsetof(struct kdbus_item
, id_change
) +
1174 sizeof(struct kdbus_notify_id_change
));
1176 m
= alloca0_align(sz
, 8);
1182 offsetof(struct kdbus_item
, id_change
) +
1183 sizeof(struct kdbus_notify_id_change
);
1184 item
->id_change
.id
= name_id
;
1186 /* If the old name is unset or empty, then this can
1187 * match against added ids */
1188 if (isempty(old_owner
)) {
1189 item
->type
= KDBUS_ITEM_ID_ADD
;
1190 if (!isempty(new_owner
))
1191 item
->id_change
.id
= new_owner_id
;
1193 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1198 /* If thew new name is unset or empty, then this can
1199 * match against removed ids */
1200 if (isempty(new_owner
)) {
1201 item
->type
= KDBUS_ITEM_ID_REMOVE
;
1202 if (!isempty(old_owner
))
1203 item
->id_change
.id
= old_owner_id
;
1205 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1214 int bus_add_match_internal_kernel(
1216 struct bus_match_component
*components
,
1217 unsigned n_components
,
1220 struct kdbus_cmd_match
*m
;
1221 struct kdbus_item
*item
;
1224 const char *sender
= NULL
;
1225 size_t sender_length
= 0;
1226 uint64_t src_id
= KDBUS_MATCH_ID_ANY
, dst_id
= KDBUS_MATCH_ID_ANY
;
1227 bool using_bloom
= false;
1229 bool matches_name_change
= true;
1230 const char *name_change_arg
[3] = {};
1235 /* Monitor streams don't support matches, make this a NOP */
1236 if (bus
->hello_flags
& KDBUS_HELLO_MONITOR
)
1239 bloom
= alloca0(bus
->bloom_size
);
1241 sz
= ALIGN8(offsetof(struct kdbus_cmd_match
, items
));
1243 for (i
= 0; i
< n_components
; i
++) {
1244 struct bus_match_component
*c
= &components
[i
];
1248 case BUS_MATCH_SENDER
:
1249 if (!streq(c
->value_str
, "org.freedesktop.DBus"))
1250 matches_name_change
= false;
1252 r
= bus_kernel_parse_unique_name(c
->value_str
, &src_id
);
1256 sz
+= ALIGN8(offsetof(struct kdbus_item
, id
) + sizeof(uint64_t));
1258 sender
= c
->value_str
;
1259 sender_length
= strlen(sender
);
1260 sz
+= ALIGN8(offsetof(struct kdbus_item
, str
) + sender_length
+ 1);
1265 case BUS_MATCH_MESSAGE_TYPE
:
1266 if (c
->value_u8
!= SD_BUS_MESSAGE_SIGNAL
)
1267 matches_name_change
= false;
1269 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, "message-type", bus_message_type_to_string(c
->value_u8
));
1273 case BUS_MATCH_INTERFACE
:
1274 if (!streq(c
->value_str
, "org.freedesktop.DBus"))
1275 matches_name_change
= false;
1277 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, "interface", c
->value_str
);
1281 case BUS_MATCH_MEMBER
:
1282 if (!streq(c
->value_str
, "NameOwnerChanged"))
1283 matches_name_change
= false;
1285 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, "member", c
->value_str
);
1289 case BUS_MATCH_PATH
:
1290 if (!streq(c
->value_str
, "/org/freedesktop/DBus"))
1291 matches_name_change
= false;
1293 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, "path", c
->value_str
);
1297 case BUS_MATCH_PATH_NAMESPACE
:
1298 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, "path-slash-prefix", c
->value_str
);
1302 case BUS_MATCH_ARG
...BUS_MATCH_ARG_LAST
: {
1303 char buf
[sizeof("arg")-1 + 2 + 1];
1305 if (c
->type
- BUS_MATCH_ARG
< 3)
1306 name_change_arg
[c
->type
- BUS_MATCH_ARG
] = c
->value_str
;
1308 xsprintf(buf
, "arg%i", c
->type
- BUS_MATCH_ARG
);
1309 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, buf
, c
->value_str
);
1314 case BUS_MATCH_ARG_HAS
...BUS_MATCH_ARG_HAS_LAST
: {
1315 char buf
[sizeof("arg")-1 + 2 + sizeof("-has")];
1317 xsprintf(buf
, "arg%i-has", c
->type
- BUS_MATCH_ARG_HAS
);
1318 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, buf
, c
->value_str
);
1323 case BUS_MATCH_ARG_PATH
...BUS_MATCH_ARG_PATH_LAST
:
1325 * XXX: DBus spec defines arg[0..63]path= matching to be
1326 * a two-way glob. That is, if either string is a prefix
1327 * of the other, it matches.
1328 * This is really hard to realize in bloom-filters, as
1329 * we would have to create a bloom-match for each prefix
1330 * of @c->value_str. This is excessive, hence we just
1331 * ignore all those matches and accept everything from
1332 * the kernel. People should really avoid those matches.
1333 * If they're used in real-life some day, we will have
1334 * to properly support multiple-matches here.
1338 case BUS_MATCH_ARG_NAMESPACE
...BUS_MATCH_ARG_NAMESPACE_LAST
: {
1339 char buf
[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1341 xsprintf(buf
, "arg%i-dot-prefix", c
->type
- BUS_MATCH_ARG_NAMESPACE
);
1342 bloom_add_pair(bloom
, bus
->bloom_size
, bus
->bloom_n_hash
, buf
, c
->value_str
);
1347 case BUS_MATCH_DESTINATION
:
1349 * Kernel only supports matching on destination IDs, but
1350 * not on destination names. So just skip the
1351 * destination name restriction and verify it in
1352 * user-space on retrieval.
1354 r
= bus_kernel_parse_unique_name(c
->value_str
, &dst_id
);
1358 sz
+= ALIGN8(offsetof(struct kdbus_item
, id
) + sizeof(uint64_t));
1360 /* if not a broadcast, it cannot be a name-change */
1361 if (r
<= 0 || dst_id
!= KDBUS_DST_ID_BROADCAST
)
1362 matches_name_change
= false;
1366 case BUS_MATCH_ROOT
:
1367 case BUS_MATCH_VALUE
:
1368 case BUS_MATCH_LEAF
:
1369 case _BUS_MATCH_NODE_TYPE_MAX
:
1370 case _BUS_MATCH_NODE_TYPE_INVALID
:
1371 assert_not_reached("Invalid match type?");
1376 sz
+= ALIGN8(offsetof(struct kdbus_item
, data64
) + bus
->bloom_size
);
1378 m
= alloca0_align(sz
, 8);
1384 if (src_id
!= KDBUS_MATCH_ID_ANY
) {
1385 item
->size
= offsetof(struct kdbus_item
, id
) + sizeof(uint64_t);
1386 item
->type
= KDBUS_ITEM_ID
;
1388 item
= KDBUS_ITEM_NEXT(item
);
1391 if (dst_id
!= KDBUS_MATCH_ID_ANY
) {
1392 item
->size
= offsetof(struct kdbus_item
, id
) + sizeof(uint64_t);
1393 item
->type
= KDBUS_ITEM_DST_ID
;
1395 item
= KDBUS_ITEM_NEXT(item
);
1399 item
->size
= offsetof(struct kdbus_item
, data64
) + bus
->bloom_size
;
1400 item
->type
= KDBUS_ITEM_BLOOM_MASK
;
1401 memcpy(item
->data64
, bloom
, bus
->bloom_size
);
1402 item
= KDBUS_ITEM_NEXT(item
);
1406 item
->size
= offsetof(struct kdbus_item
, str
) + sender_length
+ 1;
1407 item
->type
= KDBUS_ITEM_NAME
;
1408 memcpy(item
->str
, sender
, sender_length
+ 1);
1411 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_ADD
, m
);
1415 if (matches_name_change
) {
1417 /* If this match could theoretically match
1418 * NameOwnerChanged messages, we need to
1419 * install a second non-bloom filter explitly
1422 r
= add_name_change_match(bus
, cookie
, name_change_arg
[0], name_change_arg
[1], name_change_arg
[2]);
1430 #define internal_match(bus, m) \
1431 ((bus)->hello_flags & KDBUS_HELLO_MONITOR \
1432 ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
1435 static int bus_add_match_internal_dbus1(
1437 const char *match
) {
1444 e
= internal_match(bus
, match
);
1446 return sd_bus_call_method(
1448 "org.freedesktop.DBus",
1449 "/org/freedesktop/DBus",
1450 "org.freedesktop.DBus",
1458 int bus_add_match_internal(
1461 struct bus_match_component
*components
,
1462 unsigned n_components
,
1467 if (!bus
->bus_client
)
1471 return bus_add_match_internal_kernel(bus
, components
, n_components
, cookie
);
1473 return bus_add_match_internal_dbus1(bus
, match
);
1476 int bus_remove_match_internal_kernel(
1480 struct kdbus_cmd_match m
= {
1481 .size
= offsetof(struct kdbus_cmd_match
, items
),
1488 /* Monitor streams don't support matches, make this a NOP */
1489 if (bus
->hello_flags
& KDBUS_HELLO_MONITOR
)
1492 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MATCH_REMOVE
, &m
);
1499 static int bus_remove_match_internal_dbus1(
1501 const char *match
) {
1508 e
= internal_match(bus
, match
);
1510 return sd_bus_call_method(
1512 "org.freedesktop.DBus",
1513 "/org/freedesktop/DBus",
1514 "org.freedesktop.DBus",
1522 int bus_remove_match_internal(
1529 if (!bus
->bus_client
)
1533 return bus_remove_match_internal_kernel(bus
, cookie
);
1535 return bus_remove_match_internal_dbus1(bus
, match
);
1538 _public_
int sd_bus_get_name_machine_id(sd_bus
*bus
, const char *name
, sd_id128_t
*machine
) {
1539 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
, *m
= NULL
;
1543 assert_return(bus
, -EINVAL
);
1544 assert_return(name
, -EINVAL
);
1545 assert_return(machine
, -EINVAL
);
1546 assert_return(!bus_pid_changed(bus
), -ECHILD
);
1547 assert_return(service_name_is_valid(name
), -EINVAL
);
1549 if (!bus
->bus_client
)
1552 if (!BUS_IS_OPEN(bus
->state
))
1555 if (streq_ptr(name
, bus
->unique_name
))
1556 return sd_id128_get_machine(machine
);
1558 r
= sd_bus_message_new_method_call(
1563 "org.freedesktop.DBus.Peer",
1568 r
= sd_bus_message_set_auto_start(m
, false);
1572 r
= sd_bus_call(bus
, m
, 0, NULL
, &reply
);
1576 r
= sd_bus_message_read(reply
, "s", &mid
);
1580 return sd_id128_from_string(mid
, machine
);