1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/epoll.h>
28 #include "alloc-util.h"
29 #include "bus-common-errors.h"
30 #include "bus-error.h"
31 #include "bus-internal.h"
33 #include "dbus-cgroup.h"
34 #include "dbus-execute.h"
36 #include "dbus-kill.h"
37 #include "dbus-manager.h"
38 #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 static int signal_agent_released(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
77 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
78 const char *cgroup
, *me
;
79 Manager
*m
= userdata
;
87 /* ignore recursive events sent by us on the system/user bus */
88 bus
= sd_bus_message_get_bus(message
);
89 if (!sd_bus_is_server(bus
)) {
90 r
= sd_bus_get_unique_name(bus
, &me
);
94 if (streq_ptr(sd_bus_message_get_sender(message
), me
))
98 /* only accept org.freedesktop.systemd1.Agent from UID=0 */
99 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
103 r
= sd_bus_creds_get_euid(creds
, &sender_uid
);
104 if (r
< 0 || sender_uid
!= 0)
107 /* parse 'cgroup-empty' notification */
108 r
= sd_bus_message_read(message
, "s", &cgroup
);
110 bus_log_parse_error(r
);
114 manager_notify_cgroup_empty(m
, cgroup
);
116 /* if running as system-instance, forward under our name */
117 if (m
->running_as
== MANAGER_SYSTEM
&& m
->system_bus
) {
118 r
= sd_bus_message_rewind(message
, 1);
120 r
= sd_bus_send(m
->system_bus
, message
, NULL
);
122 log_warning_errno(r
, "Failed to forward Released message: %m");
128 static int signal_disconnected(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
129 Manager
*m
= userdata
;
134 assert_se(bus
= sd_bus_message_get_bus(message
));
136 if (bus
== m
->api_bus
)
137 destroy_bus(m
, &m
->api_bus
);
138 if (bus
== m
->system_bus
)
139 destroy_bus(m
, &m
->system_bus
);
140 if (set_remove(m
->private_buses
, bus
)) {
141 log_debug("Got disconnect on private connection.");
142 destroy_bus(m
, &bus
);
148 static int signal_activation_request(sd_bus_message
*message
, void *userdata
, sd_bus_error
*ret_error
) {
149 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
150 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
151 Manager
*m
= userdata
;
159 r
= sd_bus_message_read(message
, "s", &name
);
161 bus_log_parse_error(r
);
165 if (manager_unit_inactive_or_pending(m
, SPECIAL_DBUS_SERVICE
) ||
166 manager_unit_inactive_or_pending(m
, SPECIAL_DBUS_SOCKET
)) {
167 r
= sd_bus_error_setf(&error
, BUS_ERROR_SHUTTING_DOWN
, "Refusing activation, D-Bus is shutting down.");
171 r
= manager_load_unit(m
, name
, NULL
, &error
, &u
);
175 if (u
->refuse_manual_start
) {
176 r
= sd_bus_error_setf(&error
, BUS_ERROR_ONLY_BY_DEPENDENCY
, "Operation refused, %s may be requested by dependency only.", u
->id
);
180 r
= manager_add_job(m
, JOB_START
, u
, JOB_REPLACE
, &error
, NULL
);
184 /* Successfully queued, that's it for us */
188 if (!sd_bus_error_is_set(&error
))
189 sd_bus_error_set_errno(&error
, r
);
191 log_debug("D-Bus activation failed for %s: %s", name
, bus_error_message(&error
, r
));
193 r
= sd_bus_message_new_signal(sd_bus_message_get_bus(message
), &reply
, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
195 bus_log_create_error(r
);
199 r
= sd_bus_message_append(reply
, "sss", name
, error
.name
, error
.message
);
201 bus_log_create_error(r
);
205 r
= sd_bus_send_to(NULL
, reply
, "org.freedesktop.DBus", NULL
);
207 return log_error_errno(r
, "Failed to respond with to bus activation request: %m");
213 static int mac_selinux_filter(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
214 Manager
*m
= userdata
;
215 const char *verb
, *path
;
222 /* Our own method calls are all protected individually with
223 * selinux checks, but the built-in interfaces need to be
226 if (sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Properties", "Set"))
228 else if (sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Introspectable", NULL
) ||
229 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Properties", NULL
) ||
230 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.ObjectManager", NULL
) ||
231 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Peer", NULL
))
236 path
= sd_bus_message_get_path(message
);
238 if (object_path_startswith("/org/freedesktop/systemd1", path
)) {
240 r
= mac_selinux_access_check(message
, verb
, error
);
247 if (streq_ptr(path
, "/org/freedesktop/systemd1/unit/self")) {
248 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
251 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
255 r
= sd_bus_creds_get_pid(creds
, &pid
);
259 u
= manager_get_unit_by_pid(m
, pid
);
261 r
= manager_get_job_from_dbus_path(m
, path
, &j
);
265 manager_load_unit_from_dbus_path(m
, path
, NULL
, &u
);
271 r
= mac_selinux_unit_access_check(u
, message
, verb
, error
);
279 static int bus_job_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
280 Manager
*m
= userdata
;
290 r
= manager_get_job_from_dbus_path(m
, path
, &j
);
298 static int find_unit(Manager
*m
, sd_bus
*bus
, const char *path
, Unit
**unit
, sd_bus_error
*error
) {
306 if (streq_ptr(path
, "/org/freedesktop/systemd1/unit/self")) {
307 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
308 sd_bus_message
*message
;
311 message
= sd_bus_get_current_message(bus
);
315 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
319 r
= sd_bus_creds_get_pid(creds
, &pid
);
323 u
= manager_get_unit_by_pid(m
, pid
);
325 r
= manager_load_unit_from_dbus_path(m
, path
, error
, &u
);
337 static int bus_unit_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
338 Manager
*m
= userdata
;
346 return find_unit(m
, bus
, path
, (Unit
**) found
, error
);
349 static int bus_unit_interface_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
350 Manager
*m
= userdata
;
360 r
= find_unit(m
, bus
, path
, &u
, error
);
364 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
371 static int bus_unit_cgroup_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
372 Manager
*m
= userdata
;
382 r
= find_unit(m
, bus
, path
, &u
, error
);
386 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
389 if (!UNIT_HAS_CGROUP_CONTEXT(u
))
396 static int bus_cgroup_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
397 Manager
*m
= userdata
;
408 r
= find_unit(m
, bus
, path
, &u
, error
);
412 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
415 c
= unit_get_cgroup_context(u
);
423 static int bus_exec_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
424 Manager
*m
= userdata
;
435 r
= find_unit(m
, bus
, path
, &u
, error
);
439 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
442 c
= unit_get_exec_context(u
);
450 static int bus_kill_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
451 Manager
*m
= userdata
;
462 r
= find_unit(m
, bus
, path
, &u
, error
);
466 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
469 c
= unit_get_kill_context(u
);
477 static int bus_job_enumerate(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
478 _cleanup_free_
char **l
= NULL
;
479 Manager
*m
= userdata
;
484 l
= new0(char*, hashmap_size(m
->jobs
)+1);
488 HASHMAP_FOREACH(j
, m
->jobs
, i
) {
489 l
[k
] = job_dbus_path(j
);
496 assert(hashmap_size(m
->jobs
) == k
);
504 static int bus_unit_enumerate(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
505 _cleanup_free_
char **l
= NULL
;
506 Manager
*m
= userdata
;
511 l
= new0(char*, hashmap_size(m
->units
)+1);
515 HASHMAP_FOREACH(u
, m
->units
, i
) {
516 l
[k
] = unit_dbus_path(u
);
529 static int bus_setup_api_vtables(Manager
*m
, sd_bus
*bus
) {
537 r
= sd_bus_add_filter(bus
, NULL
, mac_selinux_filter
, m
);
539 return log_error_errno(r
, "Failed to add SELinux access filter: %m");
542 r
= sd_bus_add_object_vtable(bus
, NULL
, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable
, m
);
544 return log_error_errno(r
, "Failed to register Manager vtable: %m");
546 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable
, bus_job_find
, m
);
548 return log_error_errno(r
, "Failed to register Job vtable: %m");
550 r
= sd_bus_add_node_enumerator(bus
, NULL
, "/org/freedesktop/systemd1/job", bus_job_enumerate
, m
);
552 return log_error_errno(r
, "Failed to add job enumerator: %m");
554 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable
, bus_unit_find
, m
);
556 return log_error_errno(r
, "Failed to register Unit vtable: %m");
558 r
= sd_bus_add_node_enumerator(bus
, NULL
, "/org/freedesktop/systemd1/unit", bus_unit_enumerate
, m
);
560 return log_error_errno(r
, "Failed to add job enumerator: %m");
562 for (t
= 0; t
< _UNIT_TYPE_MAX
; t
++) {
563 const char *interface
;
565 assert_se(interface
= unit_dbus_interface_from_type(t
));
567 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, unit_vtable
[t
]->bus_vtable
, bus_unit_interface_find
, m
);
569 return log_error_errno(r
, "Failed to register type specific vtable for %s: %m", interface
);
571 if (unit_vtable
[t
]->cgroup_context_offset
> 0) {
572 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_unit_cgroup_vtable
, bus_unit_cgroup_find
, m
);
574 return log_error_errno(r
, "Failed to register control group unit vtable for %s: %m", interface
);
576 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_cgroup_vtable
, bus_cgroup_context_find
, m
);
578 return log_error_errno(r
, "Failed to register control group vtable for %s: %m", interface
);
581 if (unit_vtable
[t
]->exec_context_offset
> 0) {
582 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_exec_vtable
, bus_exec_context_find
, m
);
584 return log_error_errno(r
, "Failed to register execute vtable for %s: %m", interface
);
587 if (unit_vtable
[t
]->kill_context_offset
> 0) {
588 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_kill_vtable
, bus_kill_context_find
, m
);
590 return log_error_errno(r
, "Failed to register kill vtable for %s: %m", interface
);
597 static int bus_setup_disconnected_match(Manager
*m
, sd_bus
*bus
) {
603 r
= sd_bus_add_match(
606 "sender='org.freedesktop.DBus.Local',"
608 "path='/org/freedesktop/DBus/Local',"
609 "interface='org.freedesktop.DBus.Local',"
610 "member='Disconnected'",
611 signal_disconnected
, m
);
614 return log_error_errno(r
, "Failed to register match for Disconnected message: %m");
619 static int bus_on_connection(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
620 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
621 _cleanup_close_
int nfd
= -1;
622 Manager
*m
= userdata
;
629 nfd
= accept4(fd
, NULL
, NULL
, SOCK_NONBLOCK
|SOCK_CLOEXEC
);
631 log_warning_errno(errno
, "Failed to accept private connection, ignoring: %m");
635 if (set_size(m
->private_buses
) >= CONNECTIONS_MAX
) {
636 log_warning("Too many concurrent connections, refusing");
640 r
= set_ensure_allocated(&m
->private_buses
, NULL
);
646 r
= sd_bus_new(&bus
);
648 log_warning_errno(r
, "Failed to allocate new private connection bus: %m");
652 r
= sd_bus_set_fd(bus
, nfd
, nfd
);
654 log_warning_errno(r
, "Failed to set fd on new connection bus: %m");
660 r
= bus_check_peercred(bus
);
662 log_warning_errno(r
, "Incoming private connection from unprivileged client, refusing: %m");
666 assert_se(sd_id128_randomize(&id
) >= 0);
668 r
= sd_bus_set_server(bus
, 1, id
);
670 log_warning_errno(r
, "Failed to enable server support for new connection bus: %m");
674 r
= sd_bus_negotiate_creds(bus
, 1,
675 SD_BUS_CREDS_PID
|SD_BUS_CREDS_UID
|
676 SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EFFECTIVE_CAPS
|
677 SD_BUS_CREDS_SELINUX_CONTEXT
);
679 log_warning_errno(r
, "Failed to enable credentials for new connection: %m");
683 r
= sd_bus_start(bus
);
685 log_warning_errno(r
, "Failed to start new connection bus: %m");
689 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
691 log_warning_errno(r
, "Failed to attach new connection bus to event loop: %m");
695 if (m
->running_as
== MANAGER_SYSTEM
) {
696 /* When we run as system instance we get the Released
697 * signal via a direct connection */
699 r
= sd_bus_add_match(
703 "interface='org.freedesktop.systemd1.Agent',"
705 "path='/org/freedesktop/systemd1/agent'",
706 signal_agent_released
, m
);
709 log_warning_errno(r
, "Failed to register Released match on new connection bus: %m");
714 r
= bus_setup_disconnected_match(m
, bus
);
718 r
= bus_setup_api_vtables(m
, bus
);
720 log_warning_errno(r
, "Failed to set up API vtables on new connection bus: %m");
724 r
= set_put(m
->private_buses
, bus
);
726 log_warning_errno(r
, "Failed to add new connection bus to set: %m");
732 log_debug("Accepted new private connection.");
737 int manager_sync_bus_names(Manager
*m
, sd_bus
*bus
) {
738 _cleanup_strv_free_
char **names
= NULL
;
747 r
= sd_bus_list_names(bus
, &names
, NULL
);
749 return log_error_errno(r
, "Failed to get initial list of names: %m");
751 /* We have to synchronize the current bus names with the
752 * list of active services. To do this, walk the list of
753 * all units with bus names. */
754 HASHMAP_FOREACH_KEY(u
, name
, m
->watch_bus
, i
) {
755 Service
*s
= SERVICE(u
);
759 if (!streq_ptr(s
->bus_name
, name
)) {
760 log_unit_warning(u
, "Bus name has changed from %s → %s, ignoring.", s
->bus_name
, name
);
764 /* Check if a service's bus name is in the list of currently
766 if (strv_contains(names
, name
)) {
767 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
770 /* If it is, determine its current owner */
771 r
= sd_bus_get_name_creds(bus
, name
, SD_BUS_CREDS_UNIQUE_NAME
, &creds
);
773 log_error_errno(r
, "Failed to get bus name owner %s: %m", name
);
777 r
= sd_bus_creds_get_unique_name(creds
, &unique
);
779 log_error_errno(r
, "Failed to get unique name for %s: %m", name
);
783 /* Now, let's compare that to the previous bus owner, and
784 * if it's still the same, all is fine, so just don't
785 * bother the service. Otherwise, the name has apparently
786 * changed, so synthesize a name owner changed signal. */
788 if (!streq_ptr(unique
, s
->bus_name_owner
))
789 UNIT_VTABLE(u
)->bus_name_owner_change(u
, name
, s
->bus_name_owner
, unique
);
791 /* So, the name we're watching is not on the bus.
792 * This either means it simply hasn't appeared yet,
793 * or it was lost during the daemon reload.
794 * Check if the service has a stored name owner,
795 * and synthesize a name loss signal in this case. */
797 if (s
->bus_name_owner
)
798 UNIT_VTABLE(u
)->bus_name_owner_change(u
, name
, s
->bus_name_owner
, NULL
);
805 static int bus_setup_api(Manager
*m
, sd_bus
*bus
) {
814 /* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
815 r
= sd_bus_negotiate_creds(bus
, 1,
816 SD_BUS_CREDS_PID
|SD_BUS_CREDS_UID
|
817 SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EFFECTIVE_CAPS
|
818 SD_BUS_CREDS_SELINUX_CONTEXT
);
820 log_warning_errno(r
, "Failed to enable credential passing, ignoring: %m");
822 r
= bus_setup_api_vtables(m
, bus
);
826 HASHMAP_FOREACH_KEY(u
, name
, m
->watch_bus
, i
) {
827 r
= unit_install_bus_match(u
, bus
, name
);
829 log_error_errno(r
, "Failed to subscribe to NameOwnerChanged signal for '%s': %m", name
);
832 r
= sd_bus_add_match(
836 "sender='org.freedesktop.DBus',"
837 "path='/org/freedesktop/DBus',"
838 "interface='org.freedesktop.systemd1.Activator',"
839 "member='ActivationRequest'",
840 signal_activation_request
, m
);
842 log_warning_errno(r
, "Failed to subscribe to activation signal: %m");
844 /* Allow replacing of our name, to ease implementation of
845 * reexecution, where we keep the old connection open until
846 * after the new connection is set up and the name installed
847 * to allow clients to synchronously wait for reexecution to
849 r
= sd_bus_request_name(bus
,"org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING
|SD_BUS_NAME_ALLOW_REPLACEMENT
);
851 return log_error_errno(r
, "Failed to register name: %m");
853 r
= manager_sync_bus_names(m
, bus
);
857 log_debug("Successfully connected to API bus.");
861 static int bus_init_api(Manager
*m
) {
862 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
868 /* The API and system bus is the same if we are running in system mode */
869 if (m
->running_as
== MANAGER_SYSTEM
&& m
->system_bus
)
870 bus
= sd_bus_ref(m
->system_bus
);
872 if (m
->running_as
== MANAGER_SYSTEM
)
873 r
= sd_bus_open_system(&bus
);
875 r
= sd_bus_open_user(&bus
);
878 log_debug("Failed to connect to API bus, retrying later...");
882 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
884 log_error_errno(r
, "Failed to attach API bus to event loop: %m");
888 r
= bus_setup_disconnected_match(m
, bus
);
893 r
= bus_setup_api(m
, bus
);
895 log_error_errno(r
, "Failed to set up API bus: %m");
905 static int bus_setup_system(Manager
*m
, sd_bus
*bus
) {
911 /* On kdbus or if we are a user instance we get the Released message via the system bus */
912 if (m
->running_as
== MANAGER_USER
|| m
->kdbus_fd
>= 0) {
913 r
= sd_bus_add_match(
917 "interface='org.freedesktop.systemd1.Agent',"
919 "path='/org/freedesktop/systemd1/agent'",
920 signal_agent_released
, m
);
922 log_warning_errno(r
, "Failed to register Released match on system bus: %m");
925 log_debug("Successfully connected to system bus.");
929 static int bus_init_system(Manager
*m
) {
930 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
936 /* The API and system bus is the same if we are running in system mode */
937 if (m
->running_as
== MANAGER_SYSTEM
&& m
->api_bus
) {
938 m
->system_bus
= sd_bus_ref(m
->api_bus
);
942 r
= sd_bus_open_system(&bus
);
944 log_debug("Failed to connect to system bus, retrying later...");
948 r
= bus_setup_disconnected_match(m
, bus
);
952 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
954 log_error_errno(r
, "Failed to attach system bus to event loop: %m");
958 r
= bus_setup_system(m
, bus
);
960 log_error_errno(r
, "Failed to set up system bus: %m");
970 static int bus_init_private(Manager
*m
) {
971 _cleanup_close_
int fd
= -1;
972 union sockaddr_union sa
= {
973 .un
.sun_family
= AF_UNIX
981 if (m
->private_listen_fd
>= 0)
984 /* We don't need the private socket if we have kdbus */
985 if (m
->kdbus_fd
>= 0)
988 if (m
->running_as
== MANAGER_SYSTEM
) {
990 /* We want the private bus only when running as init */
994 strcpy(sa
.un
.sun_path
, "/run/systemd/private");
995 salen
= offsetof(union sockaddr_union
, un
.sun_path
) + strlen("/run/systemd/private");
997 size_t left
= sizeof(sa
.un
.sun_path
);
998 char *p
= sa
.un
.sun_path
;
1001 e
= secure_getenv("XDG_RUNTIME_DIR");
1003 log_error("Failed to determine XDG_RUNTIME_DIR");
1007 left
= strpcpy(&p
, left
, e
);
1008 left
= strpcpy(&p
, left
, "/systemd/private");
1010 salen
= sizeof(sa
.un
) - left
;
1013 (void) mkdir_parents_label(sa
.un
.sun_path
, 0755);
1014 (void) unlink(sa
.un
.sun_path
);
1016 fd
= socket(AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0);
1018 return log_error_errno(errno
, "Failed to allocate private socket: %m");
1020 r
= bind(fd
, &sa
.sa
, salen
);
1022 return log_error_errno(errno
, "Failed to bind private socket: %m");
1024 r
= listen(fd
, SOMAXCONN
);
1026 return log_error_errno(errno
, "Failed to make private socket listening: %m");
1028 r
= sd_event_add_io(m
->event
, &s
, fd
, EPOLLIN
, bus_on_connection
, m
);
1030 return log_error_errno(r
, "Failed to allocate event source: %m");
1032 (void) sd_event_source_set_description(s
, "bus-connection");
1034 m
->private_listen_fd
= fd
;
1035 m
->private_listen_event_source
= s
;
1038 log_debug("Successfully created private D-Bus server.");
1043 int bus_init(Manager
*m
, bool try_bus_connect
) {
1046 if (try_bus_connect
) {
1047 r
= bus_init_system(m
);
1051 r
= bus_init_api(m
);
1056 r
= bus_init_private(m
);
1063 static void destroy_bus(Manager
*m
, sd_bus
**bus
) {
1073 /* Get rid of tracked clients on this bus */
1074 if (m
->subscribed
&& sd_bus_track_get_bus(m
->subscribed
) == *bus
)
1075 m
->subscribed
= sd_bus_track_unref(m
->subscribed
);
1077 HASHMAP_FOREACH(j
, m
->jobs
, i
)
1078 if (j
->clients
&& sd_bus_track_get_bus(j
->clients
) == *bus
)
1079 j
->clients
= sd_bus_track_unref(j
->clients
);
1081 /* Get rid of queued message on this bus */
1082 if (m
->queued_message
&& sd_bus_message_get_bus(m
->queued_message
) == *bus
)
1083 m
->queued_message
= sd_bus_message_unref(m
->queued_message
);
1085 /* Possibly flush unwritten data, but only if we are
1086 * unprivileged, since we don't want to sync here */
1087 if (m
->running_as
!= MANAGER_SYSTEM
)
1090 /* And destroy the object */
1092 *bus
= sd_bus_unref(*bus
);
1095 void bus_done(Manager
*m
) {
1101 destroy_bus(m
, &m
->api_bus
);
1103 destroy_bus(m
, &m
->system_bus
);
1104 while ((b
= set_steal_first(m
->private_buses
)))
1107 m
->private_buses
= set_free(m
->private_buses
);
1109 m
->subscribed
= sd_bus_track_unref(m
->subscribed
);
1110 m
->deserialized_subscribed
= strv_free(m
->deserialized_subscribed
);
1112 if (m
->private_listen_event_source
)
1113 m
->private_listen_event_source
= sd_event_source_unref(m
->private_listen_event_source
);
1115 m
->private_listen_fd
= safe_close(m
->private_listen_fd
);
1117 bus_verify_polkit_async_registry_free(m
->polkit_registry
);
1120 int bus_fdset_add_all(Manager
*m
, FDSet
*fds
) {
1128 /* When we are about to reexecute we add all D-Bus fds to the
1129 * set to pass over to the newly executed systemd. They won't
1130 * be used there however, except thatt they are closed at the
1131 * very end of deserialization, those making it possible for
1132 * clients to synchronously wait for systemd to reexec by
1133 * simply waiting for disconnection */
1136 fd
= sd_bus_get_fd(m
->api_bus
);
1138 fd
= fdset_put_dup(fds
, fd
);
1144 SET_FOREACH(b
, m
->private_buses
, i
) {
1145 fd
= sd_bus_get_fd(b
);
1147 fd
= fdset_put_dup(fds
, fd
);
1153 /* We don't offer any APIs on the system bus (well, unless it
1154 * is the same as the API bus) hence we don't bother with it
1160 int bus_foreach_bus(
1162 sd_bus_track
*subscribed2
,
1163 int (*send_message
)(sd_bus
*bus
, void *userdata
),
1170 /* Send to all direct buses, unconditionally */
1171 SET_FOREACH(b
, m
->private_buses
, i
) {
1172 r
= send_message(b
, userdata
);
1177 /* Send to API bus, but only if somebody is subscribed */
1178 if (sd_bus_track_count(m
->subscribed
) > 0 ||
1179 sd_bus_track_count(subscribed2
) > 0) {
1180 r
= send_message(m
->api_bus
, userdata
);
1188 void bus_track_serialize(sd_bus_track
*t
, FILE *f
) {
1193 for (n
= sd_bus_track_first(t
); n
; n
= sd_bus_track_next(t
))
1194 fprintf(f
, "subscribed=%s\n", n
);
1197 int bus_track_deserialize_item(char ***l
, const char *line
) {
1204 e
= startswith(line
, "subscribed=");
1208 r
= strv_extend(l
, e
);
1215 int bus_track_coldplug(Manager
*m
, sd_bus_track
**t
, char ***l
) {
1222 if (!strv_isempty(*l
) && m
->api_bus
) {
1226 r
= sd_bus_track_new(m
->api_bus
, t
, NULL
, NULL
);
1232 STRV_FOREACH(i
, *l
) {
1235 k
= sd_bus_track_add_name(*t
, *i
);
1246 int bus_verify_manage_units_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1247 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.manage-units", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1250 int bus_verify_manage_unit_files_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1251 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.manage-unit-files", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1254 int bus_verify_reload_daemon_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1255 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.reload-daemon", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1258 int bus_verify_set_environment_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1259 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.set-environment", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);