1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/epoll.h>
27 #include "alloc-util.h"
28 #include "bus-common-errors.h"
29 #include "bus-error.h"
30 #include "bus-internal.h"
32 #include "dbus-cgroup.h"
33 #include "dbus-execute.h"
35 #include "dbus-kill.h"
36 #include "dbus-manager.h"
37 #include "dbus-unit.h"
44 #include "process-util.h"
45 #include "selinux-access.h"
47 #include "string-util.h"
50 #include "user-util.h"
52 #define CONNECTIONS_MAX 4096
54 static void destroy_bus(Manager
*m
, sd_bus
**bus
);
56 int bus_send_queued_message(Manager
*m
) {
61 if (!m
->queued_message
)
64 /* If we cannot get rid of this message we won't dispatch any
65 * D-Bus messages, so that we won't end up wanting to queue
68 r
= sd_bus_send(NULL
, m
->queued_message
, NULL
);
70 log_warning_errno(r
, "Failed to send queued message: %m");
72 m
->queued_message
= sd_bus_message_unref(m
->queued_message
);
77 int bus_forward_agent_released(Manager
*m
, const char *path
) {
83 if (!MANAGER_IS_SYSTEM(m
))
89 /* If we are running a system instance we forward the agent message on the system bus, so that the user
90 * instances get notified about this, too */
92 r
= sd_bus_emit_signal(m
->system_bus
,
93 "/org/freedesktop/systemd1/agent",
94 "org.freedesktop.systemd1.Agent",
98 return log_debug_errno(r
, "Failed to propagate agent release message: %m");
103 static int signal_agent_released(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
104 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
105 Manager
*m
= userdata
;
113 /* only accept org.freedesktop.systemd1.Agent from UID=0 */
114 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
118 r
= sd_bus_creds_get_euid(creds
, &sender_uid
);
119 if (r
< 0 || sender_uid
!= 0)
122 /* parse 'cgroup-empty' notification */
123 r
= sd_bus_message_read(message
, "s", &cgroup
);
125 bus_log_parse_error(r
);
129 manager_notify_cgroup_empty(m
, cgroup
);
133 static int signal_disconnected(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
134 Manager
*m
= userdata
;
139 assert_se(bus
= sd_bus_message_get_bus(message
));
141 if (bus
== m
->api_bus
)
142 destroy_bus(m
, &m
->api_bus
);
143 if (bus
== m
->system_bus
)
144 destroy_bus(m
, &m
->system_bus
);
145 if (set_remove(m
->private_buses
, bus
)) {
146 log_debug("Got disconnect on private connection.");
147 destroy_bus(m
, &bus
);
153 static int signal_activation_request(sd_bus_message
*message
, void *userdata
, sd_bus_error
*ret_error
) {
154 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
155 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
156 Manager
*m
= userdata
;
164 r
= sd_bus_message_read(message
, "s", &name
);
166 bus_log_parse_error(r
);
170 if (manager_unit_inactive_or_pending(m
, SPECIAL_DBUS_SERVICE
) ||
171 manager_unit_inactive_or_pending(m
, SPECIAL_DBUS_SOCKET
)) {
172 r
= sd_bus_error_setf(&error
, BUS_ERROR_SHUTTING_DOWN
, "Refusing activation, D-Bus is shutting down.");
176 r
= manager_load_unit(m
, name
, NULL
, &error
, &u
);
180 if (u
->refuse_manual_start
) {
181 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
);
185 r
= manager_add_job(m
, JOB_START
, u
, JOB_REPLACE
, &error
, NULL
);
189 /* Successfully queued, that's it for us */
193 if (!sd_bus_error_is_set(&error
))
194 sd_bus_error_set_errno(&error
, r
);
196 log_debug("D-Bus activation failed for %s: %s", name
, bus_error_message(&error
, r
));
198 r
= sd_bus_message_new_signal(sd_bus_message_get_bus(message
), &reply
, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
200 bus_log_create_error(r
);
204 r
= sd_bus_message_append(reply
, "sss", name
, error
.name
, error
.message
);
206 bus_log_create_error(r
);
210 r
= sd_bus_send_to(NULL
, reply
, "org.freedesktop.DBus", NULL
);
212 return log_error_errno(r
, "Failed to respond with to bus activation request: %m");
218 static int mac_selinux_filter(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
219 Manager
*m
= userdata
;
220 const char *verb
, *path
;
227 /* Our own method calls are all protected individually with
228 * selinux checks, but the built-in interfaces need to be
231 if (sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Properties", "Set"))
233 else if (sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Introspectable", NULL
) ||
234 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Properties", NULL
) ||
235 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.ObjectManager", NULL
) ||
236 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Peer", NULL
))
241 path
= sd_bus_message_get_path(message
);
243 if (object_path_startswith("/org/freedesktop/systemd1", path
)) {
245 r
= mac_selinux_access_check(message
, verb
, error
);
252 if (streq_ptr(path
, "/org/freedesktop/systemd1/unit/self")) {
253 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
256 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
260 r
= sd_bus_creds_get_pid(creds
, &pid
);
264 u
= manager_get_unit_by_pid(m
, pid
);
266 r
= manager_get_job_from_dbus_path(m
, path
, &j
);
270 manager_load_unit_from_dbus_path(m
, path
, NULL
, &u
);
276 r
= mac_selinux_unit_access_check(u
, message
, verb
, error
);
284 static int bus_job_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
285 Manager
*m
= userdata
;
295 r
= manager_get_job_from_dbus_path(m
, path
, &j
);
303 static int find_unit(Manager
*m
, sd_bus
*bus
, const char *path
, Unit
**unit
, sd_bus_error
*error
) {
304 Unit
*u
= NULL
; /* just to appease gcc, initialization is not really necessary */
311 if (streq_ptr(path
, "/org/freedesktop/systemd1/unit/self")) {
312 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
313 sd_bus_message
*message
;
316 message
= sd_bus_get_current_message(bus
);
320 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
324 r
= sd_bus_creds_get_pid(creds
, &pid
);
328 u
= manager_get_unit_by_pid(m
, pid
);
332 r
= manager_load_unit_from_dbus_path(m
, path
, error
, &u
);
342 static int bus_unit_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
343 Manager
*m
= userdata
;
351 return find_unit(m
, bus
, path
, (Unit
**) found
, error
);
354 static int bus_unit_interface_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
355 Manager
*m
= userdata
;
365 r
= find_unit(m
, bus
, path
, &u
, error
);
369 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
376 static int bus_unit_cgroup_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
377 Manager
*m
= userdata
;
387 r
= find_unit(m
, bus
, path
, &u
, error
);
391 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
394 if (!UNIT_HAS_CGROUP_CONTEXT(u
))
401 static int bus_cgroup_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
402 Manager
*m
= userdata
;
413 r
= find_unit(m
, bus
, path
, &u
, error
);
417 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
420 c
= unit_get_cgroup_context(u
);
428 static int bus_exec_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
429 Manager
*m
= userdata
;
440 r
= find_unit(m
, bus
, path
, &u
, error
);
444 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
447 c
= unit_get_exec_context(u
);
455 static int bus_kill_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
456 Manager
*m
= userdata
;
467 r
= find_unit(m
, bus
, path
, &u
, error
);
471 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
474 c
= unit_get_kill_context(u
);
482 static int bus_job_enumerate(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
483 _cleanup_strv_free_
char **l
= NULL
;
484 Manager
*m
= userdata
;
489 l
= new0(char*, hashmap_size(m
->jobs
)+1);
493 HASHMAP_FOREACH(j
, m
->jobs
, i
) {
494 l
[k
] = job_dbus_path(j
);
501 assert(hashmap_size(m
->jobs
) == k
);
509 static int bus_unit_enumerate(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
510 _cleanup_strv_free_
char **l
= NULL
;
511 Manager
*m
= userdata
;
516 l
= new0(char*, hashmap_size(m
->units
)+1);
520 HASHMAP_FOREACH(u
, m
->units
, i
) {
521 l
[k
] = unit_dbus_path(u
);
534 static int bus_setup_api_vtables(Manager
*m
, sd_bus
*bus
) {
542 r
= sd_bus_add_filter(bus
, NULL
, mac_selinux_filter
, m
);
544 return log_error_errno(r
, "Failed to add SELinux access filter: %m");
547 r
= sd_bus_add_object_vtable(bus
, NULL
, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable
, m
);
549 return log_error_errno(r
, "Failed to register Manager vtable: %m");
551 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable
, bus_job_find
, m
);
553 return log_error_errno(r
, "Failed to register Job vtable: %m");
555 r
= sd_bus_add_node_enumerator(bus
, NULL
, "/org/freedesktop/systemd1/job", bus_job_enumerate
, m
);
557 return log_error_errno(r
, "Failed to add job enumerator: %m");
559 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable
, bus_unit_find
, m
);
561 return log_error_errno(r
, "Failed to register Unit vtable: %m");
563 r
= sd_bus_add_node_enumerator(bus
, NULL
, "/org/freedesktop/systemd1/unit", bus_unit_enumerate
, m
);
565 return log_error_errno(r
, "Failed to add job enumerator: %m");
567 for (t
= 0; t
< _UNIT_TYPE_MAX
; t
++) {
568 const char *interface
;
570 assert_se(interface
= unit_dbus_interface_from_type(t
));
572 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, unit_vtable
[t
]->bus_vtable
, bus_unit_interface_find
, m
);
574 return log_error_errno(r
, "Failed to register type specific vtable for %s: %m", interface
);
576 if (unit_vtable
[t
]->cgroup_context_offset
> 0) {
577 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_unit_cgroup_vtable
, bus_unit_cgroup_find
, m
);
579 return log_error_errno(r
, "Failed to register control group unit vtable for %s: %m", interface
);
581 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_cgroup_vtable
, bus_cgroup_context_find
, m
);
583 return log_error_errno(r
, "Failed to register control group vtable for %s: %m", interface
);
586 if (unit_vtable
[t
]->exec_context_offset
> 0) {
587 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_exec_vtable
, bus_exec_context_find
, m
);
589 return log_error_errno(r
, "Failed to register execute vtable for %s: %m", interface
);
592 if (unit_vtable
[t
]->kill_context_offset
> 0) {
593 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_kill_vtable
, bus_kill_context_find
, m
);
595 return log_error_errno(r
, "Failed to register kill vtable for %s: %m", interface
);
602 static int bus_setup_disconnected_match(Manager
*m
, sd_bus
*bus
) {
608 r
= sd_bus_match_signal_async(
611 "org.freedesktop.DBus.Local",
612 "/org/freedesktop/DBus/Local",
613 "org.freedesktop.DBus.Local",
615 signal_disconnected
, NULL
, m
);
617 return log_error_errno(r
, "Failed to request match for Disconnected message: %m");
622 static int bus_on_connection(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
623 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
624 _cleanup_close_
int nfd
= -1;
625 Manager
*m
= userdata
;
632 nfd
= accept4(fd
, NULL
, NULL
, SOCK_NONBLOCK
|SOCK_CLOEXEC
);
634 log_warning_errno(errno
, "Failed to accept private connection, ignoring: %m");
638 if (set_size(m
->private_buses
) >= CONNECTIONS_MAX
) {
639 log_warning("Too many concurrent connections, refusing");
643 r
= set_ensure_allocated(&m
->private_buses
, NULL
);
649 r
= sd_bus_new(&bus
);
651 log_warning_errno(r
, "Failed to allocate new private connection bus: %m");
655 r
= sd_bus_set_fd(bus
, nfd
, nfd
);
657 log_warning_errno(r
, "Failed to set fd on new connection bus: %m");
663 r
= bus_check_peercred(bus
);
665 log_warning_errno(r
, "Incoming private connection from unprivileged client, refusing: %m");
669 assert_se(sd_id128_randomize(&id
) >= 0);
671 r
= sd_bus_set_server(bus
, 1, id
);
673 log_warning_errno(r
, "Failed to enable server support for new connection bus: %m");
677 r
= sd_bus_negotiate_creds(bus
, 1,
678 SD_BUS_CREDS_PID
|SD_BUS_CREDS_UID
|
679 SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EFFECTIVE_CAPS
|
680 SD_BUS_CREDS_SELINUX_CONTEXT
);
682 log_warning_errno(r
, "Failed to enable credentials for new connection: %m");
686 r
= sd_bus_set_sender(bus
, "org.freedesktop.systemd1");
688 log_warning_errno(r
, "Failed to set direct connection sender: %m");
692 r
= sd_bus_start(bus
);
694 log_warning_errno(r
, "Failed to start new connection bus: %m");
698 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
700 log_warning_errno(r
, "Failed to attach new connection bus to event loop: %m");
704 r
= bus_setup_disconnected_match(m
, bus
);
708 r
= bus_setup_api_vtables(m
, bus
);
710 log_warning_errno(r
, "Failed to set up API vtables on new connection bus: %m");
714 r
= set_put(m
->private_buses
, bus
);
716 log_warning_errno(r
, "Failed to add new connection bus to set: %m");
722 log_debug("Accepted new private connection.");
727 int manager_sync_bus_names(Manager
*m
, sd_bus
*bus
) {
728 _cleanup_strv_free_
char **names
= NULL
;
737 r
= sd_bus_list_names(bus
, &names
, NULL
);
739 return log_error_errno(r
, "Failed to get initial list of names: %m");
741 /* We have to synchronize the current bus names with the
742 * list of active services. To do this, walk the list of
743 * all units with bus names. */
744 HASHMAP_FOREACH_KEY(u
, name
, m
->watch_bus
, i
) {
745 Service
*s
= SERVICE(u
);
749 if (!streq_ptr(s
->bus_name
, name
)) {
750 log_unit_warning(u
, "Bus name has changed from %s → %s, ignoring.", s
->bus_name
, name
);
754 /* Check if a service's bus name is in the list of currently
756 if (strv_contains(names
, name
)) {
757 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
760 /* If it is, determine its current owner */
761 r
= sd_bus_get_name_creds(bus
, name
, SD_BUS_CREDS_UNIQUE_NAME
, &creds
);
763 log_full_errno(r
== -ENXIO
? LOG_DEBUG
: LOG_ERR
, r
, "Failed to get bus name owner %s: %m", name
);
767 r
= sd_bus_creds_get_unique_name(creds
, &unique
);
769 log_full_errno(r
== -ENXIO
? LOG_DEBUG
: LOG_ERR
, r
, "Failed to get unique name for %s: %m", name
);
773 /* Now, let's compare that to the previous bus owner, and
774 * if it's still the same, all is fine, so just don't
775 * bother the service. Otherwise, the name has apparently
776 * changed, so synthesize a name owner changed signal. */
778 if (!streq_ptr(unique
, s
->bus_name_owner
))
779 UNIT_VTABLE(u
)->bus_name_owner_change(u
, name
, s
->bus_name_owner
, unique
);
781 /* So, the name we're watching is not on the bus.
782 * This either means it simply hasn't appeared yet,
783 * or it was lost during the daemon reload.
784 * Check if the service has a stored name owner,
785 * and synthesize a name loss signal in this case. */
787 if (s
->bus_name_owner
)
788 UNIT_VTABLE(u
)->bus_name_owner_change(u
, name
, s
->bus_name_owner
, NULL
);
795 static int bus_setup_api(Manager
*m
, sd_bus
*bus
) {
804 /* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
805 r
= sd_bus_negotiate_creds(bus
, 1,
806 SD_BUS_CREDS_PID
|SD_BUS_CREDS_UID
|
807 SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EFFECTIVE_CAPS
|
808 SD_BUS_CREDS_SELINUX_CONTEXT
);
810 log_warning_errno(r
, "Failed to enable credential passing, ignoring: %m");
812 r
= bus_setup_api_vtables(m
, bus
);
816 HASHMAP_FOREACH_KEY(u
, name
, m
->watch_bus
, i
) {
817 r
= unit_install_bus_match(u
, bus
, name
);
819 log_error_errno(r
, "Failed to subscribe to NameOwnerChanged signal for '%s': %m", name
);
822 r
= sd_bus_match_signal_async(
825 "org.freedesktop.DBus",
826 "/org/freedesktop/DBus",
827 "org.freedesktop.systemd1.Activator",
829 signal_activation_request
, NULL
, m
);
831 log_warning_errno(r
, "Failed to subscribe to activation signal: %m");
833 /* Allow replacing of our name, to ease implementation of reexecution, where we keep the old connection open
834 * until after the new connection is set up and the name installed to allow clients to synchronously wait for
835 * reexecution to finish */
836 r
= sd_bus_request_name_async(bus
, NULL
, "org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING
|SD_BUS_NAME_ALLOW_REPLACEMENT
, NULL
, NULL
);
838 return log_error_errno(r
, "Failed to request name: %m");
840 r
= manager_sync_bus_names(m
, bus
);
844 log_debug("Successfully connected to API bus.");
848 static int bus_init_api(Manager
*m
) {
849 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
855 /* The API and system bus is the same if we are running in system mode */
856 if (MANAGER_IS_SYSTEM(m
) && m
->system_bus
)
857 bus
= sd_bus_ref(m
->system_bus
);
859 if (MANAGER_IS_SYSTEM(m
))
860 r
= sd_bus_open_system(&bus
);
862 r
= sd_bus_open_user(&bus
);
864 return log_error_errno(r
, "Failed to connect to API bus: %m");
866 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
868 return log_error_errno(r
, "Failed to attach API bus to event loop: %m");
870 r
= bus_setup_disconnected_match(m
, bus
);
875 r
= bus_setup_api(m
, bus
);
877 return log_error_errno(r
, "Failed to set up API bus: %m");
885 static int bus_setup_system(Manager
*m
, sd_bus
*bus
) {
891 /* if we are a user instance we get the Released message via the system bus */
892 if (MANAGER_IS_USER(m
)) {
893 r
= sd_bus_match_signal_async(
897 "/org/freedesktop/systemd1/agent",
898 "org.freedesktop.systemd1.Agent",
900 signal_agent_released
, NULL
, m
);
902 log_warning_errno(r
, "Failed to request Released match on system bus: %m");
905 log_debug("Successfully connected to system bus.");
909 static int bus_init_system(Manager
*m
) {
910 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
916 /* The API and system bus is the same if we are running in system mode */
917 if (MANAGER_IS_SYSTEM(m
) && m
->api_bus
) {
918 m
->system_bus
= sd_bus_ref(m
->api_bus
);
922 r
= sd_bus_open_system(&bus
);
924 return log_error_errno(r
, "Failed to connect to system bus: %m");
926 r
= bus_setup_disconnected_match(m
, bus
);
930 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
932 return log_error_errno(r
, "Failed to attach system bus to event loop: %m");
934 r
= bus_setup_system(m
, bus
);
936 return log_error_errno(r
, "Failed to set up system bus: %m");
944 static int bus_init_private(Manager
*m
) {
945 _cleanup_close_
int fd
= -1;
946 union sockaddr_union sa
= {
947 .un
.sun_family
= AF_UNIX
955 if (m
->private_listen_fd
>= 0)
958 if (MANAGER_IS_SYSTEM(m
)) {
960 /* We want the private bus only when running as init */
961 if (getpid_cached() != 1)
964 strcpy(sa
.un
.sun_path
, "/run/systemd/private");
965 salen
= SOCKADDR_UN_LEN(sa
.un
);
967 size_t left
= sizeof(sa
.un
.sun_path
);
968 char *p
= sa
.un
.sun_path
;
971 e
= secure_getenv("XDG_RUNTIME_DIR");
973 log_error("Failed to determine XDG_RUNTIME_DIR");
977 left
= strpcpy(&p
, left
, e
);
978 left
= strpcpy(&p
, left
, "/systemd/private");
980 salen
= sizeof(sa
.un
) - left
;
983 (void) mkdir_parents_label(sa
.un
.sun_path
, 0755);
984 (void) unlink(sa
.un
.sun_path
);
986 fd
= socket(AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0);
988 return log_error_errno(errno
, "Failed to allocate private socket: %m");
990 r
= bind(fd
, &sa
.sa
, salen
);
992 return log_error_errno(errno
, "Failed to bind private socket: %m");
994 r
= listen(fd
, SOMAXCONN
);
996 return log_error_errno(errno
, "Failed to make private socket listening: %m");
998 /* Generate an inotify event in case somebody waits for this socket to appear using inotify() */
999 (void) touch(sa
.un
.sun_path
);
1001 r
= sd_event_add_io(m
->event
, &s
, fd
, EPOLLIN
, bus_on_connection
, m
);
1003 return log_error_errno(r
, "Failed to allocate event source: %m");
1005 (void) sd_event_source_set_description(s
, "bus-connection");
1007 m
->private_listen_fd
= fd
;
1008 m
->private_listen_event_source
= s
;
1011 log_debug("Successfully created private D-Bus server.");
1016 int bus_init(Manager
*m
, bool try_bus_connect
) {
1019 if (try_bus_connect
) {
1020 r
= bus_init_system(m
);
1022 return log_error_errno(r
, "Failed to initialize D-Bus connection: %m");
1024 r
= bus_init_api(m
);
1026 return log_error_errno(r
, "Error occured during D-Bus APIs initialization: %m");
1029 r
= bus_init_private(m
);
1031 return log_error_errno(r
, "Failed to create private D-Bus server: %m");
1036 static void destroy_bus(Manager
*m
, sd_bus
**bus
) {
1047 /* Make sure all bus slots watching names are released. */
1048 HASHMAP_FOREACH(u
, m
->watch_bus
, i
) {
1049 if (!u
->match_bus_slot
)
1052 if (sd_bus_slot_get_bus(u
->match_bus_slot
) != *bus
)
1055 u
->match_bus_slot
= sd_bus_slot_unref(u
->match_bus_slot
);
1058 /* Get rid of tracked clients on this bus */
1059 if (m
->subscribed
&& sd_bus_track_get_bus(m
->subscribed
) == *bus
)
1060 m
->subscribed
= sd_bus_track_unref(m
->subscribed
);
1062 HASHMAP_FOREACH(j
, m
->jobs
, i
)
1063 if (j
->bus_track
&& sd_bus_track_get_bus(j
->bus_track
) == *bus
)
1064 j
->bus_track
= sd_bus_track_unref(j
->bus_track
);
1066 /* Get rid of queued message on this bus */
1067 if (m
->queued_message
&& sd_bus_message_get_bus(m
->queued_message
) == *bus
)
1068 m
->queued_message
= sd_bus_message_unref(m
->queued_message
);
1070 /* Possibly flush unwritten data, but only if we are
1071 * unprivileged, since we don't want to sync here */
1072 if (!MANAGER_IS_SYSTEM(m
))
1075 /* And destroy the object */
1077 *bus
= sd_bus_unref(*bus
);
1080 void bus_done(Manager
*m
) {
1086 destroy_bus(m
, &m
->api_bus
);
1088 destroy_bus(m
, &m
->system_bus
);
1089 while ((b
= set_steal_first(m
->private_buses
)))
1092 m
->private_buses
= set_free(m
->private_buses
);
1094 m
->subscribed
= sd_bus_track_unref(m
->subscribed
);
1095 m
->deserialized_subscribed
= strv_free(m
->deserialized_subscribed
);
1097 if (m
->private_listen_event_source
)
1098 m
->private_listen_event_source
= sd_event_source_unref(m
->private_listen_event_source
);
1100 m
->private_listen_fd
= safe_close(m
->private_listen_fd
);
1102 bus_verify_polkit_async_registry_free(m
->polkit_registry
);
1105 int bus_fdset_add_all(Manager
*m
, FDSet
*fds
) {
1113 /* When we are about to reexecute we add all D-Bus fds to the
1114 * set to pass over to the newly executed systemd. They won't
1115 * be used there however, except thatt they are closed at the
1116 * very end of deserialization, those making it possible for
1117 * clients to synchronously wait for systemd to reexec by
1118 * simply waiting for disconnection */
1121 fd
= sd_bus_get_fd(m
->api_bus
);
1123 fd
= fdset_put_dup(fds
, fd
);
1129 SET_FOREACH(b
, m
->private_buses
, i
) {
1130 fd
= sd_bus_get_fd(b
);
1132 fd
= fdset_put_dup(fds
, fd
);
1138 /* We don't offer any APIs on the system bus (well, unless it
1139 * is the same as the API bus) hence we don't bother with it
1145 int bus_foreach_bus(
1147 sd_bus_track
*subscribed2
,
1148 int (*send_message
)(sd_bus
*bus
, void *userdata
),
1155 /* Send to all direct buses, unconditionally */
1156 SET_FOREACH(b
, m
->private_buses
, i
) {
1157 r
= send_message(b
, userdata
);
1162 /* Send to API bus, but only if somebody is subscribed */
1163 if (sd_bus_track_count(m
->subscribed
) > 0 ||
1164 sd_bus_track_count(subscribed2
) > 0) {
1165 r
= send_message(m
->api_bus
, userdata
);
1173 void bus_track_serialize(sd_bus_track
*t
, FILE *f
, const char *prefix
) {
1179 for (n
= sd_bus_track_first(t
); n
; n
= sd_bus_track_next(t
)) {
1182 c
= sd_bus_track_count_name(t
, n
);
1184 for (j
= 0; j
< c
; j
++) {
1193 int bus_track_coldplug(Manager
*m
, sd_bus_track
**t
, bool recursive
, char **l
) {
1199 if (strv_isempty(l
))
1206 r
= sd_bus_track_new(m
->api_bus
, t
, NULL
, NULL
);
1211 r
= sd_bus_track_set_recursive(*t
, recursive
);
1215 return bus_track_add_name_many(*t
, l
);
1218 int bus_verify_manage_units_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1219 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.manage-units", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1222 int bus_verify_manage_unit_files_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1223 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.manage-unit-files", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1226 int bus_verify_reload_daemon_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1227 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.reload-daemon", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1230 int bus_verify_set_environment_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1231 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.set-environment", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);