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 return log_error_errno(r
, "Failed to connect to API bus: %m");
865 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
867 return log_error_errno(r
, "Failed to attach API bus to event loop: %m");
869 r
= bus_setup_disconnected_match(m
, bus
);
874 r
= bus_setup_api(m
, bus
);
876 return log_error_errno(r
, "Failed to set up API bus: %m");
884 static int bus_setup_system(Manager
*m
, sd_bus
*bus
) {
890 /* if we are a user instance we get the Released message via the system bus */
891 if (MANAGER_IS_USER(m
)) {
892 r
= sd_bus_match_signal_async(
896 "/org/freedesktop/systemd1/agent",
897 "org.freedesktop.systemd1.Agent",
899 signal_agent_released
, NULL
, m
);
901 log_warning_errno(r
, "Failed to request Released match on system bus: %m");
904 log_debug("Successfully connected to system bus.");
908 static int bus_init_system(Manager
*m
) {
909 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
915 /* The API and system bus is the same if we are running in system mode */
916 if (MANAGER_IS_SYSTEM(m
) && m
->api_bus
) {
917 m
->system_bus
= sd_bus_ref(m
->api_bus
);
921 r
= sd_bus_open_system(&bus
);
923 return log_error_errno(r
, "Failed to connect to system bus: %m");
925 r
= bus_setup_disconnected_match(m
, bus
);
929 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
931 return log_error_errno(r
, "Failed to attach system bus to event loop: %m");
933 r
= bus_setup_system(m
, bus
);
935 return log_error_errno(r
, "Failed to set up system bus: %m");
943 static int bus_init_private(Manager
*m
) {
944 _cleanup_close_
int fd
= -1;
945 union sockaddr_union sa
= {
946 .un
.sun_family
= AF_UNIX
954 if (m
->private_listen_fd
>= 0)
957 if (MANAGER_IS_SYSTEM(m
)) {
959 /* We want the private bus only when running as init */
960 if (getpid_cached() != 1)
963 strcpy(sa
.un
.sun_path
, "/run/systemd/private");
964 salen
= SOCKADDR_UN_LEN(sa
.un
);
966 size_t left
= sizeof(sa
.un
.sun_path
);
967 char *p
= sa
.un
.sun_path
;
970 e
= secure_getenv("XDG_RUNTIME_DIR");
972 log_error("Failed to determine XDG_RUNTIME_DIR");
976 left
= strpcpy(&p
, left
, e
);
977 left
= strpcpy(&p
, left
, "/systemd/private");
979 salen
= sizeof(sa
.un
) - left
;
982 (void) mkdir_parents_label(sa
.un
.sun_path
, 0755);
983 (void) unlink(sa
.un
.sun_path
);
985 fd
= socket(AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0);
987 return log_error_errno(errno
, "Failed to allocate private socket: %m");
989 r
= bind(fd
, &sa
.sa
, salen
);
991 return log_error_errno(errno
, "Failed to bind private socket: %m");
993 r
= listen(fd
, SOMAXCONN
);
995 return log_error_errno(errno
, "Failed to make private socket listening: %m");
997 /* Generate an inotify event in case somebody waits for this socket to appear using inotify() */
998 (void) touch(sa
.un
.sun_path
);
1000 r
= sd_event_add_io(m
->event
, &s
, fd
, EPOLLIN
, bus_on_connection
, m
);
1002 return log_error_errno(r
, "Failed to allocate event source: %m");
1004 (void) sd_event_source_set_description(s
, "bus-connection");
1006 m
->private_listen_fd
= fd
;
1007 m
->private_listen_event_source
= s
;
1010 log_debug("Successfully created private D-Bus server.");
1015 int bus_init(Manager
*m
, bool try_bus_connect
) {
1018 if (try_bus_connect
) {
1019 r
= bus_init_system(m
);
1021 return log_error_errno(r
, "Failed to initialize D-Bus connection: %m");
1023 r
= bus_init_api(m
);
1025 return log_error_errno(r
, "Error occured during D-Bus APIs initialization: %m");
1028 r
= bus_init_private(m
);
1030 return log_error_errno(r
, "Failed to create private D-Bus server: %m");
1035 static void destroy_bus(Manager
*m
, sd_bus
**bus
) {
1046 /* Make sure all bus slots watching names are released. */
1047 HASHMAP_FOREACH(u
, m
->watch_bus
, i
) {
1048 if (!u
->match_bus_slot
)
1051 if (sd_bus_slot_get_bus(u
->match_bus_slot
) != *bus
)
1054 u
->match_bus_slot
= sd_bus_slot_unref(u
->match_bus_slot
);
1057 /* Get rid of tracked clients on this bus */
1058 if (m
->subscribed
&& sd_bus_track_get_bus(m
->subscribed
) == *bus
)
1059 m
->subscribed
= sd_bus_track_unref(m
->subscribed
);
1061 HASHMAP_FOREACH(j
, m
->jobs
, i
)
1062 if (j
->bus_track
&& sd_bus_track_get_bus(j
->bus_track
) == *bus
)
1063 j
->bus_track
= sd_bus_track_unref(j
->bus_track
);
1065 /* Get rid of queued message on this bus */
1066 if (m
->queued_message
&& sd_bus_message_get_bus(m
->queued_message
) == *bus
)
1067 m
->queued_message
= sd_bus_message_unref(m
->queued_message
);
1069 /* Possibly flush unwritten data, but only if we are
1070 * unprivileged, since we don't want to sync here */
1071 if (!MANAGER_IS_SYSTEM(m
))
1074 /* And destroy the object */
1076 *bus
= sd_bus_unref(*bus
);
1079 void bus_done(Manager
*m
) {
1085 destroy_bus(m
, &m
->api_bus
);
1087 destroy_bus(m
, &m
->system_bus
);
1088 while ((b
= set_steal_first(m
->private_buses
)))
1091 m
->private_buses
= set_free(m
->private_buses
);
1093 m
->subscribed
= sd_bus_track_unref(m
->subscribed
);
1094 m
->deserialized_subscribed
= strv_free(m
->deserialized_subscribed
);
1096 if (m
->private_listen_event_source
)
1097 m
->private_listen_event_source
= sd_event_source_unref(m
->private_listen_event_source
);
1099 m
->private_listen_fd
= safe_close(m
->private_listen_fd
);
1101 bus_verify_polkit_async_registry_free(m
->polkit_registry
);
1104 int bus_fdset_add_all(Manager
*m
, FDSet
*fds
) {
1112 /* When we are about to reexecute we add all D-Bus fds to the
1113 * set to pass over to the newly executed systemd. They won't
1114 * be used there however, except thatt they are closed at the
1115 * very end of deserialization, those making it possible for
1116 * clients to synchronously wait for systemd to reexec by
1117 * simply waiting for disconnection */
1120 fd
= sd_bus_get_fd(m
->api_bus
);
1122 fd
= fdset_put_dup(fds
, fd
);
1128 SET_FOREACH(b
, m
->private_buses
, i
) {
1129 fd
= sd_bus_get_fd(b
);
1131 fd
= fdset_put_dup(fds
, fd
);
1137 /* We don't offer any APIs on the system bus (well, unless it
1138 * is the same as the API bus) hence we don't bother with it
1144 int bus_foreach_bus(
1146 sd_bus_track
*subscribed2
,
1147 int (*send_message
)(sd_bus
*bus
, void *userdata
),
1154 /* Send to all direct buses, unconditionally */
1155 SET_FOREACH(b
, m
->private_buses
, i
) {
1156 r
= send_message(b
, userdata
);
1161 /* Send to API bus, but only if somebody is subscribed */
1162 if (sd_bus_track_count(m
->subscribed
) > 0 ||
1163 sd_bus_track_count(subscribed2
) > 0) {
1164 r
= send_message(m
->api_bus
, userdata
);
1172 void bus_track_serialize(sd_bus_track
*t
, FILE *f
, const char *prefix
) {
1178 for (n
= sd_bus_track_first(t
); n
; n
= sd_bus_track_next(t
)) {
1181 c
= sd_bus_track_count_name(t
, n
);
1183 for (j
= 0; j
< c
; j
++) {
1192 int bus_track_coldplug(Manager
*m
, sd_bus_track
**t
, bool recursive
, char **l
) {
1198 if (strv_isempty(l
))
1205 r
= sd_bus_track_new(m
->api_bus
, t
, NULL
, NULL
);
1210 r
= sd_bus_track_set_recursive(*t
, recursive
);
1214 return bus_track_add_name_many(*t
, l
);
1217 int bus_verify_manage_units_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1218 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.manage-units", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1221 int bus_verify_manage_unit_files_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1222 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.manage-unit-files", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1225 int bus_verify_reload_daemon_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1226 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.reload-daemon", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1229 int bus_verify_set_environment_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1230 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.set-environment", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);