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 "selinux-access.h"
46 #include "string-util.h"
49 #include "user-util.h"
51 #define CONNECTIONS_MAX 4096
53 static void destroy_bus(Manager
*m
, sd_bus
**bus
);
55 int bus_send_queued_message(Manager
*m
) {
60 if (!m
->queued_message
)
63 /* If we cannot get rid of this message we won't dispatch any
64 * D-Bus messages, so that we won't end up wanting to queue
67 r
= sd_bus_send(NULL
, m
->queued_message
, NULL
);
69 log_warning_errno(r
, "Failed to send queued message: %m");
71 m
->queued_message
= sd_bus_message_unref(m
->queued_message
);
76 int bus_forward_agent_released(Manager
*m
, const char *path
) {
82 if (!MANAGER_IS_SYSTEM(m
))
88 /* If we are running a system instance we forward the agent message on the system bus, so that the user
89 * instances get notified about this, too */
91 r
= sd_bus_emit_signal(m
->system_bus
,
92 "/org/freedesktop/systemd1/agent",
93 "org.freedesktop.systemd1.Agent",
97 return log_debug_errno(r
, "Failed to propagate agent release message: %m");
102 static int signal_agent_released(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
103 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
104 Manager
*m
= userdata
;
112 /* only accept org.freedesktop.systemd1.Agent from UID=0 */
113 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
117 r
= sd_bus_creds_get_euid(creds
, &sender_uid
);
118 if (r
< 0 || sender_uid
!= 0)
121 /* parse 'cgroup-empty' notification */
122 r
= sd_bus_message_read(message
, "s", &cgroup
);
124 bus_log_parse_error(r
);
128 manager_notify_cgroup_empty(m
, cgroup
);
132 static int signal_disconnected(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
133 Manager
*m
= userdata
;
138 assert_se(bus
= sd_bus_message_get_bus(message
));
140 if (bus
== m
->api_bus
)
141 destroy_bus(m
, &m
->api_bus
);
142 if (bus
== m
->system_bus
)
143 destroy_bus(m
, &m
->system_bus
);
144 if (set_remove(m
->private_buses
, bus
)) {
145 log_debug("Got disconnect on private connection.");
146 destroy_bus(m
, &bus
);
152 static int signal_activation_request(sd_bus_message
*message
, void *userdata
, sd_bus_error
*ret_error
) {
153 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
154 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
155 Manager
*m
= userdata
;
163 r
= sd_bus_message_read(message
, "s", &name
);
165 bus_log_parse_error(r
);
169 if (manager_unit_inactive_or_pending(m
, SPECIAL_DBUS_SERVICE
) ||
170 manager_unit_inactive_or_pending(m
, SPECIAL_DBUS_SOCKET
)) {
171 r
= sd_bus_error_setf(&error
, BUS_ERROR_SHUTTING_DOWN
, "Refusing activation, D-Bus is shutting down.");
175 r
= manager_load_unit(m
, name
, NULL
, &error
, &u
);
179 if (u
->refuse_manual_start
) {
180 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
);
184 r
= manager_add_job(m
, JOB_START
, u
, JOB_REPLACE
, &error
, NULL
);
188 /* Successfully queued, that's it for us */
192 if (!sd_bus_error_is_set(&error
))
193 sd_bus_error_set_errno(&error
, r
);
195 log_debug("D-Bus activation failed for %s: %s", name
, bus_error_message(&error
, r
));
197 r
= sd_bus_message_new_signal(sd_bus_message_get_bus(message
), &reply
, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
199 bus_log_create_error(r
);
203 r
= sd_bus_message_append(reply
, "sss", name
, error
.name
, error
.message
);
205 bus_log_create_error(r
);
209 r
= sd_bus_send_to(NULL
, reply
, "org.freedesktop.DBus", NULL
);
211 return log_error_errno(r
, "Failed to respond with to bus activation request: %m");
217 static int mac_selinux_filter(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
218 Manager
*m
= userdata
;
219 const char *verb
, *path
;
226 /* Our own method calls are all protected individually with
227 * selinux checks, but the built-in interfaces need to be
230 if (sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Properties", "Set"))
232 else if (sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Introspectable", NULL
) ||
233 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Properties", NULL
) ||
234 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.ObjectManager", NULL
) ||
235 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Peer", NULL
))
240 path
= sd_bus_message_get_path(message
);
242 if (object_path_startswith("/org/freedesktop/systemd1", path
)) {
244 r
= mac_selinux_access_check(message
, verb
, error
);
251 if (streq_ptr(path
, "/org/freedesktop/systemd1/unit/self")) {
252 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
255 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
259 r
= sd_bus_creds_get_pid(creds
, &pid
);
263 u
= manager_get_unit_by_pid(m
, pid
);
265 r
= manager_get_job_from_dbus_path(m
, path
, &j
);
269 manager_load_unit_from_dbus_path(m
, path
, NULL
, &u
);
275 r
= mac_selinux_unit_access_check(u
, message
, verb
, error
);
283 static int bus_job_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
284 Manager
*m
= userdata
;
294 r
= manager_get_job_from_dbus_path(m
, path
, &j
);
302 static int find_unit(Manager
*m
, sd_bus
*bus
, const char *path
, Unit
**unit
, sd_bus_error
*error
) {
303 Unit
*u
= NULL
; /* just to appease gcc, initialization is not really necessary */
310 if (streq_ptr(path
, "/org/freedesktop/systemd1/unit/self")) {
311 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
312 sd_bus_message
*message
;
315 message
= sd_bus_get_current_message(bus
);
319 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
323 r
= sd_bus_creds_get_pid(creds
, &pid
);
327 u
= manager_get_unit_by_pid(m
, pid
);
331 r
= manager_load_unit_from_dbus_path(m
, path
, error
, &u
);
341 static int bus_unit_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
342 Manager
*m
= userdata
;
350 return find_unit(m
, bus
, path
, (Unit
**) found
, error
);
353 static int bus_unit_interface_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
354 Manager
*m
= userdata
;
364 r
= find_unit(m
, bus
, path
, &u
, error
);
368 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
375 static int bus_unit_cgroup_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
376 Manager
*m
= userdata
;
386 r
= find_unit(m
, bus
, path
, &u
, error
);
390 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
393 if (!UNIT_HAS_CGROUP_CONTEXT(u
))
400 static int bus_cgroup_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
401 Manager
*m
= userdata
;
412 r
= find_unit(m
, bus
, path
, &u
, error
);
416 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
419 c
= unit_get_cgroup_context(u
);
427 static int bus_exec_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
428 Manager
*m
= userdata
;
439 r
= find_unit(m
, bus
, path
, &u
, error
);
443 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
446 c
= unit_get_exec_context(u
);
454 static int bus_kill_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
455 Manager
*m
= userdata
;
466 r
= find_unit(m
, bus
, path
, &u
, error
);
470 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
473 c
= unit_get_kill_context(u
);
481 static int bus_job_enumerate(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
482 _cleanup_strv_free_
char **l
= NULL
;
483 Manager
*m
= userdata
;
488 l
= new0(char*, hashmap_size(m
->jobs
)+1);
492 HASHMAP_FOREACH(j
, m
->jobs
, i
) {
493 l
[k
] = job_dbus_path(j
);
500 assert(hashmap_size(m
->jobs
) == k
);
508 static int bus_unit_enumerate(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
509 _cleanup_strv_free_
char **l
= NULL
;
510 Manager
*m
= userdata
;
515 l
= new0(char*, hashmap_size(m
->units
)+1);
519 HASHMAP_FOREACH(u
, m
->units
, i
) {
520 l
[k
] = unit_dbus_path(u
);
533 static int bus_setup_api_vtables(Manager
*m
, sd_bus
*bus
) {
541 r
= sd_bus_add_filter(bus
, NULL
, mac_selinux_filter
, m
);
543 return log_error_errno(r
, "Failed to add SELinux access filter: %m");
546 r
= sd_bus_add_object_vtable(bus
, NULL
, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable
, m
);
548 return log_error_errno(r
, "Failed to register Manager vtable: %m");
550 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable
, bus_job_find
, m
);
552 return log_error_errno(r
, "Failed to register Job vtable: %m");
554 r
= sd_bus_add_node_enumerator(bus
, NULL
, "/org/freedesktop/systemd1/job", bus_job_enumerate
, m
);
556 return log_error_errno(r
, "Failed to add job enumerator: %m");
558 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable
, bus_unit_find
, m
);
560 return log_error_errno(r
, "Failed to register Unit vtable: %m");
562 r
= sd_bus_add_node_enumerator(bus
, NULL
, "/org/freedesktop/systemd1/unit", bus_unit_enumerate
, m
);
564 return log_error_errno(r
, "Failed to add job enumerator: %m");
566 for (t
= 0; t
< _UNIT_TYPE_MAX
; t
++) {
567 const char *interface
;
569 assert_se(interface
= unit_dbus_interface_from_type(t
));
571 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, unit_vtable
[t
]->bus_vtable
, bus_unit_interface_find
, m
);
573 return log_error_errno(r
, "Failed to register type specific vtable for %s: %m", interface
);
575 if (unit_vtable
[t
]->cgroup_context_offset
> 0) {
576 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_unit_cgroup_vtable
, bus_unit_cgroup_find
, m
);
578 return log_error_errno(r
, "Failed to register control group unit vtable for %s: %m", interface
);
580 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_cgroup_vtable
, bus_cgroup_context_find
, m
);
582 return log_error_errno(r
, "Failed to register control group vtable for %s: %m", interface
);
585 if (unit_vtable
[t
]->exec_context_offset
> 0) {
586 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_exec_vtable
, bus_exec_context_find
, m
);
588 return log_error_errno(r
, "Failed to register execute vtable for %s: %m", interface
);
591 if (unit_vtable
[t
]->kill_context_offset
> 0) {
592 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_kill_vtable
, bus_kill_context_find
, m
);
594 return log_error_errno(r
, "Failed to register kill vtable for %s: %m", interface
);
601 static int bus_setup_disconnected_match(Manager
*m
, sd_bus
*bus
) {
607 r
= sd_bus_match_signal_async(
610 "org.freedesktop.DBus.Local",
611 "/org/freedesktop/DBus/Local",
612 "org.freedesktop.DBus.Local",
614 signal_disconnected
, NULL
, m
);
616 return log_error_errno(r
, "Failed to request match for Disconnected message: %m");
621 static int bus_on_connection(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
622 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
623 _cleanup_close_
int nfd
= -1;
624 Manager
*m
= userdata
;
631 nfd
= accept4(fd
, NULL
, NULL
, SOCK_NONBLOCK
|SOCK_CLOEXEC
);
633 log_warning_errno(errno
, "Failed to accept private connection, ignoring: %m");
637 if (set_size(m
->private_buses
) >= CONNECTIONS_MAX
) {
638 log_warning("Too many concurrent connections, refusing");
642 r
= set_ensure_allocated(&m
->private_buses
, NULL
);
648 r
= sd_bus_new(&bus
);
650 log_warning_errno(r
, "Failed to allocate new private connection bus: %m");
654 r
= sd_bus_set_fd(bus
, nfd
, nfd
);
656 log_warning_errno(r
, "Failed to set fd on new connection bus: %m");
662 r
= bus_check_peercred(bus
);
664 log_warning_errno(r
, "Incoming private connection from unprivileged client, refusing: %m");
668 assert_se(sd_id128_randomize(&id
) >= 0);
670 r
= sd_bus_set_server(bus
, 1, id
);
672 log_warning_errno(r
, "Failed to enable server support for new connection bus: %m");
676 r
= sd_bus_negotiate_creds(bus
, 1,
677 SD_BUS_CREDS_PID
|SD_BUS_CREDS_UID
|
678 SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EFFECTIVE_CAPS
|
679 SD_BUS_CREDS_SELINUX_CONTEXT
);
681 log_warning_errno(r
, "Failed to enable credentials for new connection: %m");
685 r
= sd_bus_set_sender(bus
, "org.freedesktop.systemd1");
687 log_warning_errno(r
, "Failed to set direct connection sender: %m");
691 r
= sd_bus_start(bus
);
693 log_warning_errno(r
, "Failed to start new connection bus: %m");
697 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
699 log_warning_errno(r
, "Failed to attach new connection bus to event loop: %m");
703 r
= bus_setup_disconnected_match(m
, bus
);
707 r
= bus_setup_api_vtables(m
, bus
);
709 log_warning_errno(r
, "Failed to set up API vtables on new connection bus: %m");
713 r
= set_put(m
->private_buses
, bus
);
715 log_warning_errno(r
, "Failed to add new connection bus to set: %m");
721 log_debug("Accepted new private connection.");
726 int manager_sync_bus_names(Manager
*m
, sd_bus
*bus
) {
727 _cleanup_strv_free_
char **names
= NULL
;
736 r
= sd_bus_list_names(bus
, &names
, NULL
);
738 return log_error_errno(r
, "Failed to get initial list of names: %m");
740 /* We have to synchronize the current bus names with the
741 * list of active services. To do this, walk the list of
742 * all units with bus names. */
743 HASHMAP_FOREACH_KEY(u
, name
, m
->watch_bus
, i
) {
744 Service
*s
= SERVICE(u
);
748 if (!streq_ptr(s
->bus_name
, name
)) {
749 log_unit_warning(u
, "Bus name has changed from %s → %s, ignoring.", s
->bus_name
, name
);
753 /* Check if a service's bus name is in the list of currently
755 if (strv_contains(names
, name
)) {
756 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
759 /* If it is, determine its current owner */
760 r
= sd_bus_get_name_creds(bus
, name
, SD_BUS_CREDS_UNIQUE_NAME
, &creds
);
762 log_full_errno(r
== -ENXIO
? LOG_DEBUG
: LOG_ERR
, r
, "Failed to get bus name owner %s: %m", name
);
766 r
= sd_bus_creds_get_unique_name(creds
, &unique
);
768 log_full_errno(r
== -ENXIO
? LOG_DEBUG
: LOG_ERR
, r
, "Failed to get unique name for %s: %m", name
);
772 /* Now, let's compare that to the previous bus owner, and
773 * if it's still the same, all is fine, so just don't
774 * bother the service. Otherwise, the name has apparently
775 * changed, so synthesize a name owner changed signal. */
777 if (!streq_ptr(unique
, s
->bus_name_owner
))
778 UNIT_VTABLE(u
)->bus_name_owner_change(u
, name
, s
->bus_name_owner
, unique
);
780 /* So, the name we're watching is not on the bus.
781 * This either means it simply hasn't appeared yet,
782 * or it was lost during the daemon reload.
783 * Check if the service has a stored name owner,
784 * and synthesize a name loss signal in this case. */
786 if (s
->bus_name_owner
)
787 UNIT_VTABLE(u
)->bus_name_owner_change(u
, name
, s
->bus_name_owner
, NULL
);
794 static int bus_setup_api(Manager
*m
, sd_bus
*bus
) {
803 /* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
804 r
= sd_bus_negotiate_creds(bus
, 1,
805 SD_BUS_CREDS_PID
|SD_BUS_CREDS_UID
|
806 SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EFFECTIVE_CAPS
|
807 SD_BUS_CREDS_SELINUX_CONTEXT
);
809 log_warning_errno(r
, "Failed to enable credential passing, ignoring: %m");
811 r
= bus_setup_api_vtables(m
, bus
);
815 HASHMAP_FOREACH_KEY(u
, name
, m
->watch_bus
, i
) {
816 r
= unit_install_bus_match(u
, bus
, name
);
818 log_error_errno(r
, "Failed to subscribe to NameOwnerChanged signal for '%s': %m", name
);
821 r
= sd_bus_match_signal_async(
824 "org.freedesktop.DBus",
825 "/org/freedesktop/DBus",
826 "org.freedesktop.systemd1.Activator",
828 signal_activation_request
, NULL
, m
);
830 log_warning_errno(r
, "Failed to subscribe to activation signal: %m");
832 /* Allow replacing of our name, to ease implementation of reexecution, where we keep the old connection open
833 * until after the new connection is set up and the name installed to allow clients to synchronously wait for
834 * reexecution to finish */
835 r
= sd_bus_request_name_async(bus
, NULL
, "org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING
|SD_BUS_NAME_ALLOW_REPLACEMENT
, NULL
, NULL
);
837 return log_error_errno(r
, "Failed to request name: %m");
839 r
= manager_sync_bus_names(m
, bus
);
843 log_debug("Successfully connected to API bus.");
847 static int bus_init_api(Manager
*m
) {
848 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
854 /* The API and system bus is the same if we are running in system mode */
855 if (MANAGER_IS_SYSTEM(m
) && m
->system_bus
)
856 bus
= sd_bus_ref(m
->system_bus
);
858 if (MANAGER_IS_SYSTEM(m
))
859 r
= sd_bus_open_system(&bus
);
861 r
= sd_bus_open_user(&bus
);
863 log_debug("Failed to connect to API bus, retrying later...");
867 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
869 log_error_errno(r
, "Failed to attach API bus to event loop: %m");
873 r
= bus_setup_disconnected_match(m
, bus
);
878 r
= bus_setup_api(m
, bus
);
880 log_error_errno(r
, "Failed to set up API bus: %m");
890 static int bus_setup_system(Manager
*m
, sd_bus
*bus
) {
896 /* if we are a user instance we get the Released message via the system bus */
897 if (MANAGER_IS_USER(m
)) {
898 r
= sd_bus_match_signal_async(
902 "/org/freedesktop/systemd1/agent",
903 "org.freedesktop.systemd1.Agent",
905 signal_agent_released
, NULL
, m
);
907 log_warning_errno(r
, "Failed to request Released match on system bus: %m");
910 log_debug("Successfully connected to system bus.");
914 static int bus_init_system(Manager
*m
) {
915 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
921 /* The API and system bus is the same if we are running in system mode */
922 if (MANAGER_IS_SYSTEM(m
) && m
->api_bus
) {
923 m
->system_bus
= sd_bus_ref(m
->api_bus
);
927 r
= sd_bus_open_system(&bus
);
929 log_debug("Failed to connect to system bus, retrying later...");
933 r
= bus_setup_disconnected_match(m
, bus
);
937 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
939 log_error_errno(r
, "Failed to attach system bus to event loop: %m");
943 r
= bus_setup_system(m
, bus
);
945 log_error_errno(r
, "Failed to set up system bus: %m");
955 static int bus_init_private(Manager
*m
) {
956 _cleanup_close_
int fd
= -1;
957 union sockaddr_union sa
= {
958 .un
.sun_family
= AF_UNIX
966 if (m
->private_listen_fd
>= 0)
969 if (MANAGER_IS_SYSTEM(m
)) {
971 /* We want the private bus only when running as init */
972 if (getpid_cached() != 1)
975 strcpy(sa
.un
.sun_path
, "/run/systemd/private");
976 salen
= SOCKADDR_UN_LEN(sa
.un
);
978 size_t left
= sizeof(sa
.un
.sun_path
);
979 char *p
= sa
.un
.sun_path
;
982 e
= secure_getenv("XDG_RUNTIME_DIR");
984 log_error("Failed to determine XDG_RUNTIME_DIR");
988 left
= strpcpy(&p
, left
, e
);
989 left
= strpcpy(&p
, left
, "/systemd/private");
991 salen
= sizeof(sa
.un
) - left
;
994 (void) mkdir_parents_label(sa
.un
.sun_path
, 0755);
995 (void) unlink(sa
.un
.sun_path
);
997 fd
= socket(AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0);
999 return log_error_errno(errno
, "Failed to allocate private socket: %m");
1001 r
= bind(fd
, &sa
.sa
, salen
);
1003 return log_error_errno(errno
, "Failed to bind private socket: %m");
1005 r
= listen(fd
, SOMAXCONN
);
1007 return log_error_errno(errno
, "Failed to make private socket listening: %m");
1009 /* Generate an inotify event in case somebody waits for this socket to appear using inotify() */
1010 (void) touch(sa
.un
.sun_path
);
1012 r
= sd_event_add_io(m
->event
, &s
, fd
, EPOLLIN
, bus_on_connection
, m
);
1014 return log_error_errno(r
, "Failed to allocate event source: %m");
1016 (void) sd_event_source_set_description(s
, "bus-connection");
1018 m
->private_listen_fd
= fd
;
1019 m
->private_listen_event_source
= s
;
1022 log_debug("Successfully created private D-Bus server.");
1027 int bus_init(Manager
*m
, bool try_bus_connect
) {
1030 if (try_bus_connect
) {
1031 r
= bus_init_system(m
);
1035 r
= bus_init_api(m
);
1040 r
= bus_init_private(m
);
1047 static void destroy_bus(Manager
*m
, sd_bus
**bus
) {
1058 /* Make sure all bus slots watching names are released. */
1059 HASHMAP_FOREACH(u
, m
->watch_bus
, i
) {
1060 if (!u
->match_bus_slot
)
1063 if (sd_bus_slot_get_bus(u
->match_bus_slot
) != *bus
)
1066 u
->match_bus_slot
= sd_bus_slot_unref(u
->match_bus_slot
);
1069 /* Get rid of tracked clients on this bus */
1070 if (m
->subscribed
&& sd_bus_track_get_bus(m
->subscribed
) == *bus
)
1071 m
->subscribed
= sd_bus_track_unref(m
->subscribed
);
1073 HASHMAP_FOREACH(j
, m
->jobs
, i
)
1074 if (j
->bus_track
&& sd_bus_track_get_bus(j
->bus_track
) == *bus
)
1075 j
->bus_track
= sd_bus_track_unref(j
->bus_track
);
1077 /* Get rid of queued message on this bus */
1078 if (m
->queued_message
&& sd_bus_message_get_bus(m
->queued_message
) == *bus
)
1079 m
->queued_message
= sd_bus_message_unref(m
->queued_message
);
1081 /* Possibly flush unwritten data, but only if we are
1082 * unprivileged, since we don't want to sync here */
1083 if (!MANAGER_IS_SYSTEM(m
))
1086 /* And destroy the object */
1088 *bus
= sd_bus_unref(*bus
);
1091 void bus_done(Manager
*m
) {
1097 destroy_bus(m
, &m
->api_bus
);
1099 destroy_bus(m
, &m
->system_bus
);
1100 while ((b
= set_steal_first(m
->private_buses
)))
1103 m
->private_buses
= set_free(m
->private_buses
);
1105 m
->subscribed
= sd_bus_track_unref(m
->subscribed
);
1106 m
->deserialized_subscribed
= strv_free(m
->deserialized_subscribed
);
1108 if (m
->private_listen_event_source
)
1109 m
->private_listen_event_source
= sd_event_source_unref(m
->private_listen_event_source
);
1111 m
->private_listen_fd
= safe_close(m
->private_listen_fd
);
1113 bus_verify_polkit_async_registry_free(m
->polkit_registry
);
1116 int bus_fdset_add_all(Manager
*m
, FDSet
*fds
) {
1124 /* When we are about to reexecute we add all D-Bus fds to the
1125 * set to pass over to the newly executed systemd. They won't
1126 * be used there however, except thatt they are closed at the
1127 * very end of deserialization, those making it possible for
1128 * clients to synchronously wait for systemd to reexec by
1129 * simply waiting for disconnection */
1132 fd
= sd_bus_get_fd(m
->api_bus
);
1134 fd
= fdset_put_dup(fds
, fd
);
1140 SET_FOREACH(b
, m
->private_buses
, i
) {
1141 fd
= sd_bus_get_fd(b
);
1143 fd
= fdset_put_dup(fds
, fd
);
1149 /* We don't offer any APIs on the system bus (well, unless it
1150 * is the same as the API bus) hence we don't bother with it
1156 int bus_foreach_bus(
1158 sd_bus_track
*subscribed2
,
1159 int (*send_message
)(sd_bus
*bus
, void *userdata
),
1166 /* Send to all direct buses, unconditionally */
1167 SET_FOREACH(b
, m
->private_buses
, i
) {
1168 r
= send_message(b
, userdata
);
1173 /* Send to API bus, but only if somebody is subscribed */
1174 if (sd_bus_track_count(m
->subscribed
) > 0 ||
1175 sd_bus_track_count(subscribed2
) > 0) {
1176 r
= send_message(m
->api_bus
, userdata
);
1184 void bus_track_serialize(sd_bus_track
*t
, FILE *f
, const char *prefix
) {
1190 for (n
= sd_bus_track_first(t
); n
; n
= sd_bus_track_next(t
)) {
1193 c
= sd_bus_track_count_name(t
, n
);
1195 for (j
= 0; j
< c
; j
++) {
1204 int bus_track_coldplug(Manager
*m
, sd_bus_track
**t
, bool recursive
, char **l
) {
1210 if (strv_isempty(l
))
1217 r
= sd_bus_track_new(m
->api_bus
, t
, NULL
, NULL
);
1222 r
= sd_bus_track_set_recursive(*t
, recursive
);
1226 return bus_track_add_name_many(*t
, l
);
1229 int bus_verify_manage_units_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1230 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.manage-units", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1233 int bus_verify_manage_unit_files_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1234 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.manage-unit-files", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1237 int bus_verify_reload_daemon_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1238 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.reload-daemon", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1241 int bus_verify_set_environment_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1242 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.set-environment", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);