1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
8 #include "alloc-util.h"
9 #include "bus-common-errors.h"
10 #include "bus-error.h"
11 #include "bus-internal.h"
12 #include "bus-object.h"
15 #include "dbus-automount.h"
16 #include "dbus-cgroup.h"
17 #include "dbus-device.h"
18 #include "dbus-execute.h"
20 #include "dbus-kill.h"
21 #include "dbus-manager.h"
22 #include "dbus-mount.h"
23 #include "dbus-path.h"
24 #include "dbus-scope.h"
25 #include "dbus-service.h"
26 #include "dbus-slice.h"
27 #include "dbus-socket.h"
28 #include "dbus-swap.h"
29 #include "dbus-target.h"
30 #include "dbus-timer.h"
31 #include "dbus-unit.h"
32 #include "errno-util.h"
35 #include "format-util.h"
39 #include "path-util.h"
41 #include "process-util.h"
42 #include "selinux-access.h"
43 #include "serialize.h"
46 #include "string-util.h"
48 #include "umask-util.h"
50 #define CONNECTIONS_MAX 4096
52 static void destroy_bus(Manager
*m
, sd_bus
**bus
);
54 void bus_send_pending_reload_message(Manager
*m
) {
59 if (!m
->pending_reload_message
)
62 /* If we cannot get rid of this message we won't dispatch any D-Bus messages, so that we won't end up wanting
63 * to queue another message. */
65 r
= sd_bus_message_send(m
->pending_reload_message
);
67 log_warning_errno(r
, "Failed to send queued reload message, ignoring: %m");
69 m
->pending_reload_message
= sd_bus_message_unref(m
->pending_reload_message
);
74 static int signal_disconnected(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
75 Manager
*m
= ASSERT_PTR(userdata
);
79 assert_se(bus
= sd_bus_message_get_bus(message
));
81 if (bus
== m
->api_bus
) {
82 log_notice("Got disconnect on API bus.");
85 if (bus
== m
->system_bus
) {
86 /* If we are the system manager, this is already logged by the API bus. */
87 if (!MANAGER_IS_SYSTEM(m
))
88 log_notice("Got disconnect on system bus.");
92 if (set_remove(m
->private_buses
, bus
)) {
93 log_debug("Got disconnect on private connection.");
100 static int signal_activation_request(sd_bus_message
*message
, void *userdata
, sd_bus_error
*ret_error
) {
101 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
102 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
103 Manager
*m
= ASSERT_PTR(userdata
);
110 r
= sd_bus_message_read(message
, "s", &name
);
112 bus_log_parse_error(r
);
116 if (manager_unit_inactive_or_pending(m
, SPECIAL_DBUS_SOCKET
) ||
117 manager_unit_inactive_or_pending(m
, SPECIAL_DBUS_SERVICE
)) {
118 r
= sd_bus_error_set(&error
, BUS_ERROR_SHUTTING_DOWN
, "Refusing activation, D-Bus is shutting down.");
122 r
= manager_load_unit(m
, name
, NULL
, &error
, &u
);
126 if (u
->refuse_manual_start
) {
127 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
);
131 r
= manager_add_job(m
, JOB_START
, u
, JOB_REPLACE
, &error
, /* ret = */ NULL
);
135 /* Successfully queued, that's it for us */
139 if (!sd_bus_error_is_set(&error
))
140 sd_bus_error_set_errno(&error
, r
);
142 log_debug("D-Bus activation failed for %s: %s", name
, bus_error_message(&error
, r
));
144 r
= sd_bus_message_new_signal(sd_bus_message_get_bus(message
), &reply
, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
146 bus_log_create_error(r
);
150 r
= sd_bus_message_append(reply
, "sss", name
, error
.name
, error
.message
);
152 bus_log_create_error(r
);
156 r
= sd_bus_send_to(NULL
, reply
, "org.freedesktop.DBus", NULL
);
158 return log_error_errno(r
, "Failed to respond with to bus activation request: %m");
164 static int mac_selinux_filter(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
165 Manager
*m
= userdata
;
166 const char *verb
, *path
;
173 /* Our own method calls are all protected individually with
174 * selinux checks, but the built-in interfaces need to be
177 if (sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Properties", "Set"))
179 else if (sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Introspectable", NULL
) ||
180 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Properties", NULL
) ||
181 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.ObjectManager", NULL
) ||
182 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Peer", NULL
))
187 path
= sd_bus_message_get_path(message
);
191 if (object_path_startswith("/org/freedesktop/systemd1", path
)) {
192 r
= mac_selinux_access_check(message
, verb
, error
);
199 if (streq(path
, "/org/freedesktop/systemd1/unit/self")) {
200 _cleanup_(pidref_done
) PidRef pidref
= PIDREF_NULL
;
202 r
= bus_query_sender_pidref(message
, &pidref
);
206 u
= manager_get_unit_by_pidref(m
, &pidref
);
208 r
= manager_get_job_from_dbus_path(m
, path
, &j
);
212 (void) manager_load_unit_from_dbus_path(m
, path
, NULL
, &u
);
217 r
= mac_selinux_unit_access_check(u
, message
, verb
, error
);
225 static int find_unit(Manager
*m
, sd_bus
*bus
, const char *path
, Unit
**unit
, sd_bus_error
*error
) {
226 Unit
*u
= NULL
; /* just to appease gcc, initialization is not really necessary */
233 if (streq(path
, "/org/freedesktop/systemd1/unit/self")) {
234 _cleanup_(pidref_done
) PidRef pidref
= PIDREF_NULL
;
235 sd_bus_message
*message
;
237 message
= sd_bus_get_current_message(bus
);
241 r
= bus_query_sender_pidref(message
, &pidref
);
245 u
= manager_get_unit_by_pidref(m
, &pidref
);
249 r
= manager_load_unit_from_dbus_path(m
, path
, error
, &u
);
259 static int bus_unit_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
260 Manager
*m
= ASSERT_PTR(userdata
);
267 return find_unit(m
, bus
, path
, (Unit
**) found
, error
);
270 static int bus_unit_interface_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
271 Manager
*m
= ASSERT_PTR(userdata
);
280 r
= find_unit(m
, bus
, path
, &u
, error
);
284 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
291 static int bus_unit_cgroup_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
292 Manager
*m
= ASSERT_PTR(userdata
);
301 r
= find_unit(m
, bus
, path
, &u
, error
);
305 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
308 if (!UNIT_HAS_CGROUP_CONTEXT(u
))
315 static int bus_cgroup_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
316 Manager
*m
= ASSERT_PTR(userdata
);
326 r
= find_unit(m
, bus
, path
, &u
, error
);
330 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
333 c
= unit_get_cgroup_context(u
);
341 static int bus_exec_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
342 Manager
*m
= ASSERT_PTR(userdata
);
352 r
= find_unit(m
, bus
, path
, &u
, error
);
356 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
359 c
= unit_get_exec_context(u
);
367 static int bus_kill_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
368 Manager
*m
= ASSERT_PTR(userdata
);
378 r
= find_unit(m
, bus
, path
, &u
, error
);
382 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
385 c
= unit_get_kill_context(u
);
393 static int bus_unit_enumerate(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
394 _cleanup_strv_free_
char **l
= NULL
;
395 Manager
*m
= userdata
;
399 l
= new0(char*, hashmap_size(m
->units
)+1);
403 HASHMAP_FOREACH(u
, m
->units
) {
404 l
[k
] = unit_dbus_path(u
);
411 *nodes
= TAKE_PTR(l
);
416 static const BusObjectImplementation unit_object
= {
417 "/org/freedesktop/systemd1/unit",
418 "org.freedesktop.systemd1.Unit",
419 .fallback_vtables
= BUS_FALLBACK_VTABLES(
420 { bus_unit_vtable
, bus_unit_find
}),
421 .node_enumerator
= bus_unit_enumerate
,
424 static const BusObjectImplementation bus_automount_object
= {
425 "/org/freedesktop/systemd1/unit",
426 "org.freedesktop.systemd1.Automount",
427 .fallback_vtables
= BUS_FALLBACK_VTABLES(
428 { bus_automount_vtable
, bus_unit_interface_find
}),
431 static const BusObjectImplementation bus_device_object
= {
432 "/org/freedesktop/systemd1/unit",
433 "org.freedesktop.systemd1.Device",
434 .fallback_vtables
= BUS_FALLBACK_VTABLES(
435 { bus_device_vtable
, bus_unit_interface_find
}),
438 static const BusObjectImplementation bus_mount_object
= {
439 "/org/freedesktop/systemd1/unit",
440 "org.freedesktop.systemd1.Mount",
441 .fallback_vtables
= BUS_FALLBACK_VTABLES(
442 { bus_mount_vtable
, bus_unit_interface_find
},
443 { bus_unit_cgroup_vtable
, bus_unit_cgroup_find
},
444 { bus_cgroup_vtable
, bus_cgroup_context_find
},
445 { bus_exec_vtable
, bus_exec_context_find
},
446 { bus_kill_vtable
, bus_kill_context_find
}),
449 static const BusObjectImplementation bus_path_object
= {
450 "/org/freedesktop/systemd1/unit",
451 "org.freedesktop.systemd1.Path",
452 .fallback_vtables
= BUS_FALLBACK_VTABLES(
453 { bus_path_vtable
, bus_unit_interface_find
}),
456 static const BusObjectImplementation bus_scope_object
= {
457 "/org/freedesktop/systemd1/unit",
458 "org.freedesktop.systemd1.Scope",
459 .fallback_vtables
= BUS_FALLBACK_VTABLES(
460 { bus_scope_vtable
, bus_unit_interface_find
},
461 { bus_unit_cgroup_vtable
, bus_unit_cgroup_find
},
462 { bus_cgroup_vtable
, bus_cgroup_context_find
},
463 { bus_kill_vtable
, bus_kill_context_find
}),
466 static const BusObjectImplementation bus_service_object
= {
467 "/org/freedesktop/systemd1/unit",
468 "org.freedesktop.systemd1.Service",
469 .fallback_vtables
= BUS_FALLBACK_VTABLES(
470 { bus_service_vtable
, bus_unit_interface_find
},
471 { bus_unit_cgroup_vtable
, bus_unit_cgroup_find
},
472 { bus_cgroup_vtable
, bus_cgroup_context_find
},
473 { bus_exec_vtable
, bus_exec_context_find
},
474 { bus_kill_vtable
, bus_kill_context_find
}),
477 static const BusObjectImplementation bus_slice_object
= {
478 "/org/freedesktop/systemd1/unit",
479 "org.freedesktop.systemd1.Slice",
480 .fallback_vtables
= BUS_FALLBACK_VTABLES(
481 { bus_slice_vtable
, bus_unit_interface_find
},
482 { bus_unit_cgroup_vtable
, bus_unit_cgroup_find
},
483 { bus_cgroup_vtable
, bus_cgroup_context_find
}),
486 static const BusObjectImplementation bus_socket_object
= {
487 "/org/freedesktop/systemd1/unit",
488 "org.freedesktop.systemd1.Socket",
489 .fallback_vtables
= BUS_FALLBACK_VTABLES(
490 { bus_socket_vtable
, bus_unit_interface_find
},
491 { bus_unit_cgroup_vtable
, bus_unit_cgroup_find
},
492 { bus_cgroup_vtable
, bus_cgroup_context_find
},
493 { bus_exec_vtable
, bus_exec_context_find
},
494 { bus_kill_vtable
, bus_kill_context_find
}),
497 static const BusObjectImplementation bus_swap_object
= {
498 "/org/freedesktop/systemd1/unit",
499 "org.freedesktop.systemd1.Swap",
500 .fallback_vtables
= BUS_FALLBACK_VTABLES(
501 { bus_swap_vtable
, bus_unit_interface_find
},
502 { bus_unit_cgroup_vtable
, bus_unit_cgroup_find
},
503 { bus_cgroup_vtable
, bus_cgroup_context_find
},
504 { bus_exec_vtable
, bus_exec_context_find
},
505 { bus_kill_vtable
, bus_kill_context_find
}),
508 static const BusObjectImplementation bus_target_object
= {
509 "/org/freedesktop/systemd1/unit",
510 "org.freedesktop.systemd1.Target",
511 .fallback_vtables
= BUS_FALLBACK_VTABLES(
512 { bus_target_vtable
, bus_unit_interface_find
}),
515 static const BusObjectImplementation bus_timer_object
= {
516 "/org/freedesktop/systemd1/unit",
517 "org.freedesktop.systemd1.Timer",
518 .fallback_vtables
= BUS_FALLBACK_VTABLES(
519 { bus_timer_vtable
, bus_unit_interface_find
}),
522 static const BusObjectImplementation bus_manager_object
= {
523 "/org/freedesktop/systemd1",
524 "org.freedesktop.systemd1.Manager",
525 .vtables
= BUS_VTABLES(bus_manager_vtable
),
526 .children
= BUS_IMPLEMENTATIONS(
529 &bus_automount_object
,
542 static const BusObjectImplementation manager_log_control_object
= {
543 "/org/freedesktop/LogControl1",
544 "org.freedesktop.LogControl1",
545 .vtables
= BUS_VTABLES(bus_manager_log_control_vtable
),
548 int bus_manager_introspect_implementations(FILE *out
, const char *pattern
) {
549 return bus_introspect_implementations(
552 BUS_IMPLEMENTATIONS(&bus_manager_object
,
553 &manager_log_control_object
));
556 static int bus_setup_api_vtables(Manager
*m
, sd_bus
*bus
) {
563 r
= sd_bus_add_filter(bus
, NULL
, mac_selinux_filter
, m
);
565 return log_error_errno(r
, "Failed to add SELinux access filter: %m");
568 r
= bus_add_implementation(bus
, &bus_manager_object
, m
);
572 return bus_add_implementation(bus
, &manager_log_control_object
, m
);
575 static int bus_setup_disconnected_match(Manager
*m
, sd_bus
*bus
) {
581 r
= sd_bus_match_signal_async(
584 "org.freedesktop.DBus.Local",
585 "/org/freedesktop/DBus/Local",
586 "org.freedesktop.DBus.Local",
588 signal_disconnected
, NULL
, m
);
590 return log_error_errno(r
, "Failed to request match for Disconnected message: %m");
595 static int bus_on_connection(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
596 _cleanup_(sd_bus_close_unrefp
) sd_bus
*bus
= NULL
;
597 _cleanup_close_
int nfd
= -EBADF
;
598 Manager
*m
= ASSERT_PTR(userdata
);
604 nfd
= accept4(fd
, NULL
, NULL
, SOCK_NONBLOCK
|SOCK_CLOEXEC
);
606 if (ERRNO_IS_ACCEPT_AGAIN(errno
))
609 log_warning_errno(errno
, "Failed to accept private connection, ignoring: %m");
613 if (set_size(m
->private_buses
) >= CONNECTIONS_MAX
) {
614 log_warning("Too many concurrent connections, refusing");
618 r
= sd_bus_new(&bus
);
620 log_warning_errno(r
, "Failed to allocate new private connection bus: %m");
624 (void) sd_bus_set_description(bus
, "private-bus-connection");
626 r
= sd_bus_set_fd(bus
, nfd
, nfd
);
628 log_warning_errno(r
, "Failed to set fd on new connection bus: %m");
634 r
= bus_check_peercred(bus
);
636 log_warning_errno(r
, "Incoming private connection from unprivileged client, refusing: %m");
640 assert_se(sd_id128_randomize(&id
) >= 0);
642 r
= sd_bus_set_server(bus
, 1, id
);
644 log_warning_errno(r
, "Failed to enable server support for new connection bus: %m");
648 r
= sd_bus_negotiate_creds(bus
, 1,
649 SD_BUS_CREDS_PID
|SD_BUS_CREDS_UID
|
650 SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EFFECTIVE_CAPS
|
651 SD_BUS_CREDS_SELINUX_CONTEXT
|
652 SD_BUS_CREDS_COMM
|SD_BUS_CREDS_DESCRIPTION
);
654 log_warning_errno(r
, "Failed to enable credentials for new connection: %m");
658 r
= sd_bus_set_sender(bus
, "org.freedesktop.systemd1");
660 log_warning_errno(r
, "Failed to set direct connection sender: %m");
664 r
= sd_bus_start(bus
);
666 log_warning_errno(r
, "Failed to start new connection bus: %m");
671 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*c
= NULL
;
672 const char *comm
= NULL
, *description
= NULL
;
675 r
= sd_bus_get_owner_creds(bus
, SD_BUS_CREDS_PID
|SD_BUS_CREDS_COMM
|SD_BUS_CREDS_DESCRIPTION
, &c
);
677 log_warning_errno(r
, "Failed to get peer creds, ignoring: %m");
679 (void) sd_bus_creds_get_pid(c
, &pid
);
680 (void) sd_bus_creds_get_comm(c
, &comm
);
681 (void) sd_bus_creds_get_description(c
, &description
);
684 log_debug("Accepting direct incoming connection from " PID_FMT
" (%s) [%s]", pid
, strna(comm
), strna(description
));
687 r
= sd_bus_attach_event(bus
, m
->event
, EVENT_PRIORITY_IPC
);
689 log_warning_errno(r
, "Failed to attach new connection bus to event loop: %m");
693 r
= bus_setup_disconnected_match(m
, bus
);
697 r
= bus_setup_api_vtables(m
, bus
);
699 log_warning_errno(r
, "Failed to set up API vtables on new connection bus: %m");
703 r
= bus_register_malloc_status(bus
, "org.freedesktop.systemd1");
705 log_warning_errno(r
, "Failed to register MemoryAllocation1, ignoring: %m");
707 r
= set_ensure_put(&m
->private_buses
, NULL
, bus
);
713 log_warning_errno(r
, "Failed to add new connection bus to set: %m");
719 log_debug("Accepted new private connection.");
724 static int bus_track_coldplug(sd_bus
*bus
, sd_bus_track
**t
, char * const *l
) {
734 r
= sd_bus_track_new(bus
, t
, NULL
, NULL
);
739 return bus_track_add_name_many(*t
, l
);
742 static int bus_setup_api(Manager
*m
, sd_bus
*bus
) {
750 /* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
751 r
= sd_bus_negotiate_creds(bus
, 1,
752 SD_BUS_CREDS_PID
|SD_BUS_CREDS_UID
|
753 SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EFFECTIVE_CAPS
|
754 SD_BUS_CREDS_SELINUX_CONTEXT
);
756 log_warning_errno(r
, "Failed to enable credential passing, ignoring: %m");
758 r
= bus_setup_api_vtables(m
, bus
);
762 HASHMAP_FOREACH_KEY(u
, name
, m
->watch_bus
) {
763 r
= unit_install_bus_match(u
, bus
, name
);
765 log_error_errno(r
, "Failed to subscribe to NameOwnerChanged signal for '%s': %m", name
);
768 r
= sd_bus_match_signal_async(
771 "org.freedesktop.DBus",
772 "/org/freedesktop/DBus",
773 "org.freedesktop.systemd1.Activator",
775 signal_activation_request
, NULL
, m
);
777 log_warning_errno(r
, "Failed to subscribe to activation signal: %m");
779 /* Allow replacing of our name, to ease implementation of reexecution, where we keep the old connection open
780 * until after the new connection is set up and the name installed to allow clients to synchronously wait for
781 * reexecution to finish */
782 r
= sd_bus_request_name_async(bus
, NULL
, "org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING
|SD_BUS_NAME_ALLOW_REPLACEMENT
, NULL
, NULL
);
784 return log_error_errno(r
, "Failed to request name: %m");
786 r
= bus_register_malloc_status(bus
, "org.freedesktop.systemd1");
788 log_warning_errno(r
, "Failed to register MemoryAllocation1, ignoring: %m");
790 log_debug("Successfully connected to API bus.");
795 int bus_init_api(Manager
*m
) {
796 _cleanup_(sd_bus_close_unrefp
) sd_bus
*bus
= NULL
;
804 /* The API and system bus is the same if we are running in system mode */
805 if (MANAGER_IS_SYSTEM(m
) && m
->system_bus
)
806 bus
= sd_bus_ref(m
->system_bus
);
808 if (MANAGER_IS_SYSTEM(m
))
809 r
= sd_bus_open_system_with_description(&bus
, "bus-api-system");
811 r
= sd_bus_open_user_with_description(&bus
, "bus-api-user");
813 return log_error_errno(r
, "Failed to connect to API bus: %m");
815 r
= sd_bus_attach_event(bus
, m
->event
, EVENT_PRIORITY_IPC
);
817 return log_error_errno(r
, "Failed to attach API bus to event loop: %m");
819 r
= bus_setup_disconnected_match(m
, bus
);
824 r
= bus_setup_api(m
, bus
);
826 return log_error_errno(r
, "Failed to set up API bus: %m");
828 r
= bus_get_instance_id(bus
, &m
->bus_id
);
830 log_warning_errno(r
, "Failed to query API bus instance ID, not deserializing subscriptions: %m");
831 else if (sd_id128_is_null(m
->deserialized_bus_id
) || sd_id128_equal(m
->bus_id
, m
->deserialized_bus_id
))
832 (void) bus_track_coldplug(bus
, &m
->subscribed
, m
->subscribed_as_strv
);
833 m
->subscribed_as_strv
= strv_free(m
->subscribed_as_strv
);
834 m
->deserialized_bus_id
= SD_ID128_NULL
;
836 m
->api_bus
= TAKE_PTR(bus
);
840 int bus_init_system(Manager
*m
) {
841 _cleanup_(sd_bus_close_unrefp
) sd_bus
*bus
= NULL
;
847 /* The API and system bus is the same if we are running in system mode */
848 if (MANAGER_IS_SYSTEM(m
) && m
->api_bus
)
849 bus
= sd_bus_ref(m
->api_bus
);
851 r
= sd_bus_open_system_with_description(&bus
, "bus-system");
853 return log_error_errno(r
, "Failed to connect to system bus: %m");
855 r
= sd_bus_attach_event(bus
, m
->event
, EVENT_PRIORITY_IPC
);
857 return log_error_errno(r
, "Failed to attach system bus to event loop: %m");
859 r
= bus_setup_disconnected_match(m
, bus
);
864 m
->system_bus
= TAKE_PTR(bus
);
866 log_debug("Successfully connected to system bus.");
871 int bus_init_private(Manager
*m
) {
872 _cleanup_close_
int fd
= -EBADF
;
873 union sockaddr_union sa
;
880 if (m
->private_listen_fd
>= 0)
883 if (MANAGER_IS_SYSTEM(m
)) {
885 /* We want the private bus only when running as init */
886 if (getpid_cached() != 1)
889 r
= sockaddr_un_set_path(&sa
.un
, "/run/systemd/private");
891 _cleanup_free_
char *p
= NULL
;
893 p
= path_join(m
->prefix
[EXEC_DIRECTORY_RUNTIME
], "systemd/private");
897 r
= sockaddr_un_set_path(&sa
.un
, p
);
900 return log_error_errno(r
, "Failed set socket path for private bus: %m");
903 (void) sockaddr_un_unlink(&sa
.un
);
905 fd
= socket(AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0);
907 return log_error_errno(errno
, "Failed to allocate private socket: %m");
910 r
= bind(fd
, &sa
.sa
, sa_len
);
912 return log_error_errno(errno
, "Failed to bind private socket: %m");
914 r
= listen(fd
, SOMAXCONN_DELUXE
);
916 return log_error_errno(errno
, "Failed to make private socket listening: %m");
918 /* Generate an inotify event in case somebody waits for this socket to appear using inotify() */
919 (void) touch(sa
.un
.sun_path
);
921 r
= sd_event_add_io(m
->event
, &s
, fd
, EPOLLIN
, bus_on_connection
, m
);
923 return log_error_errno(r
, "Failed to allocate event source: %m");
925 (void) sd_event_source_set_description(s
, "bus-connection");
927 m
->private_listen_fd
= TAKE_FD(fd
);
928 m
->private_listen_event_source
= s
;
930 log_debug("Successfully created private D-Bus server.");
935 static void destroy_bus(Manager
*m
, sd_bus
**bus
) {
945 /* Make sure all bus slots watching names are released. */
946 HASHMAP_FOREACH(u
, m
->watch_bus
) {
947 if (u
->match_bus_slot
&& sd_bus_slot_get_bus(u
->match_bus_slot
) == *bus
)
948 u
->match_bus_slot
= sd_bus_slot_unref(u
->match_bus_slot
);
949 if (u
->get_name_owner_slot
&& sd_bus_slot_get_bus(u
->get_name_owner_slot
) == *bus
)
950 u
->get_name_owner_slot
= sd_bus_slot_unref(u
->get_name_owner_slot
);
953 /* Get rid of tracked clients on this bus */
954 if (m
->subscribed
&& sd_bus_track_get_bus(m
->subscribed
) == *bus
) {
955 _cleanup_strv_free_
char **subscribed
= NULL
;
958 r
= bus_track_to_strv(m
->subscribed
, &subscribed
);
960 log_warning_errno(r
, "Failed to serialize api subscribers, ignoring: %m");
961 strv_free_and_replace(m
->subscribed_as_strv
, subscribed
);
963 m
->deserialized_bus_id
= m
->bus_id
;
964 m
->bus_id
= SD_ID128_NULL
;
966 m
->subscribed
= sd_bus_track_unref(m
->subscribed
);
969 HASHMAP_FOREACH(j
, m
->jobs
)
970 if (j
->bus_track
&& sd_bus_track_get_bus(j
->bus_track
) == *bus
)
971 j
->bus_track
= sd_bus_track_unref(j
->bus_track
);
973 HASHMAP_FOREACH(u
, m
->units
) {
974 if (u
->bus_track
&& sd_bus_track_get_bus(u
->bus_track
) == *bus
)
975 u
->bus_track
= sd_bus_track_unref(u
->bus_track
);
977 /* Get rid of pending freezer messages on this bus */
978 if (u
->pending_freezer_invocation
&& sd_bus_message_get_bus(u
->pending_freezer_invocation
) == *bus
)
979 u
->pending_freezer_invocation
= sd_bus_message_unref(u
->pending_freezer_invocation
);
982 /* Get rid of queued message on this bus */
983 if (m
->pending_reload_message
&& sd_bus_message_get_bus(m
->pending_reload_message
) == *bus
)
984 m
->pending_reload_message
= sd_bus_message_unref(m
->pending_reload_message
);
986 /* Possibly flush unwritten data, but only if we are
987 * unprivileged, since we don't want to sync here */
988 if (!MANAGER_IS_SYSTEM(m
))
991 /* And destroy the object */
992 *bus
= sd_bus_close_unref(*bus
);
995 void bus_done_api(Manager
*m
) {
996 destroy_bus(m
, &m
->api_bus
);
999 void bus_done_system(Manager
*m
) {
1000 destroy_bus(m
, &m
->system_bus
);
1003 void bus_done_private(Manager
*m
) {
1008 while ((b
= set_steal_first(m
->private_buses
)))
1011 m
->private_buses
= set_free(m
->private_buses
);
1013 m
->private_listen_event_source
= sd_event_source_disable_unref(m
->private_listen_event_source
);
1014 m
->private_listen_fd
= safe_close(m
->private_listen_fd
);
1017 void bus_done(Manager
*m
) {
1022 bus_done_private(m
);
1024 assert(!m
->subscribed
);
1026 m
->polkit_registry
= hashmap_free(m
->polkit_registry
);
1029 int bus_fdset_add_all(Manager
*m
, FDSet
*fds
) {
1036 /* When we are about to reexecute we add all D-Bus fds to the
1037 * set to pass over to the newly executed systemd. They won't
1038 * be used there however, except thatt they are closed at the
1039 * very end of deserialization, those making it possible for
1040 * clients to synchronously wait for systemd to reexec by
1041 * simply waiting for disconnection */
1044 fd
= sd_bus_get_fd(m
->api_bus
);
1046 fd
= fdset_put_dup(fds
, fd
);
1052 SET_FOREACH(b
, m
->private_buses
) {
1053 fd
= sd_bus_get_fd(b
);
1055 fd
= fdset_put_dup(fds
, fd
);
1061 /* We don't offer any APIs on the system bus (well, unless it
1062 * is the same as the API bus) hence we don't bother with it
1068 int bus_foreach_bus(
1070 sd_bus_track
*subscribed2
,
1071 int (*send_message
)(sd_bus
*bus
, void *userdata
),
1077 assert(send_message
);
1079 /* Send to all direct buses, unconditionally */
1081 SET_FOREACH(b
, m
->private_buses
) {
1083 /* Don't bother with enqueuing these messages to clients that haven't started yet */
1084 if (sd_bus_is_ready(b
) <= 0)
1087 RET_GATHER(r
, send_message(b
, userdata
));
1090 /* Send to API bus, but only if somebody is subscribed */
1092 (sd_bus_track_count(m
->subscribed
) > 0 ||
1093 sd_bus_track_count(subscribed2
) > 0))
1094 RET_GATHER(r
, send_message(m
->api_bus
, userdata
));
1099 void bus_track_serialize(sd_bus_track
*t
, FILE *f
, const char *prefix
) {
1105 for (n
= sd_bus_track_first(t
); n
; n
= sd_bus_track_next(t
)) {
1108 c
= sd_bus_track_count_name(t
, n
);
1109 for (j
= 0; j
< c
; j
++)
1110 (void) serialize_item(f
, prefix
, n
);
1114 uint64_t manager_bus_n_queued_write(Manager
*m
) {
1119 /* Returns the total number of messages queued for writing on all our direct and API buses. */
1121 SET_FOREACH(b
, m
->private_buses
) {
1124 r
= sd_bus_get_n_queued_write(b
, &k
);
1126 log_debug_errno(r
, "Failed to query queued messages for private bus: %m");
1134 r
= sd_bus_get_n_queued_write(m
->api_bus
, &k
);
1136 log_debug_errno(r
, "Failed to query queued messages for API bus: %m");
1144 static void vtable_dump_bus_properties(FILE *f
, const sd_bus_vtable
*table
) {
1145 const sd_bus_vtable
*i
;
1147 for (i
= table
; i
->type
!= _SD_BUS_VTABLE_END
; i
++) {
1148 if (!IN_SET(i
->type
, _SD_BUS_VTABLE_PROPERTY
, _SD_BUS_VTABLE_WRITABLE_PROPERTY
) ||
1149 (i
->flags
& (SD_BUS_VTABLE_DEPRECATED
| SD_BUS_VTABLE_HIDDEN
)) != 0)
1152 fprintf(f
, "%s\n", i
->x
.property
.member
);
1156 void dump_bus_properties(FILE *f
) {
1159 vtable_dump_bus_properties(f
, bus_automount_vtable
);
1160 vtable_dump_bus_properties(f
, bus_cgroup_vtable
);
1161 vtable_dump_bus_properties(f
, bus_device_vtable
);
1162 vtable_dump_bus_properties(f
, bus_exec_vtable
);
1163 vtable_dump_bus_properties(f
, bus_job_vtable
);
1164 vtable_dump_bus_properties(f
, bus_kill_vtable
);
1165 vtable_dump_bus_properties(f
, bus_manager_vtable
);
1166 vtable_dump_bus_properties(f
, bus_mount_vtable
);
1167 vtable_dump_bus_properties(f
, bus_path_vtable
);
1168 vtable_dump_bus_properties(f
, bus_scope_vtable
);
1169 vtable_dump_bus_properties(f
, bus_service_vtable
);
1170 vtable_dump_bus_properties(f
, bus_slice_vtable
);
1171 vtable_dump_bus_properties(f
, bus_socket_vtable
);
1172 vtable_dump_bus_properties(f
, bus_swap_vtable
);
1173 vtable_dump_bus_properties(f
, bus_target_vtable
);
1174 vtable_dump_bus_properties(f
, bus_timer_vtable
);
1175 vtable_dump_bus_properties(f
, bus_unit_vtable
);
1176 vtable_dump_bus_properties(f
, bus_unit_cgroup_vtable
);