2 This file is part of systemd.
4 Copyright 2010 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include <sys/epoll.h>
26 #include "alloc-util.h"
27 #include "bus-common-errors.h"
28 #include "bus-error.h"
29 #include "bus-internal.h"
31 #include "dbus-cgroup.h"
32 #include "dbus-execute.h"
34 #include "dbus-kill.h"
35 #include "dbus-manager.h"
36 #include "dbus-unit.h"
42 #include "selinux-access.h"
44 #include "string-util.h"
47 #include "user-util.h"
49 #define CONNECTIONS_MAX 4096
51 static void destroy_bus(Manager
*m
, sd_bus
**bus
);
53 int bus_send_queued_message(Manager
*m
) {
58 if (!m
->queued_message
)
61 /* If we cannot get rid of this message we won't dispatch any
62 * D-Bus messages, so that we won't end up wanting to queue
65 r
= sd_bus_send(NULL
, m
->queued_message
, NULL
);
67 log_warning_errno(r
, "Failed to send queued message: %m");
69 m
->queued_message
= sd_bus_message_unref(m
->queued_message
);
74 int bus_forward_agent_released(Manager
*m
, const char *path
) {
80 if (!MANAGER_IS_SYSTEM(m
))
86 /* If we are running a system instance we forward the agent message on the system bus, so that the user
87 * instances get notified about this, too */
89 r
= sd_bus_emit_signal(m
->system_bus
,
90 "/org/freedesktop/systemd1/agent",
91 "org.freedesktop.systemd1.Agent",
95 return log_warning_errno(r
, "Failed to propagate agent release message: %m");
100 static int signal_agent_released(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
101 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
102 Manager
*m
= userdata
;
110 /* only accept org.freedesktop.systemd1.Agent from UID=0 */
111 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
115 r
= sd_bus_creds_get_euid(creds
, &sender_uid
);
116 if (r
< 0 || sender_uid
!= 0)
119 /* parse 'cgroup-empty' notification */
120 r
= sd_bus_message_read(message
, "s", &cgroup
);
122 bus_log_parse_error(r
);
126 manager_notify_cgroup_empty(m
, cgroup
);
130 static int signal_disconnected(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
131 Manager
*m
= userdata
;
136 assert_se(bus
= sd_bus_message_get_bus(message
));
138 if (bus
== m
->api_bus
)
139 destroy_bus(m
, &m
->api_bus
);
140 if (bus
== m
->system_bus
)
141 destroy_bus(m
, &m
->system_bus
);
142 if (set_remove(m
->private_buses
, bus
)) {
143 log_debug("Got disconnect on private connection.");
144 destroy_bus(m
, &bus
);
150 static int signal_activation_request(sd_bus_message
*message
, void *userdata
, sd_bus_error
*ret_error
) {
151 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
152 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
153 Manager
*m
= userdata
;
161 r
= sd_bus_message_read(message
, "s", &name
);
163 bus_log_parse_error(r
);
167 if (manager_unit_inactive_or_pending(m
, SPECIAL_DBUS_SERVICE
) ||
168 manager_unit_inactive_or_pending(m
, SPECIAL_DBUS_SOCKET
)) {
169 r
= sd_bus_error_setf(&error
, BUS_ERROR_SHUTTING_DOWN
, "Refusing activation, D-Bus is shutting down.");
173 r
= manager_load_unit(m
, name
, NULL
, &error
, &u
);
177 if (u
->refuse_manual_start
) {
178 r
= sd_bus_error_setf(&error
, BUS_ERROR_ONLY_BY_DEPENDENCY
, "Operation refused, %s may be requested by dependency only.", u
->id
);
182 r
= manager_add_job(m
, JOB_START
, u
, JOB_REPLACE
, &error
, NULL
);
186 /* Successfully queued, that's it for us */
190 if (!sd_bus_error_is_set(&error
))
191 sd_bus_error_set_errno(&error
, r
);
193 log_debug("D-Bus activation failed for %s: %s", name
, bus_error_message(&error
, r
));
195 r
= sd_bus_message_new_signal(sd_bus_message_get_bus(message
), &reply
, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
197 bus_log_create_error(r
);
201 r
= sd_bus_message_append(reply
, "sss", name
, error
.name
, error
.message
);
203 bus_log_create_error(r
);
207 r
= sd_bus_send_to(NULL
, reply
, "org.freedesktop.DBus", NULL
);
209 return log_error_errno(r
, "Failed to respond with to bus activation request: %m");
215 static int mac_selinux_filter(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
216 Manager
*m
= userdata
;
217 const char *verb
, *path
;
224 /* Our own method calls are all protected individually with
225 * selinux checks, but the built-in interfaces need to be
228 if (sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Properties", "Set"))
230 else if (sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Introspectable", NULL
) ||
231 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Properties", NULL
) ||
232 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.ObjectManager", NULL
) ||
233 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Peer", NULL
))
238 path
= sd_bus_message_get_path(message
);
240 if (object_path_startswith("/org/freedesktop/systemd1", path
)) {
242 r
= mac_selinux_access_check(message
, verb
, error
);
249 if (streq_ptr(path
, "/org/freedesktop/systemd1/unit/self")) {
250 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
253 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
257 r
= sd_bus_creds_get_pid(creds
, &pid
);
261 u
= manager_get_unit_by_pid(m
, pid
);
263 r
= manager_get_job_from_dbus_path(m
, path
, &j
);
267 manager_load_unit_from_dbus_path(m
, path
, NULL
, &u
);
273 r
= mac_selinux_unit_access_check(u
, message
, verb
, error
);
281 static int bus_job_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
282 Manager
*m
= userdata
;
292 r
= manager_get_job_from_dbus_path(m
, path
, &j
);
300 static int find_unit(Manager
*m
, sd_bus
*bus
, const char *path
, Unit
**unit
, sd_bus_error
*error
) {
308 if (streq_ptr(path
, "/org/freedesktop/systemd1/unit/self")) {
309 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
310 sd_bus_message
*message
;
313 message
= sd_bus_get_current_message(bus
);
317 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
321 r
= sd_bus_creds_get_pid(creds
, &pid
);
325 u
= manager_get_unit_by_pid(m
, pid
);
327 r
= manager_load_unit_from_dbus_path(m
, path
, error
, &u
);
339 static int bus_unit_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
340 Manager
*m
= userdata
;
348 return find_unit(m
, bus
, path
, (Unit
**) found
, error
);
351 static int bus_unit_interface_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
352 Manager
*m
= userdata
;
362 r
= find_unit(m
, bus
, path
, &u
, error
);
366 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
373 static int bus_unit_cgroup_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
374 Manager
*m
= userdata
;
384 r
= find_unit(m
, bus
, path
, &u
, error
);
388 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
391 if (!UNIT_HAS_CGROUP_CONTEXT(u
))
398 static int bus_cgroup_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
399 Manager
*m
= userdata
;
410 r
= find_unit(m
, bus
, path
, &u
, error
);
414 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
417 c
= unit_get_cgroup_context(u
);
425 static int bus_exec_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
426 Manager
*m
= userdata
;
437 r
= find_unit(m
, bus
, path
, &u
, error
);
441 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
444 c
= unit_get_exec_context(u
);
452 static int bus_kill_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
453 Manager
*m
= userdata
;
464 r
= find_unit(m
, bus
, path
, &u
, error
);
468 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
471 c
= unit_get_kill_context(u
);
479 static int bus_job_enumerate(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
480 _cleanup_free_
char **l
= NULL
;
481 Manager
*m
= userdata
;
486 l
= new0(char*, hashmap_size(m
->jobs
)+1);
490 HASHMAP_FOREACH(j
, m
->jobs
, i
) {
491 l
[k
] = job_dbus_path(j
);
498 assert(hashmap_size(m
->jobs
) == k
);
506 static int bus_unit_enumerate(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
507 _cleanup_free_
char **l
= NULL
;
508 Manager
*m
= userdata
;
513 l
= new0(char*, hashmap_size(m
->units
)+1);
517 HASHMAP_FOREACH(u
, m
->units
, i
) {
518 l
[k
] = unit_dbus_path(u
);
531 static int bus_setup_api_vtables(Manager
*m
, sd_bus
*bus
) {
539 r
= sd_bus_add_filter(bus
, NULL
, mac_selinux_filter
, m
);
541 return log_error_errno(r
, "Failed to add SELinux access filter: %m");
544 r
= sd_bus_add_object_vtable(bus
, NULL
, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable
, m
);
546 return log_error_errno(r
, "Failed to register Manager vtable: %m");
548 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable
, bus_job_find
, m
);
550 return log_error_errno(r
, "Failed to register Job vtable: %m");
552 r
= sd_bus_add_node_enumerator(bus
, NULL
, "/org/freedesktop/systemd1/job", bus_job_enumerate
, m
);
554 return log_error_errno(r
, "Failed to add job enumerator: %m");
556 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable
, bus_unit_find
, m
);
558 return log_error_errno(r
, "Failed to register Unit vtable: %m");
560 r
= sd_bus_add_node_enumerator(bus
, NULL
, "/org/freedesktop/systemd1/unit", bus_unit_enumerate
, m
);
562 return log_error_errno(r
, "Failed to add job enumerator: %m");
564 for (t
= 0; t
< _UNIT_TYPE_MAX
; t
++) {
565 const char *interface
;
567 assert_se(interface
= unit_dbus_interface_from_type(t
));
569 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, unit_vtable
[t
]->bus_vtable
, bus_unit_interface_find
, m
);
571 return log_error_errno(r
, "Failed to register type specific vtable for %s: %m", interface
);
573 if (unit_vtable
[t
]->cgroup_context_offset
> 0) {
574 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_unit_cgroup_vtable
, bus_unit_cgroup_find
, m
);
576 return log_error_errno(r
, "Failed to register control group unit vtable for %s: %m", interface
);
578 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_cgroup_vtable
, bus_cgroup_context_find
, m
);
580 return log_error_errno(r
, "Failed to register control group vtable for %s: %m", interface
);
583 if (unit_vtable
[t
]->exec_context_offset
> 0) {
584 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_exec_vtable
, bus_exec_context_find
, m
);
586 return log_error_errno(r
, "Failed to register execute vtable for %s: %m", interface
);
589 if (unit_vtable
[t
]->kill_context_offset
> 0) {
590 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_kill_vtable
, bus_kill_context_find
, m
);
592 return log_error_errno(r
, "Failed to register kill vtable for %s: %m", interface
);
599 static int bus_setup_disconnected_match(Manager
*m
, sd_bus
*bus
) {
605 r
= sd_bus_add_match(
608 "sender='org.freedesktop.DBus.Local',"
610 "path='/org/freedesktop/DBus/Local',"
611 "interface='org.freedesktop.DBus.Local',"
612 "member='Disconnected'",
613 signal_disconnected
, m
);
616 return log_error_errno(r
, "Failed to register 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_start(bus
);
687 log_warning_errno(r
, "Failed to start new connection bus: %m");
691 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
693 log_warning_errno(r
, "Failed to attach new connection bus to event loop: %m");
697 r
= bus_setup_disconnected_match(m
, bus
);
701 r
= bus_setup_api_vtables(m
, bus
);
703 log_warning_errno(r
, "Failed to set up API vtables on new connection bus: %m");
707 r
= set_put(m
->private_buses
, bus
);
709 log_warning_errno(r
, "Failed to add new connection bus to set: %m");
715 log_debug("Accepted new private connection.");
720 int manager_sync_bus_names(Manager
*m
, sd_bus
*bus
) {
721 _cleanup_strv_free_
char **names
= NULL
;
730 r
= sd_bus_list_names(bus
, &names
, NULL
);
732 return log_error_errno(r
, "Failed to get initial list of names: %m");
734 /* We have to synchronize the current bus names with the
735 * list of active services. To do this, walk the list of
736 * all units with bus names. */
737 HASHMAP_FOREACH_KEY(u
, name
, m
->watch_bus
, i
) {
738 Service
*s
= SERVICE(u
);
742 if (!streq_ptr(s
->bus_name
, name
)) {
743 log_unit_warning(u
, "Bus name has changed from %s → %s, ignoring.", s
->bus_name
, name
);
747 /* Check if a service's bus name is in the list of currently
749 if (strv_contains(names
, name
)) {
750 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
753 /* If it is, determine its current owner */
754 r
= sd_bus_get_name_creds(bus
, name
, SD_BUS_CREDS_UNIQUE_NAME
, &creds
);
756 log_error_errno(r
, "Failed to get bus name owner %s: %m", name
);
760 r
= sd_bus_creds_get_unique_name(creds
, &unique
);
762 log_error_errno(r
, "Failed to get unique name for %s: %m", name
);
766 /* Now, let's compare that to the previous bus owner, and
767 * if it's still the same, all is fine, so just don't
768 * bother the service. Otherwise, the name has apparently
769 * changed, so synthesize a name owner changed signal. */
771 if (!streq_ptr(unique
, s
->bus_name_owner
))
772 UNIT_VTABLE(u
)->bus_name_owner_change(u
, name
, s
->bus_name_owner
, unique
);
774 /* So, the name we're watching is not on the bus.
775 * This either means it simply hasn't appeared yet,
776 * or it was lost during the daemon reload.
777 * Check if the service has a stored name owner,
778 * and synthesize a name loss signal in this case. */
780 if (s
->bus_name_owner
)
781 UNIT_VTABLE(u
)->bus_name_owner_change(u
, name
, s
->bus_name_owner
, NULL
);
788 static int bus_setup_api(Manager
*m
, sd_bus
*bus
) {
797 /* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
798 r
= sd_bus_negotiate_creds(bus
, 1,
799 SD_BUS_CREDS_PID
|SD_BUS_CREDS_UID
|
800 SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EFFECTIVE_CAPS
|
801 SD_BUS_CREDS_SELINUX_CONTEXT
);
803 log_warning_errno(r
, "Failed to enable credential passing, ignoring: %m");
805 r
= bus_setup_api_vtables(m
, bus
);
809 HASHMAP_FOREACH_KEY(u
, name
, m
->watch_bus
, i
) {
810 r
= unit_install_bus_match(u
, bus
, name
);
812 log_error_errno(r
, "Failed to subscribe to NameOwnerChanged signal for '%s': %m", name
);
815 r
= sd_bus_add_match(
819 "sender='org.freedesktop.DBus',"
820 "path='/org/freedesktop/DBus',"
821 "interface='org.freedesktop.systemd1.Activator',"
822 "member='ActivationRequest'",
823 signal_activation_request
, m
);
825 log_warning_errno(r
, "Failed to subscribe to activation signal: %m");
827 /* Allow replacing of our name, to ease implementation of
828 * reexecution, where we keep the old connection open until
829 * after the new connection is set up and the name installed
830 * to allow clients to synchronously wait for reexecution to
832 r
= sd_bus_request_name(bus
,"org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING
|SD_BUS_NAME_ALLOW_REPLACEMENT
);
834 return log_error_errno(r
, "Failed to register name: %m");
836 r
= manager_sync_bus_names(m
, bus
);
840 log_debug("Successfully connected to API bus.");
844 static int bus_init_api(Manager
*m
) {
845 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
851 /* The API and system bus is the same if we are running in system mode */
852 if (MANAGER_IS_SYSTEM(m
) && m
->system_bus
)
853 bus
= sd_bus_ref(m
->system_bus
);
855 if (MANAGER_IS_SYSTEM(m
))
856 r
= sd_bus_open_system(&bus
);
858 r
= sd_bus_open_user(&bus
);
861 log_debug("Failed to connect to API bus, retrying later...");
865 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
867 log_error_errno(r
, "Failed to attach API bus to event loop: %m");
871 r
= bus_setup_disconnected_match(m
, bus
);
876 r
= bus_setup_api(m
, bus
);
878 log_error_errno(r
, "Failed to set up API bus: %m");
888 static int bus_setup_system(Manager
*m
, sd_bus
*bus
) {
894 /* if we are a user instance we get the Released message via the system bus */
895 if (MANAGER_IS_USER(m
)) {
896 r
= sd_bus_add_match(
900 "interface='org.freedesktop.systemd1.Agent',"
902 "path='/org/freedesktop/systemd1/agent'",
903 signal_agent_released
, m
);
905 log_warning_errno(r
, "Failed to register Released match on system bus: %m");
908 log_debug("Successfully connected to system bus.");
912 static int bus_init_system(Manager
*m
) {
913 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
919 /* The API and system bus is the same if we are running in system mode */
920 if (MANAGER_IS_SYSTEM(m
) && m
->api_bus
) {
921 m
->system_bus
= sd_bus_ref(m
->api_bus
);
925 r
= sd_bus_open_system(&bus
);
927 log_debug("Failed to connect to system bus, retrying later...");
931 r
= bus_setup_disconnected_match(m
, bus
);
935 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
937 log_error_errno(r
, "Failed to attach system bus to event loop: %m");
941 r
= bus_setup_system(m
, bus
);
943 log_error_errno(r
, "Failed to set up system bus: %m");
953 static int bus_init_private(Manager
*m
) {
954 _cleanup_close_
int fd
= -1;
955 union sockaddr_union sa
= {
956 .un
.sun_family
= AF_UNIX
964 if (m
->private_listen_fd
>= 0)
967 if (MANAGER_IS_SYSTEM(m
)) {
969 /* We want the private bus only when running as init */
973 strcpy(sa
.un
.sun_path
, "/run/systemd/private");
974 salen
= SOCKADDR_UN_LEN(sa
.un
);
976 size_t left
= sizeof(sa
.un
.sun_path
);
977 char *p
= sa
.un
.sun_path
;
980 e
= secure_getenv("XDG_RUNTIME_DIR");
982 log_error("Failed to determine XDG_RUNTIME_DIR");
986 left
= strpcpy(&p
, left
, e
);
987 left
= strpcpy(&p
, left
, "/systemd/private");
989 salen
= sizeof(sa
.un
) - left
;
992 (void) mkdir_parents_label(sa
.un
.sun_path
, 0755);
993 (void) unlink(sa
.un
.sun_path
);
995 fd
= socket(AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0);
997 return log_error_errno(errno
, "Failed to allocate private socket: %m");
999 r
= bind(fd
, &sa
.sa
, salen
);
1001 return log_error_errno(errno
, "Failed to bind private socket: %m");
1003 r
= listen(fd
, SOMAXCONN
);
1005 return log_error_errno(errno
, "Failed to make private socket listening: %m");
1007 r
= sd_event_add_io(m
->event
, &s
, fd
, EPOLLIN
, bus_on_connection
, m
);
1009 return log_error_errno(r
, "Failed to allocate event source: %m");
1011 (void) sd_event_source_set_description(s
, "bus-connection");
1013 m
->private_listen_fd
= fd
;
1014 m
->private_listen_event_source
= s
;
1017 log_debug("Successfully created private D-Bus server.");
1022 int bus_init(Manager
*m
, bool try_bus_connect
) {
1025 if (try_bus_connect
) {
1026 r
= bus_init_system(m
);
1030 r
= bus_init_api(m
);
1035 r
= bus_init_private(m
);
1042 static void destroy_bus(Manager
*m
, sd_bus
**bus
) {
1052 /* Get rid of tracked clients on this bus */
1053 if (m
->subscribed
&& sd_bus_track_get_bus(m
->subscribed
) == *bus
)
1054 m
->subscribed
= sd_bus_track_unref(m
->subscribed
);
1056 HASHMAP_FOREACH(j
, m
->jobs
, i
)
1057 if (j
->clients
&& sd_bus_track_get_bus(j
->clients
) == *bus
)
1058 j
->clients
= sd_bus_track_unref(j
->clients
);
1060 /* Get rid of queued message on this bus */
1061 if (m
->queued_message
&& sd_bus_message_get_bus(m
->queued_message
) == *bus
)
1062 m
->queued_message
= sd_bus_message_unref(m
->queued_message
);
1064 /* Possibly flush unwritten data, but only if we are
1065 * unprivileged, since we don't want to sync here */
1066 if (!MANAGER_IS_SYSTEM(m
))
1069 /* And destroy the object */
1071 *bus
= sd_bus_unref(*bus
);
1074 void bus_done(Manager
*m
) {
1080 destroy_bus(m
, &m
->api_bus
);
1082 destroy_bus(m
, &m
->system_bus
);
1083 while ((b
= set_steal_first(m
->private_buses
)))
1086 m
->private_buses
= set_free(m
->private_buses
);
1088 m
->subscribed
= sd_bus_track_unref(m
->subscribed
);
1089 m
->deserialized_subscribed
= strv_free(m
->deserialized_subscribed
);
1091 if (m
->private_listen_event_source
)
1092 m
->private_listen_event_source
= sd_event_source_unref(m
->private_listen_event_source
);
1094 m
->private_listen_fd
= safe_close(m
->private_listen_fd
);
1096 bus_verify_polkit_async_registry_free(m
->polkit_registry
);
1099 int bus_fdset_add_all(Manager
*m
, FDSet
*fds
) {
1107 /* When we are about to reexecute we add all D-Bus fds to the
1108 * set to pass over to the newly executed systemd. They won't
1109 * be used there however, except thatt they are closed at the
1110 * very end of deserialization, those making it possible for
1111 * clients to synchronously wait for systemd to reexec by
1112 * simply waiting for disconnection */
1115 fd
= sd_bus_get_fd(m
->api_bus
);
1117 fd
= fdset_put_dup(fds
, fd
);
1123 SET_FOREACH(b
, m
->private_buses
, i
) {
1124 fd
= sd_bus_get_fd(b
);
1126 fd
= fdset_put_dup(fds
, fd
);
1132 /* We don't offer any APIs on the system bus (well, unless it
1133 * is the same as the API bus) hence we don't bother with it
1139 int bus_foreach_bus(
1141 sd_bus_track
*subscribed2
,
1142 int (*send_message
)(sd_bus
*bus
, void *userdata
),
1149 /* Send to all direct buses, unconditionally */
1150 SET_FOREACH(b
, m
->private_buses
, i
) {
1151 r
= send_message(b
, userdata
);
1156 /* Send to API bus, but only if somebody is subscribed */
1157 if (sd_bus_track_count(m
->subscribed
) > 0 ||
1158 sd_bus_track_count(subscribed2
) > 0) {
1159 r
= send_message(m
->api_bus
, userdata
);
1167 void bus_track_serialize(sd_bus_track
*t
, FILE *f
, const char *prefix
) {
1173 for (n
= sd_bus_track_first(t
); n
; n
= sd_bus_track_next(t
)) {
1176 c
= sd_bus_track_count_name(t
, n
);
1178 for (j
= 0; j
< c
; j
++) {
1187 int bus_track_coldplug(Manager
*m
, sd_bus_track
**t
, bool recursive
, char **l
) {
1193 if (strv_isempty(l
))
1200 r
= sd_bus_track_new(m
->api_bus
, t
, NULL
, NULL
);
1205 r
= sd_bus_track_set_recursive(*t
, recursive
);
1209 return bus_track_add_name_many(*t
, l
);
1212 int bus_verify_manage_units_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1213 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.manage-units", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1216 int bus_verify_manage_unit_files_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1217 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.manage-unit-files", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1220 int bus_verify_reload_daemon_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1221 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.reload-daemon", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1224 int bus_verify_set_environment_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1225 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.set-environment", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);