1 /* SPDX-License-Identifier: LGPL-2.1+ */
9 #include "alloc-util.h"
10 #include "bus-common-errors.h"
11 #include "bus-error.h"
12 #include "bus-internal.h"
13 #include "bus-polkit.h"
14 #include "dbus-automount.h"
15 #include "dbus-cgroup.h"
16 #include "dbus-device.h"
17 #include "dbus-execute.h"
19 #include "dbus-kill.h"
20 #include "dbus-manager.h"
21 #include "dbus-mount.h"
22 #include "dbus-path.h"
23 #include "dbus-scope.h"
24 #include "dbus-service.h"
25 #include "dbus-slice.h"
26 #include "dbus-socket.h"
27 #include "dbus-swap.h"
28 #include "dbus-target.h"
29 #include "dbus-timer.h"
30 #include "dbus-unit.h"
36 #include "process-util.h"
37 #include "selinux-access.h"
38 #include "serialize.h"
41 #include "string-util.h"
44 #include "user-util.h"
46 #define CONNECTIONS_MAX 4096
48 static void destroy_bus(Manager
*m
, sd_bus
**bus
);
50 int bus_send_pending_reload_message(Manager
*m
) {
55 if (!m
->pending_reload_message
)
58 /* If we cannot get rid of this message we won't dispatch any D-Bus messages, so that we won't end up wanting
59 * to queue another message. */
61 r
= sd_bus_send(NULL
, m
->pending_reload_message
, NULL
);
63 log_warning_errno(r
, "Failed to send queued message, ignoring: %m");
65 m
->pending_reload_message
= sd_bus_message_unref(m
->pending_reload_message
);
70 int bus_forward_agent_released(Manager
*m
, const char *path
) {
76 if (!MANAGER_IS_SYSTEM(m
))
82 /* If we are running a system instance we forward the agent message on the system bus, so that the user
83 * instances get notified about this, too */
85 r
= sd_bus_emit_signal(m
->system_bus
,
86 "/org/freedesktop/systemd1/agent",
87 "org.freedesktop.systemd1.Agent",
91 return log_debug_errno(r
, "Failed to propagate agent release message: %m");
96 static int signal_agent_released(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
97 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
98 Manager
*m
= userdata
;
106 /* only accept org.freedesktop.systemd1.Agent from UID=0 */
107 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
111 r
= sd_bus_creds_get_euid(creds
, &sender_uid
);
112 if (r
< 0 || sender_uid
!= 0)
115 /* parse 'cgroup-empty' notification */
116 r
= sd_bus_message_read(message
, "s", &cgroup
);
118 bus_log_parse_error(r
);
122 manager_notify_cgroup_empty(m
, cgroup
);
126 static int signal_disconnected(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
127 Manager
*m
= userdata
;
132 assert_se(bus
= sd_bus_message_get_bus(message
));
134 if (bus
== m
->api_bus
)
136 if (bus
== m
->system_bus
)
139 if (set_remove(m
->private_buses
, bus
)) {
140 log_debug("Got disconnect on private connection.");
141 destroy_bus(m
, &bus
);
147 static int signal_activation_request(sd_bus_message
*message
, void *userdata
, sd_bus_error
*ret_error
) {
148 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
149 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
150 Manager
*m
= userdata
;
158 r
= sd_bus_message_read(message
, "s", &name
);
160 bus_log_parse_error(r
);
164 if (manager_unit_inactive_or_pending(m
, SPECIAL_DBUS_SERVICE
) ||
165 manager_unit_inactive_or_pending(m
, SPECIAL_DBUS_SOCKET
)) {
166 r
= sd_bus_error_setf(&error
, BUS_ERROR_SHUTTING_DOWN
, "Refusing activation, D-Bus is shutting down.");
170 r
= manager_load_unit(m
, name
, NULL
, &error
, &u
);
174 if (u
->refuse_manual_start
) {
175 r
= sd_bus_error_setf(&error
, BUS_ERROR_ONLY_BY_DEPENDENCY
, "Operation refused, %s may be requested by dependency only (it is configured to refuse manual start/stop).", u
->id
);
179 r
= manager_add_job(m
, JOB_START
, u
, JOB_REPLACE
, NULL
, &error
, NULL
);
183 /* Successfully queued, that's it for us */
187 if (!sd_bus_error_is_set(&error
))
188 sd_bus_error_set_errno(&error
, r
);
190 log_debug("D-Bus activation failed for %s: %s", name
, bus_error_message(&error
, r
));
192 r
= sd_bus_message_new_signal(sd_bus_message_get_bus(message
), &reply
, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
194 bus_log_create_error(r
);
198 r
= sd_bus_message_append(reply
, "sss", name
, error
.name
, error
.message
);
200 bus_log_create_error(r
);
204 r
= sd_bus_send_to(NULL
, reply
, "org.freedesktop.DBus", NULL
);
206 return log_error_errno(r
, "Failed to respond with to bus activation request: %m");
212 static int mac_selinux_filter(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
213 Manager
*m
= userdata
;
214 const char *verb
, *path
;
221 /* Our own method calls are all protected individually with
222 * selinux checks, but the built-in interfaces need to be
225 if (sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Properties", "Set"))
227 else if (sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Introspectable", NULL
) ||
228 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Properties", NULL
) ||
229 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.ObjectManager", NULL
) ||
230 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Peer", NULL
))
235 path
= sd_bus_message_get_path(message
);
237 if (object_path_startswith("/org/freedesktop/systemd1", path
)) {
238 r
= mac_selinux_access_check(message
, verb
, error
);
245 if (streq_ptr(path
, "/org/freedesktop/systemd1/unit/self")) {
246 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
249 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
253 r
= sd_bus_creds_get_pid(creds
, &pid
);
257 u
= manager_get_unit_by_pid(m
, pid
);
259 r
= manager_get_job_from_dbus_path(m
, path
, &j
);
263 manager_load_unit_from_dbus_path(m
, path
, NULL
, &u
);
268 r
= mac_selinux_unit_access_check(u
, message
, verb
, error
);
276 static int bus_job_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
277 Manager
*m
= userdata
;
287 r
= manager_get_job_from_dbus_path(m
, path
, &j
);
295 static int find_unit(Manager
*m
, sd_bus
*bus
, const char *path
, Unit
**unit
, sd_bus_error
*error
) {
296 Unit
*u
= NULL
; /* just to appease gcc, initialization is not really necessary */
303 if (streq_ptr(path
, "/org/freedesktop/systemd1/unit/self")) {
304 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
305 sd_bus_message
*message
;
308 message
= sd_bus_get_current_message(bus
);
312 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
316 r
= sd_bus_creds_get_pid(creds
, &pid
);
320 u
= manager_get_unit_by_pid(m
, pid
);
324 r
= manager_load_unit_from_dbus_path(m
, path
, error
, &u
);
334 static int bus_unit_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
335 Manager
*m
= userdata
;
343 return find_unit(m
, bus
, path
, (Unit
**) found
, error
);
346 static int bus_unit_interface_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
347 Manager
*m
= userdata
;
357 r
= find_unit(m
, bus
, path
, &u
, error
);
361 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
368 static int bus_unit_cgroup_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
369 Manager
*m
= userdata
;
379 r
= find_unit(m
, bus
, path
, &u
, error
);
383 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
386 if (!UNIT_HAS_CGROUP_CONTEXT(u
))
393 static int bus_cgroup_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
394 Manager
*m
= userdata
;
405 r
= find_unit(m
, bus
, path
, &u
, error
);
409 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
412 c
= unit_get_cgroup_context(u
);
420 static int bus_exec_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
421 Manager
*m
= userdata
;
432 r
= find_unit(m
, bus
, path
, &u
, error
);
436 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
439 c
= unit_get_exec_context(u
);
447 static int bus_kill_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
448 Manager
*m
= userdata
;
459 r
= find_unit(m
, bus
, path
, &u
, error
);
463 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
466 c
= unit_get_kill_context(u
);
474 static int bus_job_enumerate(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
475 _cleanup_strv_free_
char **l
= NULL
;
476 Manager
*m
= userdata
;
481 l
= new0(char*, hashmap_size(m
->jobs
)+1);
485 HASHMAP_FOREACH(j
, m
->jobs
, i
) {
486 l
[k
] = job_dbus_path(j
);
493 assert(hashmap_size(m
->jobs
) == k
);
495 *nodes
= TAKE_PTR(l
);
500 static int bus_unit_enumerate(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
501 _cleanup_strv_free_
char **l
= NULL
;
502 Manager
*m
= userdata
;
507 l
= new0(char*, hashmap_size(m
->units
)+1);
511 HASHMAP_FOREACH(u
, m
->units
, i
) {
512 l
[k
] = unit_dbus_path(u
);
519 *nodes
= TAKE_PTR(l
);
524 static int bus_setup_api_vtables(Manager
*m
, sd_bus
*bus
) {
532 r
= sd_bus_add_filter(bus
, NULL
, mac_selinux_filter
, m
);
534 return log_error_errno(r
, "Failed to add SELinux access filter: %m");
537 r
= sd_bus_add_object_vtable(bus
, NULL
, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable
, m
);
539 return log_error_errno(r
, "Failed to register Manager vtable: %m");
541 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable
, bus_job_find
, m
);
543 return log_error_errno(r
, "Failed to register Job vtable: %m");
545 r
= sd_bus_add_node_enumerator(bus
, NULL
, "/org/freedesktop/systemd1/job", bus_job_enumerate
, m
);
547 return log_error_errno(r
, "Failed to add job enumerator: %m");
549 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable
, bus_unit_find
, m
);
551 return log_error_errno(r
, "Failed to register Unit vtable: %m");
553 r
= sd_bus_add_node_enumerator(bus
, NULL
, "/org/freedesktop/systemd1/unit", bus_unit_enumerate
, m
);
555 return log_error_errno(r
, "Failed to add job enumerator: %m");
557 for (t
= 0; t
< _UNIT_TYPE_MAX
; t
++) {
558 const char *interface
;
560 assert_se(interface
= unit_dbus_interface_from_type(t
));
562 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, unit_vtable
[t
]->bus_vtable
, bus_unit_interface_find
, m
);
564 return log_error_errno(r
, "Failed to register type specific vtable for %s: %m", interface
);
566 if (unit_vtable
[t
]->cgroup_context_offset
> 0) {
567 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_unit_cgroup_vtable
, bus_unit_cgroup_find
, m
);
569 return log_error_errno(r
, "Failed to register control group unit vtable for %s: %m", interface
);
571 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_cgroup_vtable
, bus_cgroup_context_find
, m
);
573 return log_error_errno(r
, "Failed to register control group vtable for %s: %m", interface
);
576 if (unit_vtable
[t
]->exec_context_offset
> 0) {
577 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_exec_vtable
, bus_exec_context_find
, m
);
579 return log_error_errno(r
, "Failed to register execute vtable for %s: %m", interface
);
582 if (unit_vtable
[t
]->kill_context_offset
> 0) {
583 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_kill_vtable
, bus_kill_context_find
, m
);
585 return log_error_errno(r
, "Failed to register kill vtable for %s: %m", interface
);
592 static int bus_setup_disconnected_match(Manager
*m
, sd_bus
*bus
) {
598 r
= sd_bus_match_signal_async(
601 "org.freedesktop.DBus.Local",
602 "/org/freedesktop/DBus/Local",
603 "org.freedesktop.DBus.Local",
605 signal_disconnected
, NULL
, m
);
607 return log_error_errno(r
, "Failed to request match for Disconnected message: %m");
612 static int bus_on_connection(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
613 _cleanup_(sd_bus_close_unrefp
) sd_bus
*bus
= NULL
;
614 _cleanup_close_
int nfd
= -1;
615 Manager
*m
= userdata
;
622 nfd
= accept4(fd
, NULL
, NULL
, SOCK_NONBLOCK
|SOCK_CLOEXEC
);
624 if (ERRNO_IS_ACCEPT_AGAIN(errno
))
627 log_warning_errno(errno
, "Failed to accept private connection, ignoring: %m");
631 if (set_size(m
->private_buses
) >= CONNECTIONS_MAX
) {
632 log_warning("Too many concurrent connections, refusing");
636 r
= set_ensure_allocated(&m
->private_buses
, NULL
);
642 r
= sd_bus_new(&bus
);
644 log_warning_errno(r
, "Failed to allocate new private connection bus: %m");
648 (void) sd_bus_set_description(bus
, "private-bus-connection");
650 r
= sd_bus_set_fd(bus
, nfd
, nfd
);
652 log_warning_errno(r
, "Failed to set fd on new connection bus: %m");
658 r
= bus_check_peercred(bus
);
660 log_warning_errno(r
, "Incoming private connection from unprivileged client, refusing: %m");
664 assert_se(sd_id128_randomize(&id
) >= 0);
666 r
= sd_bus_set_server(bus
, 1, id
);
668 log_warning_errno(r
, "Failed to enable server support for new connection bus: %m");
672 r
= sd_bus_negotiate_creds(bus
, 1,
673 SD_BUS_CREDS_PID
|SD_BUS_CREDS_UID
|
674 SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EFFECTIVE_CAPS
|
675 SD_BUS_CREDS_SELINUX_CONTEXT
);
677 log_warning_errno(r
, "Failed to enable credentials for new connection: %m");
681 r
= sd_bus_set_sender(bus
, "org.freedesktop.systemd1");
683 log_warning_errno(r
, "Failed to set direct connection sender: %m");
687 r
= sd_bus_start(bus
);
689 log_warning_errno(r
, "Failed to start new connection bus: %m");
693 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
695 log_warning_errno(r
, "Failed to attach new connection bus to event loop: %m");
699 r
= bus_setup_disconnected_match(m
, bus
);
703 r
= bus_setup_api_vtables(m
, bus
);
705 log_warning_errno(r
, "Failed to set up API vtables on new connection bus: %m");
709 r
= set_put(m
->private_buses
, bus
);
711 log_warning_errno(r
, "Failed to add new connection bus to set: %m");
717 log_debug("Accepted new private connection.");
722 static int bus_setup_api(Manager
*m
, sd_bus
*bus
) {
731 /* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
732 r
= sd_bus_negotiate_creds(bus
, 1,
733 SD_BUS_CREDS_PID
|SD_BUS_CREDS_UID
|
734 SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EFFECTIVE_CAPS
|
735 SD_BUS_CREDS_SELINUX_CONTEXT
);
737 log_warning_errno(r
, "Failed to enable credential passing, ignoring: %m");
739 r
= bus_setup_api_vtables(m
, bus
);
743 HASHMAP_FOREACH_KEY(u
, name
, m
->watch_bus
, i
) {
744 r
= unit_install_bus_match(u
, bus
, name
);
746 log_error_errno(r
, "Failed to subscribe to NameOwnerChanged signal for '%s': %m", name
);
749 r
= sd_bus_match_signal_async(
752 "org.freedesktop.DBus",
753 "/org/freedesktop/DBus",
754 "org.freedesktop.systemd1.Activator",
756 signal_activation_request
, NULL
, m
);
758 log_warning_errno(r
, "Failed to subscribe to activation signal: %m");
760 /* Allow replacing of our name, to ease implementation of reexecution, where we keep the old connection open
761 * until after the new connection is set up and the name installed to allow clients to synchronously wait for
762 * reexecution to finish */
763 r
= sd_bus_request_name_async(bus
, NULL
, "org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING
|SD_BUS_NAME_ALLOW_REPLACEMENT
, NULL
, NULL
);
765 return log_error_errno(r
, "Failed to request name: %m");
767 log_debug("Successfully connected to API bus.");
772 int bus_init_api(Manager
*m
) {
773 _cleanup_(sd_bus_close_unrefp
) sd_bus
*bus
= NULL
;
779 /* The API and system bus is the same if we are running in system mode */
780 if (MANAGER_IS_SYSTEM(m
) && m
->system_bus
)
781 bus
= sd_bus_ref(m
->system_bus
);
783 if (MANAGER_IS_SYSTEM(m
))
784 r
= sd_bus_open_system_with_description(&bus
, "bus-api-system");
786 r
= sd_bus_open_user_with_description(&bus
, "bus-api-user");
788 return log_error_errno(r
, "Failed to connect to API bus: %m");
790 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
792 return log_error_errno(r
, "Failed to attach API bus to event loop: %m");
794 r
= bus_setup_disconnected_match(m
, bus
);
799 r
= bus_setup_api(m
, bus
);
801 return log_error_errno(r
, "Failed to set up API bus: %m");
803 m
->api_bus
= TAKE_PTR(bus
);
808 static int bus_setup_system(Manager
*m
, sd_bus
*bus
) {
814 /* if we are a user instance we get the Released message via the system bus */
815 if (MANAGER_IS_USER(m
)) {
816 r
= sd_bus_match_signal_async(
820 "/org/freedesktop/systemd1/agent",
821 "org.freedesktop.systemd1.Agent",
823 signal_agent_released
, NULL
, m
);
825 log_warning_errno(r
, "Failed to request Released match on system bus: %m");
828 log_debug("Successfully connected to system bus.");
832 int bus_init_system(Manager
*m
) {
833 _cleanup_(sd_bus_close_unrefp
) sd_bus
*bus
= NULL
;
839 /* The API and system bus is the same if we are running in system mode */
840 if (MANAGER_IS_SYSTEM(m
) && m
->api_bus
)
841 bus
= sd_bus_ref(m
->api_bus
);
843 r
= sd_bus_open_system_with_description(&bus
, "bus-system");
845 return log_error_errno(r
, "Failed to connect to system bus: %m");
847 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
849 return log_error_errno(r
, "Failed to attach system bus to event loop: %m");
851 r
= bus_setup_disconnected_match(m
, bus
);
856 r
= bus_setup_system(m
, bus
);
858 return log_error_errno(r
, "Failed to set up system bus: %m");
860 m
->system_bus
= TAKE_PTR(bus
);
865 int bus_init_private(Manager
*m
) {
866 _cleanup_close_
int fd
= -1;
867 union sockaddr_union sa
= {};
873 if (m
->private_listen_fd
>= 0)
876 if (MANAGER_IS_SYSTEM(m
)) {
878 /* We want the private bus only when running as init */
879 if (getpid_cached() != 1)
882 salen
= sockaddr_un_set_path(&sa
.un
, "/run/systemd/private");
884 const char *e
, *joined
;
886 e
= secure_getenv("XDG_RUNTIME_DIR");
888 return log_error_errno(SYNTHETIC_ERRNO(EHOSTDOWN
),
889 "XDG_RUNTIME_DIR is not set, refusing.");
891 joined
= strjoina(e
, "/systemd/private");
892 salen
= sockaddr_un_set_path(&sa
.un
, joined
);
895 return log_error_errno(salen
, "Can't set path for AF_UNIX socket to bind to: %m");
897 (void) mkdir_parents_label(sa
.un
.sun_path
, 0755);
898 (void) sockaddr_un_unlink(&sa
.un
);
900 fd
= socket(AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0);
902 return log_error_errno(errno
, "Failed to allocate private socket: %m");
904 r
= bind(fd
, &sa
.sa
, salen
);
906 return log_error_errno(errno
, "Failed to bind private socket: %m");
908 r
= listen(fd
, SOMAXCONN
);
910 return log_error_errno(errno
, "Failed to make private socket listening: %m");
912 /* Generate an inotify event in case somebody waits for this socket to appear using inotify() */
913 (void) touch(sa
.un
.sun_path
);
915 r
= sd_event_add_io(m
->event
, &s
, fd
, EPOLLIN
, bus_on_connection
, m
);
917 return log_error_errno(r
, "Failed to allocate event source: %m");
919 (void) sd_event_source_set_description(s
, "bus-connection");
921 m
->private_listen_fd
= TAKE_FD(fd
);
922 m
->private_listen_event_source
= s
;
924 log_debug("Successfully created private D-Bus server.");
929 static void destroy_bus(Manager
*m
, sd_bus
**bus
) {
940 /* Make sure all bus slots watching names are released. */
941 HASHMAP_FOREACH(u
, m
->watch_bus
, i
) {
942 if (u
->match_bus_slot
&& sd_bus_slot_get_bus(u
->match_bus_slot
) == *bus
)
943 u
->match_bus_slot
= sd_bus_slot_unref(u
->match_bus_slot
);
944 if (u
->get_name_owner_slot
&& sd_bus_slot_get_bus(u
->get_name_owner_slot
) == *bus
)
945 u
->get_name_owner_slot
= sd_bus_slot_unref(u
->get_name_owner_slot
);
948 /* Get rid of tracked clients on this bus */
949 if (m
->subscribed
&& sd_bus_track_get_bus(m
->subscribed
) == *bus
)
950 m
->subscribed
= sd_bus_track_unref(m
->subscribed
);
952 HASHMAP_FOREACH(j
, m
->jobs
, i
)
953 if (j
->bus_track
&& sd_bus_track_get_bus(j
->bus_track
) == *bus
)
954 j
->bus_track
= sd_bus_track_unref(j
->bus_track
);
956 HASHMAP_FOREACH(u
, m
->units
, i
)
957 if (u
->bus_track
&& sd_bus_track_get_bus(u
->bus_track
) == *bus
)
958 u
->bus_track
= sd_bus_track_unref(u
->bus_track
);
960 /* Get rid of queued message on this bus */
961 if (m
->pending_reload_message
&& sd_bus_message_get_bus(m
->pending_reload_message
) == *bus
)
962 m
->pending_reload_message
= sd_bus_message_unref(m
->pending_reload_message
);
964 /* Possibly flush unwritten data, but only if we are
965 * unprivileged, since we don't want to sync here */
966 if (!MANAGER_IS_SYSTEM(m
))
969 /* And destroy the object */
970 *bus
= sd_bus_close_unref(*bus
);
973 void bus_done_api(Manager
*m
) {
974 destroy_bus(m
, &m
->api_bus
);
977 void bus_done_system(Manager
*m
) {
978 destroy_bus(m
, &m
->system_bus
);
981 void bus_done_private(Manager
*m
) {
986 while ((b
= set_steal_first(m
->private_buses
)))
989 m
->private_buses
= set_free(m
->private_buses
);
991 m
->private_listen_event_source
= sd_event_source_unref(m
->private_listen_event_source
);
992 m
->private_listen_fd
= safe_close(m
->private_listen_fd
);
995 void bus_done(Manager
*m
) {
1000 bus_done_private(m
);
1002 assert(!m
->subscribed
);
1004 m
->deserialized_subscribed
= strv_free(m
->deserialized_subscribed
);
1005 bus_verify_polkit_async_registry_free(m
->polkit_registry
);
1008 int bus_fdset_add_all(Manager
*m
, FDSet
*fds
) {
1016 /* When we are about to reexecute we add all D-Bus fds to the
1017 * set to pass over to the newly executed systemd. They won't
1018 * be used there however, except thatt they are closed at the
1019 * very end of deserialization, those making it possible for
1020 * clients to synchronously wait for systemd to reexec by
1021 * simply waiting for disconnection */
1024 fd
= sd_bus_get_fd(m
->api_bus
);
1026 fd
= fdset_put_dup(fds
, fd
);
1032 SET_FOREACH(b
, m
->private_buses
, i
) {
1033 fd
= sd_bus_get_fd(b
);
1035 fd
= fdset_put_dup(fds
, fd
);
1041 /* We don't offer any APIs on the system bus (well, unless it
1042 * is the same as the API bus) hence we don't bother with it
1048 int bus_foreach_bus(
1050 sd_bus_track
*subscribed2
,
1051 int (*send_message
)(sd_bus
*bus
, void *userdata
),
1058 /* Send to all direct buses, unconditionally */
1059 SET_FOREACH(b
, m
->private_buses
, i
) {
1061 /* Don't bother with enqueing these messages to clients that haven't started yet */
1062 if (sd_bus_is_ready(b
) <= 0)
1065 r
= send_message(b
, userdata
);
1070 /* Send to API bus, but only if somebody is subscribed */
1072 (sd_bus_track_count(m
->subscribed
) > 0 ||
1073 sd_bus_track_count(subscribed2
) > 0)) {
1074 r
= send_message(m
->api_bus
, userdata
);
1082 void bus_track_serialize(sd_bus_track
*t
, FILE *f
, const char *prefix
) {
1088 for (n
= sd_bus_track_first(t
); n
; n
= sd_bus_track_next(t
)) {
1091 c
= sd_bus_track_count_name(t
, n
);
1092 for (j
= 0; j
< c
; j
++)
1093 (void) serialize_item(f
, prefix
, n
);
1097 int bus_track_coldplug(Manager
*m
, sd_bus_track
**t
, bool recursive
, char **l
) {
1103 if (strv_isempty(l
))
1110 r
= sd_bus_track_new(m
->api_bus
, t
, NULL
, NULL
);
1115 r
= sd_bus_track_set_recursive(*t
, recursive
);
1119 return bus_track_add_name_many(*t
, l
);
1122 int bus_verify_manage_units_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1123 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.manage-units", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1126 int bus_verify_manage_unit_files_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1127 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.manage-unit-files", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1130 int bus_verify_reload_daemon_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1131 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.reload-daemon", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1134 int bus_verify_set_environment_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1135 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.set-environment", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1138 uint64_t manager_bus_n_queued_write(Manager
*m
) {
1144 /* Returns the total number of messages queued for writing on all our direct and API buses. */
1146 SET_FOREACH(b
, m
->private_buses
, i
) {
1149 r
= sd_bus_get_n_queued_write(b
, &k
);
1151 log_debug_errno(r
, "Failed to query queued messages for private bus: %m");
1159 r
= sd_bus_get_n_queued_write(m
->api_bus
, &k
);
1161 log_debug_errno(r
, "Failed to query queued messages for API bus: %m");
1169 static void vtable_dump_bus_properties(FILE *f
, const sd_bus_vtable
*table
) {
1170 const sd_bus_vtable
*i
;
1172 for (i
= table
; i
->type
!= _SD_BUS_VTABLE_END
; i
++) {
1173 if (!IN_SET(i
->type
, _SD_BUS_VTABLE_PROPERTY
, _SD_BUS_VTABLE_WRITABLE_PROPERTY
) ||
1174 (i
->flags
& (SD_BUS_VTABLE_DEPRECATED
| SD_BUS_VTABLE_HIDDEN
)) != 0)
1177 fprintf(f
, "%s\n", i
->x
.property
.member
);
1181 void dump_bus_properties(FILE *f
) {
1184 vtable_dump_bus_properties(f
, bus_automount_vtable
);
1185 vtable_dump_bus_properties(f
, bus_cgroup_vtable
);
1186 vtable_dump_bus_properties(f
, bus_device_vtable
);
1187 vtable_dump_bus_properties(f
, bus_exec_vtable
);
1188 vtable_dump_bus_properties(f
, bus_job_vtable
);
1189 vtable_dump_bus_properties(f
, bus_kill_vtable
);
1190 vtable_dump_bus_properties(f
, bus_manager_vtable
);
1191 vtable_dump_bus_properties(f
, bus_mount_vtable
);
1192 vtable_dump_bus_properties(f
, bus_path_vtable
);
1193 vtable_dump_bus_properties(f
, bus_scope_vtable
);
1194 vtable_dump_bus_properties(f
, bus_service_vtable
);
1195 vtable_dump_bus_properties(f
, bus_slice_vtable
);
1196 vtable_dump_bus_properties(f
, bus_socket_vtable
);
1197 vtable_dump_bus_properties(f
, bus_swap_vtable
);
1198 vtable_dump_bus_properties(f
, bus_target_vtable
);
1199 vtable_dump_bus_properties(f
, bus_timer_vtable
);
1200 vtable_dump_bus_properties(f
, bus_unit_vtable
);
1201 vtable_dump_bus_properties(f
, bus_unit_cgroup_vtable
);