1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
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"
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"
36 #include "mkdir-label.h"
37 #include "process-util.h"
38 #include "selinux-access.h"
39 #include "serialize.h"
42 #include "string-util.h"
45 #include "umask-util.h"
46 #include "user-util.h"
48 #define CONNECTIONS_MAX 4096
50 static void destroy_bus(Manager
*m
, sd_bus
**bus
);
52 int bus_send_pending_reload_message(Manager
*m
) {
57 if (!m
->pending_reload_message
)
60 /* If we cannot get rid of this message we won't dispatch any D-Bus messages, so that we won't end up wanting
61 * to queue another message. */
63 r
= sd_bus_send(NULL
, m
->pending_reload_message
, NULL
);
65 log_warning_errno(r
, "Failed to send queued message, ignoring: %m");
67 m
->pending_reload_message
= sd_bus_message_unref(m
->pending_reload_message
);
72 int bus_forward_agent_released(Manager
*m
, const char *path
) {
78 if (!MANAGER_IS_SYSTEM(m
))
84 /* If we are running a system instance we forward the agent message on the system bus, so that the user
85 * instances get notified about this, too */
87 r
= sd_bus_emit_signal(m
->system_bus
,
88 "/org/freedesktop/systemd1/agent",
89 "org.freedesktop.systemd1.Agent",
93 return log_debug_errno(r
, "Failed to propagate agent release message: %m");
98 static int signal_agent_released(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
99 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
100 Manager
*m
= ASSERT_PTR(userdata
);
107 /* only accept org.freedesktop.systemd1.Agent from UID=0 */
108 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
112 r
= sd_bus_creds_get_euid(creds
, &sender_uid
);
113 if (r
< 0 || sender_uid
!= 0)
116 /* parse 'cgroup-empty' notification */
117 r
= sd_bus_message_read(message
, "s", &cgroup
);
119 bus_log_parse_error(r
);
123 manager_notify_cgroup_empty(m
, cgroup
);
127 static int signal_disconnected(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
128 Manager
*m
= ASSERT_PTR(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
= ASSERT_PTR(userdata
);
157 r
= sd_bus_message_read(message
, "s", &name
);
159 bus_log_parse_error(r
);
163 if (manager_unit_inactive_or_pending(m
, SPECIAL_DBUS_SERVICE
) ||
164 manager_unit_inactive_or_pending(m
, SPECIAL_DBUS_SOCKET
)) {
165 r
= sd_bus_error_set(&error
, BUS_ERROR_SHUTTING_DOWN
, "Refusing activation, D-Bus is shutting down.");
169 r
= manager_load_unit(m
, name
, NULL
, &error
, &u
);
173 if (u
->refuse_manual_start
) {
174 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
);
178 r
= manager_add_job(m
, JOB_START
, u
, JOB_REPLACE
, NULL
, &error
, NULL
);
182 /* Successfully queued, that's it for us */
186 if (!sd_bus_error_is_set(&error
))
187 sd_bus_error_set_errno(&error
, r
);
189 log_debug("D-Bus activation failed for %s: %s", name
, bus_error_message(&error
, r
));
191 r
= sd_bus_message_new_signal(sd_bus_message_get_bus(message
), &reply
, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
193 bus_log_create_error(r
);
197 r
= sd_bus_message_append(reply
, "sss", name
, error
.name
, error
.message
);
199 bus_log_create_error(r
);
203 r
= sd_bus_send_to(NULL
, reply
, "org.freedesktop.DBus", NULL
);
205 return log_error_errno(r
, "Failed to respond with to bus activation request: %m");
211 static int mac_selinux_filter(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
212 Manager
*m
= userdata
;
213 const char *verb
, *path
;
220 /* Our own method calls are all protected individually with
221 * selinux checks, but the built-in interfaces need to be
224 if (sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Properties", "Set"))
226 else if (sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Introspectable", NULL
) ||
227 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Properties", NULL
) ||
228 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.ObjectManager", NULL
) ||
229 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Peer", NULL
))
234 path
= sd_bus_message_get_path(message
);
236 if (object_path_startswith("/org/freedesktop/systemd1", path
)) {
237 r
= mac_selinux_access_check(message
, verb
, error
);
244 if (streq_ptr(path
, "/org/freedesktop/systemd1/unit/self")) {
245 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
248 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
252 r
= sd_bus_creds_get_pid(creds
, &pid
);
256 u
= manager_get_unit_by_pid(m
, pid
);
258 r
= manager_get_job_from_dbus_path(m
, path
, &j
);
262 manager_load_unit_from_dbus_path(m
, path
, NULL
, &u
);
267 r
= mac_selinux_unit_access_check(u
, message
, verb
, error
);
275 static int find_unit(Manager
*m
, sd_bus
*bus
, const char *path
, Unit
**unit
, sd_bus_error
*error
) {
276 Unit
*u
= NULL
; /* just to appease gcc, initialization is not really necessary */
283 if (streq_ptr(path
, "/org/freedesktop/systemd1/unit/self")) {
284 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
285 sd_bus_message
*message
;
288 message
= sd_bus_get_current_message(bus
);
292 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
296 r
= sd_bus_creds_get_pid(creds
, &pid
);
300 u
= manager_get_unit_by_pid(m
, pid
);
304 r
= manager_load_unit_from_dbus_path(m
, path
, error
, &u
);
314 static int bus_unit_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
315 Manager
*m
= ASSERT_PTR(userdata
);
322 return find_unit(m
, bus
, path
, (Unit
**) found
, error
);
325 static int bus_unit_interface_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
326 Manager
*m
= ASSERT_PTR(userdata
);
335 r
= find_unit(m
, bus
, path
, &u
, error
);
339 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
346 static int bus_unit_cgroup_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
347 Manager
*m
= ASSERT_PTR(userdata
);
356 r
= find_unit(m
, bus
, path
, &u
, error
);
360 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
363 if (!UNIT_HAS_CGROUP_CONTEXT(u
))
370 static int bus_cgroup_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
371 Manager
*m
= ASSERT_PTR(userdata
);
381 r
= find_unit(m
, bus
, path
, &u
, error
);
385 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
388 c
= unit_get_cgroup_context(u
);
396 static int bus_exec_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
397 Manager
*m
= ASSERT_PTR(userdata
);
407 r
= find_unit(m
, bus
, path
, &u
, error
);
411 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
414 c
= unit_get_exec_context(u
);
422 static int bus_kill_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
423 Manager
*m
= ASSERT_PTR(userdata
);
433 r
= find_unit(m
, bus
, path
, &u
, error
);
437 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
440 c
= unit_get_kill_context(u
);
448 static int bus_unit_enumerate(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
449 _cleanup_strv_free_
char **l
= NULL
;
450 Manager
*m
= userdata
;
454 l
= new0(char*, hashmap_size(m
->units
)+1);
458 HASHMAP_FOREACH(u
, m
->units
) {
459 l
[k
] = unit_dbus_path(u
);
466 *nodes
= TAKE_PTR(l
);
471 static const BusObjectImplementation unit_object
= {
472 "/org/freedesktop/systemd1/unit",
473 "org.freedesktop.systemd1.Unit",
474 .fallback_vtables
= BUS_FALLBACK_VTABLES(
475 { bus_unit_vtable
, bus_unit_find
}),
476 .node_enumerator
= bus_unit_enumerate
,
479 static const BusObjectImplementation bus_automount_object
= {
480 "/org/freedesktop/systemd1/unit",
481 "org.freedesktop.systemd1.Automount",
482 .fallback_vtables
= BUS_FALLBACK_VTABLES(
483 { bus_automount_vtable
, bus_unit_interface_find
}),
486 static const BusObjectImplementation bus_device_object
= {
487 "/org/freedesktop/systemd1/unit",
488 "org.freedesktop.systemd1.Device",
489 .fallback_vtables
= BUS_FALLBACK_VTABLES(
490 { bus_device_vtable
, bus_unit_interface_find
}),
493 static const BusObjectImplementation bus_mount_object
= {
494 "/org/freedesktop/systemd1/unit",
495 "org.freedesktop.systemd1.Mount",
496 .fallback_vtables
= BUS_FALLBACK_VTABLES(
497 { bus_mount_vtable
, bus_unit_interface_find
},
498 { bus_unit_cgroup_vtable
, bus_unit_cgroup_find
},
499 { bus_cgroup_vtable
, bus_cgroup_context_find
},
500 { bus_exec_vtable
, bus_exec_context_find
},
501 { bus_kill_vtable
, bus_kill_context_find
}),
504 static const BusObjectImplementation bus_path_object
= {
505 "/org/freedesktop/systemd1/unit",
506 "org.freedesktop.systemd1.Path",
507 .fallback_vtables
= BUS_FALLBACK_VTABLES(
508 { bus_path_vtable
, bus_unit_interface_find
}),
511 static const BusObjectImplementation bus_scope_object
= {
512 "/org/freedesktop/systemd1/unit",
513 "org.freedesktop.systemd1.Scope",
514 .fallback_vtables
= BUS_FALLBACK_VTABLES(
515 { bus_scope_vtable
, bus_unit_interface_find
},
516 { bus_unit_cgroup_vtable
, bus_unit_cgroup_find
},
517 { bus_cgroup_vtable
, bus_cgroup_context_find
},
518 { bus_kill_vtable
, bus_kill_context_find
}),
521 static const BusObjectImplementation bus_service_object
= {
522 "/org/freedesktop/systemd1/unit",
523 "org.freedesktop.systemd1.Service",
524 .fallback_vtables
= BUS_FALLBACK_VTABLES(
525 { bus_service_vtable
, bus_unit_interface_find
},
526 { bus_unit_cgroup_vtable
, bus_unit_cgroup_find
},
527 { bus_cgroup_vtable
, bus_cgroup_context_find
},
528 { bus_exec_vtable
, bus_exec_context_find
},
529 { bus_kill_vtable
, bus_kill_context_find
}),
532 static const BusObjectImplementation bus_slice_object
= {
533 "/org/freedesktop/systemd1/unit",
534 "org.freedesktop.systemd1.Slice",
535 .fallback_vtables
= BUS_FALLBACK_VTABLES(
536 { bus_slice_vtable
, bus_unit_interface_find
},
537 { bus_unit_cgroup_vtable
, bus_unit_cgroup_find
},
538 { bus_cgroup_vtable
, bus_cgroup_context_find
}),
541 static const BusObjectImplementation bus_socket_object
= {
542 "/org/freedesktop/systemd1/unit",
543 "org.freedesktop.systemd1.Socket",
544 .fallback_vtables
= BUS_FALLBACK_VTABLES(
545 { bus_socket_vtable
, bus_unit_interface_find
},
546 { bus_unit_cgroup_vtable
, bus_unit_cgroup_find
},
547 { bus_cgroup_vtable
, bus_cgroup_context_find
},
548 { bus_exec_vtable
, bus_exec_context_find
},
549 { bus_kill_vtable
, bus_kill_context_find
}),
552 static const BusObjectImplementation bus_swap_object
= {
553 "/org/freedesktop/systemd1/unit",
554 "org.freedesktop.systemd1.Swap",
555 .fallback_vtables
= BUS_FALLBACK_VTABLES(
556 { bus_swap_vtable
, bus_unit_interface_find
},
557 { bus_unit_cgroup_vtable
, bus_unit_cgroup_find
},
558 { bus_cgroup_vtable
, bus_cgroup_context_find
},
559 { bus_exec_vtable
, bus_exec_context_find
},
560 { bus_kill_vtable
, bus_kill_context_find
}),
563 static const BusObjectImplementation bus_target_object
= {
564 "/org/freedesktop/systemd1/unit",
565 "org.freedesktop.systemd1.Target",
566 .fallback_vtables
= BUS_FALLBACK_VTABLES(
567 { bus_target_vtable
, bus_unit_interface_find
}),
570 static const BusObjectImplementation bus_timer_object
= {
571 "/org/freedesktop/systemd1/unit",
572 "org.freedesktop.systemd1.Timer",
573 .fallback_vtables
= BUS_FALLBACK_VTABLES(
574 { bus_timer_vtable
, bus_unit_interface_find
}),
577 static const BusObjectImplementation bus_manager_object
= {
578 "/org/freedesktop/systemd1",
579 "org.freedesktop.systemd1.Manager",
580 .vtables
= BUS_VTABLES(bus_manager_vtable
),
581 .children
= BUS_IMPLEMENTATIONS(
584 &bus_automount_object
,
597 static const BusObjectImplementation manager_log_control_object
= {
598 "/org/freedesktop/LogControl1",
599 "org.freedesktop.LogControl1",
600 .vtables
= BUS_VTABLES(bus_manager_log_control_vtable
),
603 int bus_manager_introspect_implementations(FILE *out
, const char *pattern
) {
604 return bus_introspect_implementations(
607 BUS_IMPLEMENTATIONS(&bus_manager_object
,
608 &manager_log_control_object
));
611 static int bus_setup_api_vtables(Manager
*m
, sd_bus
*bus
) {
618 r
= sd_bus_add_filter(bus
, NULL
, mac_selinux_filter
, m
);
620 return log_error_errno(r
, "Failed to add SELinux access filter: %m");
623 r
= bus_add_implementation(bus
, &bus_manager_object
, m
);
627 return bus_add_implementation(bus
, &manager_log_control_object
, m
);
630 static int bus_setup_disconnected_match(Manager
*m
, sd_bus
*bus
) {
636 r
= sd_bus_match_signal_async(
639 "org.freedesktop.DBus.Local",
640 "/org/freedesktop/DBus/Local",
641 "org.freedesktop.DBus.Local",
643 signal_disconnected
, NULL
, m
);
645 return log_error_errno(r
, "Failed to request match for Disconnected message: %m");
650 static int bus_on_connection(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
651 _cleanup_(sd_bus_close_unrefp
) sd_bus
*bus
= NULL
;
652 _cleanup_close_
int nfd
= -1;
653 Manager
*m
= ASSERT_PTR(userdata
);
659 nfd
= accept4(fd
, NULL
, NULL
, SOCK_NONBLOCK
|SOCK_CLOEXEC
);
661 if (ERRNO_IS_ACCEPT_AGAIN(errno
))
664 log_warning_errno(errno
, "Failed to accept private connection, ignoring: %m");
668 if (set_size(m
->private_buses
) >= CONNECTIONS_MAX
) {
669 log_warning("Too many concurrent connections, refusing");
673 r
= sd_bus_new(&bus
);
675 log_warning_errno(r
, "Failed to allocate new private connection bus: %m");
679 (void) sd_bus_set_description(bus
, "private-bus-connection");
681 r
= sd_bus_set_fd(bus
, nfd
, nfd
);
683 log_warning_errno(r
, "Failed to set fd on new connection bus: %m");
689 r
= bus_check_peercred(bus
);
691 log_warning_errno(r
, "Incoming private connection from unprivileged client, refusing: %m");
695 assert_se(sd_id128_randomize(&id
) >= 0);
697 r
= sd_bus_set_server(bus
, 1, id
);
699 log_warning_errno(r
, "Failed to enable server support for new connection bus: %m");
703 r
= sd_bus_negotiate_creds(bus
, 1,
704 SD_BUS_CREDS_PID
|SD_BUS_CREDS_UID
|
705 SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EFFECTIVE_CAPS
|
706 SD_BUS_CREDS_SELINUX_CONTEXT
);
708 log_warning_errno(r
, "Failed to enable credentials for new connection: %m");
712 r
= sd_bus_set_sender(bus
, "org.freedesktop.systemd1");
714 log_warning_errno(r
, "Failed to set direct connection sender: %m");
718 r
= sd_bus_start(bus
);
720 log_warning_errno(r
, "Failed to start new connection bus: %m");
724 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
726 log_warning_errno(r
, "Failed to attach new connection bus to event loop: %m");
730 r
= bus_setup_disconnected_match(m
, bus
);
734 r
= bus_setup_api_vtables(m
, bus
);
736 log_warning_errno(r
, "Failed to set up API vtables on new connection bus: %m");
740 r
= set_ensure_put(&m
->private_buses
, NULL
, bus
);
746 log_warning_errno(r
, "Failed to add new connection bus to set: %m");
752 log_debug("Accepted new private connection.");
757 static int bus_setup_api(Manager
*m
, sd_bus
*bus
) {
765 /* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
766 r
= sd_bus_negotiate_creds(bus
, 1,
767 SD_BUS_CREDS_PID
|SD_BUS_CREDS_UID
|
768 SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EFFECTIVE_CAPS
|
769 SD_BUS_CREDS_SELINUX_CONTEXT
);
771 log_warning_errno(r
, "Failed to enable credential passing, ignoring: %m");
773 r
= bus_setup_api_vtables(m
, bus
);
777 HASHMAP_FOREACH_KEY(u
, name
, m
->watch_bus
) {
778 r
= unit_install_bus_match(u
, bus
, name
);
780 log_error_errno(r
, "Failed to subscribe to NameOwnerChanged signal for '%s': %m", name
);
783 r
= sd_bus_match_signal_async(
786 "org.freedesktop.DBus",
787 "/org/freedesktop/DBus",
788 "org.freedesktop.systemd1.Activator",
790 signal_activation_request
, NULL
, m
);
792 log_warning_errno(r
, "Failed to subscribe to activation signal: %m");
794 /* Allow replacing of our name, to ease implementation of reexecution, where we keep the old connection open
795 * until after the new connection is set up and the name installed to allow clients to synchronously wait for
796 * reexecution to finish */
797 r
= sd_bus_request_name_async(bus
, NULL
, "org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING
|SD_BUS_NAME_ALLOW_REPLACEMENT
, NULL
, NULL
);
799 return log_error_errno(r
, "Failed to request name: %m");
801 log_debug("Successfully connected to API bus.");
806 int bus_init_api(Manager
*m
) {
807 _cleanup_(sd_bus_close_unrefp
) sd_bus
*bus
= NULL
;
813 /* The API and system bus is the same if we are running in system mode */
814 if (MANAGER_IS_SYSTEM(m
) && m
->system_bus
)
815 bus
= sd_bus_ref(m
->system_bus
);
817 if (MANAGER_IS_SYSTEM(m
))
818 r
= sd_bus_open_system_with_description(&bus
, "bus-api-system");
820 r
= sd_bus_open_user_with_description(&bus
, "bus-api-user");
822 return log_error_errno(r
, "Failed to connect to API bus: %m");
824 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
826 return log_error_errno(r
, "Failed to attach API bus to event loop: %m");
828 r
= bus_setup_disconnected_match(m
, bus
);
833 r
= bus_setup_api(m
, bus
);
835 return log_error_errno(r
, "Failed to set up API bus: %m");
837 m
->api_bus
= TAKE_PTR(bus
);
842 static int bus_setup_system(Manager
*m
, sd_bus
*bus
) {
848 /* if we are a user instance we get the Released message via the system bus */
849 if (MANAGER_IS_USER(m
)) {
850 r
= sd_bus_match_signal_async(
854 "/org/freedesktop/systemd1/agent",
855 "org.freedesktop.systemd1.Agent",
857 signal_agent_released
, NULL
, m
);
859 log_warning_errno(r
, "Failed to request Released match on system bus: %m");
862 log_debug("Successfully connected to system bus.");
866 int bus_init_system(Manager
*m
) {
867 _cleanup_(sd_bus_close_unrefp
) sd_bus
*bus
= NULL
;
873 /* The API and system bus is the same if we are running in system mode */
874 if (MANAGER_IS_SYSTEM(m
) && m
->api_bus
)
875 bus
= sd_bus_ref(m
->api_bus
);
877 r
= sd_bus_open_system_with_description(&bus
, "bus-system");
879 return log_error_errno(r
, "Failed to connect to system bus: %m");
881 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
883 return log_error_errno(r
, "Failed to attach system bus to event loop: %m");
885 r
= bus_setup_disconnected_match(m
, bus
);
890 r
= bus_setup_system(m
, bus
);
892 return log_error_errno(r
, "Failed to set up system bus: %m");
894 m
->system_bus
= TAKE_PTR(bus
);
899 int bus_init_private(Manager
*m
) {
900 _cleanup_close_
int fd
= -1;
901 union sockaddr_union sa
;
908 if (m
->private_listen_fd
>= 0)
911 if (MANAGER_IS_SYSTEM(m
)) {
913 /* We want the private bus only when running as init */
914 if (getpid_cached() != 1)
917 r
= sockaddr_un_set_path(&sa
.un
, "/run/systemd/private");
919 _cleanup_free_
char *joined
= NULL
;
922 e
= secure_getenv("XDG_RUNTIME_DIR");
924 return log_error_errno(SYNTHETIC_ERRNO(EHOSTDOWN
),
925 "XDG_RUNTIME_DIR is not set, refusing.");
927 joined
= path_join(e
, "/systemd/private");
931 r
= sockaddr_un_set_path(&sa
.un
, joined
);
934 return log_error_errno(r
, "Can't set path for AF_UNIX socket to bind to: %m");
937 (void) mkdir_parents_label(sa
.un
.sun_path
, 0755);
938 (void) sockaddr_un_unlink(&sa
.un
);
940 fd
= socket(AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0);
942 return log_error_errno(errno
, "Failed to allocate private socket: %m");
945 r
= bind(fd
, &sa
.sa
, sa_len
);
947 return log_error_errno(errno
, "Failed to bind private socket: %m");
949 r
= listen(fd
, SOMAXCONN
);
951 return log_error_errno(errno
, "Failed to make private socket listening: %m");
953 /* Generate an inotify event in case somebody waits for this socket to appear using inotify() */
954 (void) touch(sa
.un
.sun_path
);
956 r
= sd_event_add_io(m
->event
, &s
, fd
, EPOLLIN
, bus_on_connection
, m
);
958 return log_error_errno(r
, "Failed to allocate event source: %m");
960 (void) sd_event_source_set_description(s
, "bus-connection");
962 m
->private_listen_fd
= TAKE_FD(fd
);
963 m
->private_listen_event_source
= s
;
965 log_debug("Successfully created private D-Bus server.");
970 static void destroy_bus(Manager
*m
, sd_bus
**bus
) {
980 /* Make sure all bus slots watching names are released. */
981 HASHMAP_FOREACH(u
, m
->watch_bus
) {
982 if (u
->match_bus_slot
&& sd_bus_slot_get_bus(u
->match_bus_slot
) == *bus
)
983 u
->match_bus_slot
= sd_bus_slot_unref(u
->match_bus_slot
);
984 if (u
->get_name_owner_slot
&& sd_bus_slot_get_bus(u
->get_name_owner_slot
) == *bus
)
985 u
->get_name_owner_slot
= sd_bus_slot_unref(u
->get_name_owner_slot
);
988 /* Get rid of tracked clients on this bus */
989 if (m
->subscribed
&& sd_bus_track_get_bus(m
->subscribed
) == *bus
)
990 m
->subscribed
= sd_bus_track_unref(m
->subscribed
);
992 HASHMAP_FOREACH(j
, m
->jobs
)
993 if (j
->bus_track
&& sd_bus_track_get_bus(j
->bus_track
) == *bus
)
994 j
->bus_track
= sd_bus_track_unref(j
->bus_track
);
996 HASHMAP_FOREACH(u
, m
->units
) {
997 if (u
->bus_track
&& sd_bus_track_get_bus(u
->bus_track
) == *bus
)
998 u
->bus_track
= sd_bus_track_unref(u
->bus_track
);
1000 /* Get rid of pending freezer messages on this bus */
1001 if (u
->pending_freezer_invocation
&& sd_bus_message_get_bus(u
->pending_freezer_invocation
) == *bus
)
1002 u
->pending_freezer_invocation
= sd_bus_message_unref(u
->pending_freezer_invocation
);
1005 /* Get rid of queued message on this bus */
1006 if (m
->pending_reload_message
&& sd_bus_message_get_bus(m
->pending_reload_message
) == *bus
)
1007 m
->pending_reload_message
= sd_bus_message_unref(m
->pending_reload_message
);
1009 /* Possibly flush unwritten data, but only if we are
1010 * unprivileged, since we don't want to sync here */
1011 if (!MANAGER_IS_SYSTEM(m
))
1014 /* And destroy the object */
1015 *bus
= sd_bus_close_unref(*bus
);
1018 void bus_done_api(Manager
*m
) {
1019 destroy_bus(m
, &m
->api_bus
);
1022 void bus_done_system(Manager
*m
) {
1023 destroy_bus(m
, &m
->system_bus
);
1026 void bus_done_private(Manager
*m
) {
1031 while ((b
= set_steal_first(m
->private_buses
)))
1034 m
->private_buses
= set_free(m
->private_buses
);
1036 m
->private_listen_event_source
= sd_event_source_disable_unref(m
->private_listen_event_source
);
1037 m
->private_listen_fd
= safe_close(m
->private_listen_fd
);
1040 void bus_done(Manager
*m
) {
1045 bus_done_private(m
);
1047 assert(!m
->subscribed
);
1049 m
->deserialized_subscribed
= strv_free(m
->deserialized_subscribed
);
1050 bus_verify_polkit_async_registry_free(m
->polkit_registry
);
1053 int bus_fdset_add_all(Manager
*m
, FDSet
*fds
) {
1060 /* When we are about to reexecute we add all D-Bus fds to the
1061 * set to pass over to the newly executed systemd. They won't
1062 * be used there however, except thatt they are closed at the
1063 * very end of deserialization, those making it possible for
1064 * clients to synchronously wait for systemd to reexec by
1065 * simply waiting for disconnection */
1068 fd
= sd_bus_get_fd(m
->api_bus
);
1070 fd
= fdset_put_dup(fds
, fd
);
1076 SET_FOREACH(b
, m
->private_buses
) {
1077 fd
= sd_bus_get_fd(b
);
1079 fd
= fdset_put_dup(fds
, fd
);
1085 /* We don't offer any APIs on the system bus (well, unless it
1086 * is the same as the API bus) hence we don't bother with it
1092 int bus_foreach_bus(
1094 sd_bus_track
*subscribed2
,
1095 int (*send_message
)(sd_bus
*bus
, void *userdata
),
1101 /* Send to all direct buses, unconditionally */
1102 SET_FOREACH(b
, m
->private_buses
) {
1104 /* Don't bother with enqueuing these messages to clients that haven't started yet */
1105 if (sd_bus_is_ready(b
) <= 0)
1108 r
= send_message(b
, userdata
);
1113 /* Send to API bus, but only if somebody is subscribed */
1115 (sd_bus_track_count(m
->subscribed
) > 0 ||
1116 sd_bus_track_count(subscribed2
) > 0)) {
1117 r
= send_message(m
->api_bus
, userdata
);
1125 void bus_track_serialize(sd_bus_track
*t
, FILE *f
, const char *prefix
) {
1131 for (n
= sd_bus_track_first(t
); n
; n
= sd_bus_track_next(t
)) {
1134 c
= sd_bus_track_count_name(t
, n
);
1135 for (j
= 0; j
< c
; j
++)
1136 (void) serialize_item(f
, prefix
, n
);
1140 int bus_track_coldplug(Manager
*m
, sd_bus_track
**t
, bool recursive
, char **l
) {
1146 if (strv_isempty(l
))
1153 r
= sd_bus_track_new(m
->api_bus
, t
, NULL
, NULL
);
1158 r
= sd_bus_track_set_recursive(*t
, recursive
);
1162 return bus_track_add_name_many(*t
, l
);
1165 int bus_verify_manage_units_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1166 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.manage-units", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1169 int bus_verify_manage_unit_files_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1170 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.manage-unit-files", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1173 int bus_verify_reload_daemon_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1174 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.reload-daemon", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1177 int bus_verify_set_environment_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1178 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.set-environment", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1181 uint64_t manager_bus_n_queued_write(Manager
*m
) {
1186 /* Returns the total number of messages queued for writing on all our direct and API buses. */
1188 SET_FOREACH(b
, m
->private_buses
) {
1191 r
= sd_bus_get_n_queued_write(b
, &k
);
1193 log_debug_errno(r
, "Failed to query queued messages for private bus: %m");
1201 r
= sd_bus_get_n_queued_write(m
->api_bus
, &k
);
1203 log_debug_errno(r
, "Failed to query queued messages for API bus: %m");
1211 static void vtable_dump_bus_properties(FILE *f
, const sd_bus_vtable
*table
) {
1212 const sd_bus_vtable
*i
;
1214 for (i
= table
; i
->type
!= _SD_BUS_VTABLE_END
; i
++) {
1215 if (!IN_SET(i
->type
, _SD_BUS_VTABLE_PROPERTY
, _SD_BUS_VTABLE_WRITABLE_PROPERTY
) ||
1216 (i
->flags
& (SD_BUS_VTABLE_DEPRECATED
| SD_BUS_VTABLE_HIDDEN
)) != 0)
1219 fprintf(f
, "%s\n", i
->x
.property
.member
);
1223 void dump_bus_properties(FILE *f
) {
1226 vtable_dump_bus_properties(f
, bus_automount_vtable
);
1227 vtable_dump_bus_properties(f
, bus_cgroup_vtable
);
1228 vtable_dump_bus_properties(f
, bus_device_vtable
);
1229 vtable_dump_bus_properties(f
, bus_exec_vtable
);
1230 vtable_dump_bus_properties(f
, bus_job_vtable
);
1231 vtable_dump_bus_properties(f
, bus_kill_vtable
);
1232 vtable_dump_bus_properties(f
, bus_manager_vtable
);
1233 vtable_dump_bus_properties(f
, bus_mount_vtable
);
1234 vtable_dump_bus_properties(f
, bus_path_vtable
);
1235 vtable_dump_bus_properties(f
, bus_scope_vtable
);
1236 vtable_dump_bus_properties(f
, bus_service_vtable
);
1237 vtable_dump_bus_properties(f
, bus_slice_vtable
);
1238 vtable_dump_bus_properties(f
, bus_socket_vtable
);
1239 vtable_dump_bus_properties(f
, bus_swap_vtable
);
1240 vtable_dump_bus_properties(f
, bus_target_vtable
);
1241 vtable_dump_bus_properties(f
, bus_timer_vtable
);
1242 vtable_dump_bus_properties(f
, bus_unit_vtable
);
1243 vtable_dump_bus_properties(f
, bus_unit_cgroup_vtable
);