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"
43 #include "selinux-access.h"
45 #include "string-util.h"
48 #include "user-util.h"
50 #define CONNECTIONS_MAX 4096
52 static void destroy_bus(Manager
*m
, sd_bus
**bus
);
54 int bus_send_queued_message(Manager
*m
) {
59 if (!m
->queued_message
)
62 /* If we cannot get rid of this message we won't dispatch any
63 * D-Bus messages, so that we won't end up wanting to queue
66 r
= sd_bus_send(NULL
, m
->queued_message
, NULL
);
68 log_warning_errno(r
, "Failed to send queued message: %m");
70 m
->queued_message
= sd_bus_message_unref(m
->queued_message
);
75 int bus_forward_agent_released(Manager
*m
, const char *path
) {
81 if (!MANAGER_IS_SYSTEM(m
))
87 /* If we are running a system instance we forward the agent message on the system bus, so that the user
88 * instances get notified about this, too */
90 r
= sd_bus_emit_signal(m
->system_bus
,
91 "/org/freedesktop/systemd1/agent",
92 "org.freedesktop.systemd1.Agent",
96 return log_debug_errno(r
, "Failed to propagate agent release message: %m");
101 static int signal_agent_released(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
102 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
103 Manager
*m
= userdata
;
111 /* only accept org.freedesktop.systemd1.Agent from UID=0 */
112 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
116 r
= sd_bus_creds_get_euid(creds
, &sender_uid
);
117 if (r
< 0 || sender_uid
!= 0)
120 /* parse 'cgroup-empty' notification */
121 r
= sd_bus_message_read(message
, "s", &cgroup
);
123 bus_log_parse_error(r
);
127 manager_notify_cgroup_empty(m
, cgroup
);
131 static int signal_disconnected(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
132 Manager
*m
= userdata
;
137 assert_se(bus
= sd_bus_message_get_bus(message
));
139 if (bus
== m
->api_bus
)
140 destroy_bus(m
, &m
->api_bus
);
141 if (bus
== m
->system_bus
)
142 destroy_bus(m
, &m
->system_bus
);
143 if (set_remove(m
->private_buses
, bus
)) {
144 log_debug("Got disconnect on private connection.");
145 destroy_bus(m
, &bus
);
151 static int signal_activation_request(sd_bus_message
*message
, void *userdata
, sd_bus_error
*ret_error
) {
152 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
153 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
154 Manager
*m
= userdata
;
162 r
= sd_bus_message_read(message
, "s", &name
);
164 bus_log_parse_error(r
);
168 if (manager_unit_inactive_or_pending(m
, SPECIAL_DBUS_SERVICE
) ||
169 manager_unit_inactive_or_pending(m
, SPECIAL_DBUS_SOCKET
)) {
170 r
= sd_bus_error_setf(&error
, BUS_ERROR_SHUTTING_DOWN
, "Refusing activation, D-Bus is shutting down.");
174 r
= manager_load_unit(m
, name
, NULL
, &error
, &u
);
178 if (u
->refuse_manual_start
) {
179 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
);
183 r
= manager_add_job(m
, JOB_START
, u
, JOB_REPLACE
, &error
, NULL
);
187 /* Successfully queued, that's it for us */
191 if (!sd_bus_error_is_set(&error
))
192 sd_bus_error_set_errno(&error
, r
);
194 log_debug("D-Bus activation failed for %s: %s", name
, bus_error_message(&error
, r
));
196 r
= sd_bus_message_new_signal(sd_bus_message_get_bus(message
), &reply
, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
198 bus_log_create_error(r
);
202 r
= sd_bus_message_append(reply
, "sss", name
, error
.name
, error
.message
);
204 bus_log_create_error(r
);
208 r
= sd_bus_send_to(NULL
, reply
, "org.freedesktop.DBus", NULL
);
210 return log_error_errno(r
, "Failed to respond with to bus activation request: %m");
216 static int mac_selinux_filter(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
217 Manager
*m
= userdata
;
218 const char *verb
, *path
;
225 /* Our own method calls are all protected individually with
226 * selinux checks, but the built-in interfaces need to be
229 if (sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Properties", "Set"))
231 else if (sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Introspectable", NULL
) ||
232 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Properties", NULL
) ||
233 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.ObjectManager", NULL
) ||
234 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Peer", NULL
))
239 path
= sd_bus_message_get_path(message
);
241 if (object_path_startswith("/org/freedesktop/systemd1", path
)) {
243 r
= mac_selinux_access_check(message
, verb
, error
);
250 if (streq_ptr(path
, "/org/freedesktop/systemd1/unit/self")) {
251 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
254 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
258 r
= sd_bus_creds_get_pid(creds
, &pid
);
262 u
= manager_get_unit_by_pid(m
, pid
);
264 r
= manager_get_job_from_dbus_path(m
, path
, &j
);
268 manager_load_unit_from_dbus_path(m
, path
, NULL
, &u
);
274 r
= mac_selinux_unit_access_check(u
, message
, verb
, error
);
282 static int bus_job_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
283 Manager
*m
= userdata
;
293 r
= manager_get_job_from_dbus_path(m
, path
, &j
);
301 static int find_unit(Manager
*m
, sd_bus
*bus
, const char *path
, Unit
**unit
, sd_bus_error
*error
) {
302 Unit
*u
= NULL
; /* just to appease gcc, initialization is not really necessary */
309 if (streq_ptr(path
, "/org/freedesktop/systemd1/unit/self")) {
310 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
311 sd_bus_message
*message
;
314 message
= sd_bus_get_current_message(bus
);
318 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
322 r
= sd_bus_creds_get_pid(creds
, &pid
);
326 u
= manager_get_unit_by_pid(m
, pid
);
330 r
= manager_load_unit_from_dbus_path(m
, path
, error
, &u
);
340 static int bus_unit_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
341 Manager
*m
= userdata
;
349 return find_unit(m
, bus
, path
, (Unit
**) found
, error
);
352 static int bus_unit_interface_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
353 Manager
*m
= userdata
;
363 r
= find_unit(m
, bus
, path
, &u
, error
);
367 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
374 static int bus_unit_cgroup_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
375 Manager
*m
= userdata
;
385 r
= find_unit(m
, bus
, path
, &u
, error
);
389 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
392 if (!UNIT_HAS_CGROUP_CONTEXT(u
))
399 static int bus_cgroup_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
400 Manager
*m
= userdata
;
411 r
= find_unit(m
, bus
, path
, &u
, error
);
415 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
418 c
= unit_get_cgroup_context(u
);
426 static int bus_exec_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
427 Manager
*m
= userdata
;
438 r
= find_unit(m
, bus
, path
, &u
, error
);
442 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
445 c
= unit_get_exec_context(u
);
453 static int bus_kill_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
454 Manager
*m
= userdata
;
465 r
= find_unit(m
, bus
, path
, &u
, error
);
469 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
472 c
= unit_get_kill_context(u
);
480 static int bus_job_enumerate(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
481 _cleanup_strv_free_
char **l
= NULL
;
482 Manager
*m
= userdata
;
487 l
= new0(char*, hashmap_size(m
->jobs
)+1);
491 HASHMAP_FOREACH(j
, m
->jobs
, i
) {
492 l
[k
] = job_dbus_path(j
);
499 assert(hashmap_size(m
->jobs
) == k
);
507 static int bus_unit_enumerate(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
508 _cleanup_strv_free_
char **l
= NULL
;
509 Manager
*m
= userdata
;
514 l
= new0(char*, hashmap_size(m
->units
)+1);
518 HASHMAP_FOREACH(u
, m
->units
, i
) {
519 l
[k
] = unit_dbus_path(u
);
532 static int bus_setup_api_vtables(Manager
*m
, sd_bus
*bus
) {
540 r
= sd_bus_add_filter(bus
, NULL
, mac_selinux_filter
, m
);
542 return log_error_errno(r
, "Failed to add SELinux access filter: %m");
545 r
= sd_bus_add_object_vtable(bus
, NULL
, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable
, m
);
547 return log_error_errno(r
, "Failed to register Manager vtable: %m");
549 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable
, bus_job_find
, m
);
551 return log_error_errno(r
, "Failed to register Job vtable: %m");
553 r
= sd_bus_add_node_enumerator(bus
, NULL
, "/org/freedesktop/systemd1/job", bus_job_enumerate
, m
);
555 return log_error_errno(r
, "Failed to add job enumerator: %m");
557 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable
, bus_unit_find
, m
);
559 return log_error_errno(r
, "Failed to register Unit vtable: %m");
561 r
= sd_bus_add_node_enumerator(bus
, NULL
, "/org/freedesktop/systemd1/unit", bus_unit_enumerate
, m
);
563 return log_error_errno(r
, "Failed to add job enumerator: %m");
565 for (t
= 0; t
< _UNIT_TYPE_MAX
; t
++) {
566 const char *interface
;
568 assert_se(interface
= unit_dbus_interface_from_type(t
));
570 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, unit_vtable
[t
]->bus_vtable
, bus_unit_interface_find
, m
);
572 return log_error_errno(r
, "Failed to register type specific vtable for %s: %m", interface
);
574 if (unit_vtable
[t
]->cgroup_context_offset
> 0) {
575 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_unit_cgroup_vtable
, bus_unit_cgroup_find
, m
);
577 return log_error_errno(r
, "Failed to register control group unit vtable for %s: %m", interface
);
579 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_cgroup_vtable
, bus_cgroup_context_find
, m
);
581 return log_error_errno(r
, "Failed to register control group vtable for %s: %m", interface
);
584 if (unit_vtable
[t
]->exec_context_offset
> 0) {
585 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_exec_vtable
, bus_exec_context_find
, m
);
587 return log_error_errno(r
, "Failed to register execute vtable for %s: %m", interface
);
590 if (unit_vtable
[t
]->kill_context_offset
> 0) {
591 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_kill_vtable
, bus_kill_context_find
, m
);
593 return log_error_errno(r
, "Failed to register kill vtable for %s: %m", interface
);
600 static int bus_setup_disconnected_match(Manager
*m
, sd_bus
*bus
) {
606 r
= sd_bus_add_match(
609 "sender='org.freedesktop.DBus.Local',"
611 "path='/org/freedesktop/DBus/Local',"
612 "interface='org.freedesktop.DBus.Local',"
613 "member='Disconnected'",
614 signal_disconnected
, m
);
617 return log_error_errno(r
, "Failed to register 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_start(bus
);
688 log_warning_errno(r
, "Failed to start new connection bus: %m");
692 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
694 log_warning_errno(r
, "Failed to attach new connection bus to event loop: %m");
698 r
= bus_setup_disconnected_match(m
, bus
);
702 r
= bus_setup_api_vtables(m
, bus
);
704 log_warning_errno(r
, "Failed to set up API vtables on new connection bus: %m");
708 r
= set_put(m
->private_buses
, bus
);
710 log_warning_errno(r
, "Failed to add new connection bus to set: %m");
716 log_debug("Accepted new private connection.");
721 int manager_sync_bus_names(Manager
*m
, sd_bus
*bus
) {
722 _cleanup_strv_free_
char **names
= NULL
;
731 r
= sd_bus_list_names(bus
, &names
, NULL
);
733 return log_error_errno(r
, "Failed to get initial list of names: %m");
735 /* We have to synchronize the current bus names with the
736 * list of active services. To do this, walk the list of
737 * all units with bus names. */
738 HASHMAP_FOREACH_KEY(u
, name
, m
->watch_bus
, i
) {
739 Service
*s
= SERVICE(u
);
743 if (!streq_ptr(s
->bus_name
, name
)) {
744 log_unit_warning(u
, "Bus name has changed from %s → %s, ignoring.", s
->bus_name
, name
);
748 /* Check if a service's bus name is in the list of currently
750 if (strv_contains(names
, name
)) {
751 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
754 /* If it is, determine its current owner */
755 r
= sd_bus_get_name_creds(bus
, name
, SD_BUS_CREDS_UNIQUE_NAME
, &creds
);
757 log_full_errno(r
== -ENXIO
? LOG_DEBUG
: LOG_ERR
, r
, "Failed to get bus name owner %s: %m", name
);
761 r
= sd_bus_creds_get_unique_name(creds
, &unique
);
763 log_full_errno(r
== -ENXIO
? LOG_DEBUG
: LOG_ERR
, r
, "Failed to get unique name for %s: %m", name
);
767 /* Now, let's compare that to the previous bus owner, and
768 * if it's still the same, all is fine, so just don't
769 * bother the service. Otherwise, the name has apparently
770 * changed, so synthesize a name owner changed signal. */
772 if (!streq_ptr(unique
, s
->bus_name_owner
))
773 UNIT_VTABLE(u
)->bus_name_owner_change(u
, name
, s
->bus_name_owner
, unique
);
775 /* So, the name we're watching is not on the bus.
776 * This either means it simply hasn't appeared yet,
777 * or it was lost during the daemon reload.
778 * Check if the service has a stored name owner,
779 * and synthesize a name loss signal in this case. */
781 if (s
->bus_name_owner
)
782 UNIT_VTABLE(u
)->bus_name_owner_change(u
, name
, s
->bus_name_owner
, NULL
);
789 static int bus_setup_api(Manager
*m
, sd_bus
*bus
) {
798 /* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
799 r
= sd_bus_negotiate_creds(bus
, 1,
800 SD_BUS_CREDS_PID
|SD_BUS_CREDS_UID
|
801 SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EFFECTIVE_CAPS
|
802 SD_BUS_CREDS_SELINUX_CONTEXT
);
804 log_warning_errno(r
, "Failed to enable credential passing, ignoring: %m");
806 r
= bus_setup_api_vtables(m
, bus
);
810 HASHMAP_FOREACH_KEY(u
, name
, m
->watch_bus
, i
) {
811 r
= unit_install_bus_match(u
, bus
, name
);
813 log_error_errno(r
, "Failed to subscribe to NameOwnerChanged signal for '%s': %m", name
);
816 r
= sd_bus_add_match(
820 "sender='org.freedesktop.DBus',"
821 "path='/org/freedesktop/DBus',"
822 "interface='org.freedesktop.systemd1.Activator',"
823 "member='ActivationRequest'",
824 signal_activation_request
, m
);
826 log_warning_errno(r
, "Failed to subscribe to activation signal: %m");
828 /* Allow replacing of our name, to ease implementation of
829 * reexecution, where we keep the old connection open until
830 * after the new connection is set up and the name installed
831 * to allow clients to synchronously wait for reexecution to
833 r
= sd_bus_request_name(bus
,"org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING
|SD_BUS_NAME_ALLOW_REPLACEMENT
);
835 return log_error_errno(r
, "Failed to register name: %m");
837 r
= manager_sync_bus_names(m
, bus
);
841 log_debug("Successfully connected to API bus.");
845 static int bus_init_api(Manager
*m
) {
846 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
852 /* The API and system bus is the same if we are running in system mode */
853 if (MANAGER_IS_SYSTEM(m
) && m
->system_bus
)
854 bus
= sd_bus_ref(m
->system_bus
);
856 if (MANAGER_IS_SYSTEM(m
))
857 r
= sd_bus_open_system(&bus
);
859 r
= sd_bus_open_user(&bus
);
862 log_debug("Failed to connect to API bus, retrying later...");
866 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
868 log_error_errno(r
, "Failed to attach API bus to event loop: %m");
872 r
= bus_setup_disconnected_match(m
, bus
);
877 r
= bus_setup_api(m
, bus
);
879 log_error_errno(r
, "Failed to set up API bus: %m");
889 static int bus_setup_system(Manager
*m
, sd_bus
*bus
) {
895 /* if we are a user instance we get the Released message via the system bus */
896 if (MANAGER_IS_USER(m
)) {
897 r
= sd_bus_add_match(
901 "interface='org.freedesktop.systemd1.Agent',"
903 "path='/org/freedesktop/systemd1/agent'",
904 signal_agent_released
, m
);
906 log_warning_errno(r
, "Failed to register Released match on system bus: %m");
909 log_debug("Successfully connected to system bus.");
913 static int bus_init_system(Manager
*m
) {
914 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
920 /* The API and system bus is the same if we are running in system mode */
921 if (MANAGER_IS_SYSTEM(m
) && m
->api_bus
) {
922 m
->system_bus
= sd_bus_ref(m
->api_bus
);
926 r
= sd_bus_open_system(&bus
);
928 log_debug("Failed to connect to system bus, retrying later...");
932 r
= bus_setup_disconnected_match(m
, bus
);
936 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
938 log_error_errno(r
, "Failed to attach system bus to event loop: %m");
942 r
= bus_setup_system(m
, bus
);
944 log_error_errno(r
, "Failed to set up system bus: %m");
954 static int bus_init_private(Manager
*m
) {
955 _cleanup_close_
int fd
= -1;
956 union sockaddr_union sa
= {
957 .un
.sun_family
= AF_UNIX
965 if (m
->private_listen_fd
>= 0)
968 if (MANAGER_IS_SYSTEM(m
)) {
970 /* We want the private bus only when running as init */
971 if (getpid_cached() != 1)
974 strcpy(sa
.un
.sun_path
, "/run/systemd/private");
975 salen
= SOCKADDR_UN_LEN(sa
.un
);
977 size_t left
= sizeof(sa
.un
.sun_path
);
978 char *p
= sa
.un
.sun_path
;
981 e
= secure_getenv("XDG_RUNTIME_DIR");
983 log_error("Failed to determine XDG_RUNTIME_DIR");
987 left
= strpcpy(&p
, left
, e
);
988 left
= strpcpy(&p
, left
, "/systemd/private");
990 salen
= sizeof(sa
.un
) - left
;
993 (void) mkdir_parents_label(sa
.un
.sun_path
, 0755);
994 (void) unlink(sa
.un
.sun_path
);
996 fd
= socket(AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0);
998 return log_error_errno(errno
, "Failed to allocate private socket: %m");
1000 r
= bind(fd
, &sa
.sa
, salen
);
1002 return log_error_errno(errno
, "Failed to bind private socket: %m");
1004 r
= listen(fd
, SOMAXCONN
);
1006 return log_error_errno(errno
, "Failed to make private socket listening: %m");
1008 r
= sd_event_add_io(m
->event
, &s
, fd
, EPOLLIN
, bus_on_connection
, m
);
1010 return log_error_errno(r
, "Failed to allocate event source: %m");
1012 (void) sd_event_source_set_description(s
, "bus-connection");
1014 m
->private_listen_fd
= fd
;
1015 m
->private_listen_event_source
= s
;
1018 log_debug("Successfully created private D-Bus server.");
1023 int bus_init(Manager
*m
, bool try_bus_connect
) {
1026 if (try_bus_connect
) {
1027 r
= bus_init_system(m
);
1031 r
= bus_init_api(m
);
1036 r
= bus_init_private(m
);
1043 static void destroy_bus(Manager
*m
, sd_bus
**bus
) {
1054 /* Make sure all bus slots watching names are released. */
1055 HASHMAP_FOREACH(u
, m
->watch_bus
, i
) {
1056 if (!u
->match_bus_slot
)
1059 if (sd_bus_slot_get_bus(u
->match_bus_slot
) != *bus
)
1062 u
->match_bus_slot
= sd_bus_slot_unref(u
->match_bus_slot
);
1065 /* Get rid of tracked clients on this bus */
1066 if (m
->subscribed
&& sd_bus_track_get_bus(m
->subscribed
) == *bus
)
1067 m
->subscribed
= sd_bus_track_unref(m
->subscribed
);
1069 HASHMAP_FOREACH(j
, m
->jobs
, i
)
1070 if (j
->bus_track
&& sd_bus_track_get_bus(j
->bus_track
) == *bus
)
1071 j
->bus_track
= sd_bus_track_unref(j
->bus_track
);
1073 /* Get rid of queued message on this bus */
1074 if (m
->queued_message
&& sd_bus_message_get_bus(m
->queued_message
) == *bus
)
1075 m
->queued_message
= sd_bus_message_unref(m
->queued_message
);
1077 /* Possibly flush unwritten data, but only if we are
1078 * unprivileged, since we don't want to sync here */
1079 if (!MANAGER_IS_SYSTEM(m
))
1082 /* And destroy the object */
1084 *bus
= sd_bus_unref(*bus
);
1087 void bus_done(Manager
*m
) {
1093 destroy_bus(m
, &m
->api_bus
);
1095 destroy_bus(m
, &m
->system_bus
);
1096 while ((b
= set_steal_first(m
->private_buses
)))
1099 m
->private_buses
= set_free(m
->private_buses
);
1101 m
->subscribed
= sd_bus_track_unref(m
->subscribed
);
1102 m
->deserialized_subscribed
= strv_free(m
->deserialized_subscribed
);
1104 if (m
->private_listen_event_source
)
1105 m
->private_listen_event_source
= sd_event_source_unref(m
->private_listen_event_source
);
1107 m
->private_listen_fd
= safe_close(m
->private_listen_fd
);
1109 bus_verify_polkit_async_registry_free(m
->polkit_registry
);
1112 int bus_fdset_add_all(Manager
*m
, FDSet
*fds
) {
1120 /* When we are about to reexecute we add all D-Bus fds to the
1121 * set to pass over to the newly executed systemd. They won't
1122 * be used there however, except thatt they are closed at the
1123 * very end of deserialization, those making it possible for
1124 * clients to synchronously wait for systemd to reexec by
1125 * simply waiting for disconnection */
1128 fd
= sd_bus_get_fd(m
->api_bus
);
1130 fd
= fdset_put_dup(fds
, fd
);
1136 SET_FOREACH(b
, m
->private_buses
, i
) {
1137 fd
= sd_bus_get_fd(b
);
1139 fd
= fdset_put_dup(fds
, fd
);
1145 /* We don't offer any APIs on the system bus (well, unless it
1146 * is the same as the API bus) hence we don't bother with it
1152 int bus_foreach_bus(
1154 sd_bus_track
*subscribed2
,
1155 int (*send_message
)(sd_bus
*bus
, void *userdata
),
1162 /* Send to all direct buses, unconditionally */
1163 SET_FOREACH(b
, m
->private_buses
, i
) {
1164 r
= send_message(b
, userdata
);
1169 /* Send to API bus, but only if somebody is subscribed */
1170 if (sd_bus_track_count(m
->subscribed
) > 0 ||
1171 sd_bus_track_count(subscribed2
) > 0) {
1172 r
= send_message(m
->api_bus
, userdata
);
1180 void bus_track_serialize(sd_bus_track
*t
, FILE *f
, const char *prefix
) {
1186 for (n
= sd_bus_track_first(t
); n
; n
= sd_bus_track_next(t
)) {
1189 c
= sd_bus_track_count_name(t
, n
);
1191 for (j
= 0; j
< c
; j
++) {
1200 int bus_track_coldplug(Manager
*m
, sd_bus_track
**t
, bool recursive
, char **l
) {
1206 if (strv_isempty(l
))
1213 r
= sd_bus_track_new(m
->api_bus
, t
, NULL
, NULL
);
1218 r
= sd_bus_track_set_recursive(*t
, recursive
);
1222 return bus_track_add_name_many(*t
, l
);
1225 int bus_verify_manage_units_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1226 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.manage-units", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1229 int bus_verify_manage_unit_files_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-unit-files", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1233 int bus_verify_reload_daemon_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1234 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.reload-daemon", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1237 int bus_verify_set_environment_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1238 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.set-environment", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);