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 static int signal_agent_released(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
75 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
76 const char *cgroup
, *me
;
77 Manager
*m
= userdata
;
85 /* ignore recursive events sent by us on the system/user bus */
86 bus
= sd_bus_message_get_bus(message
);
87 if (!sd_bus_is_server(bus
)) {
88 r
= sd_bus_get_unique_name(bus
, &me
);
92 if (streq_ptr(sd_bus_message_get_sender(message
), me
))
96 /* only accept org.freedesktop.systemd1.Agent from UID=0 */
97 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
101 r
= sd_bus_creds_get_euid(creds
, &sender_uid
);
102 if (r
< 0 || sender_uid
!= 0)
105 /* parse 'cgroup-empty' notification */
106 r
= sd_bus_message_read(message
, "s", &cgroup
);
108 bus_log_parse_error(r
);
112 manager_notify_cgroup_empty(m
, cgroup
);
114 /* if running as system-instance, forward under our name */
115 if (MANAGER_IS_SYSTEM(m
) && m
->system_bus
) {
116 r
= sd_bus_message_rewind(message
, 1);
118 r
= sd_bus_send(m
->system_bus
, message
, NULL
);
120 log_warning_errno(r
, "Failed to forward Released message: %m");
126 static int signal_disconnected(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
127 Manager
*m
= userdata
;
132 assert_se(bus
= sd_bus_message_get_bus(message
));
134 if (bus
== m
->api_bus
)
135 destroy_bus(m
, &m
->api_bus
);
136 if (bus
== m
->system_bus
)
137 destroy_bus(m
, &m
->system_bus
);
138 if (set_remove(m
->private_buses
, bus
)) {
139 log_debug("Got disconnect on private connection.");
140 destroy_bus(m
, &bus
);
146 static int signal_activation_request(sd_bus_message
*message
, void *userdata
, sd_bus_error
*ret_error
) {
147 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
148 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
149 Manager
*m
= userdata
;
157 r
= sd_bus_message_read(message
, "s", &name
);
159 bus_log_parse_error(r
);
163 if (manager_unit_inactive_or_pending(m
, SPECIAL_DBUS_SERVICE
) ||
164 manager_unit_inactive_or_pending(m
, SPECIAL_DBUS_SOCKET
)) {
165 r
= sd_bus_error_setf(&error
, BUS_ERROR_SHUTTING_DOWN
, "Refusing activation, D-Bus is shutting down.");
169 r
= manager_load_unit(m
, name
, NULL
, &error
, &u
);
173 if (u
->refuse_manual_start
) {
174 r
= sd_bus_error_setf(&error
, BUS_ERROR_ONLY_BY_DEPENDENCY
, "Operation refused, %s may be requested by dependency only.", u
->id
);
178 r
= manager_add_job(m
, JOB_START
, u
, JOB_REPLACE
, &error
, NULL
);
182 /* Successfully queued, that's it for us */
186 if (!sd_bus_error_is_set(&error
))
187 sd_bus_error_set_errno(&error
, r
);
189 log_debug("D-Bus activation failed for %s: %s", name
, bus_error_message(&error
, r
));
191 r
= sd_bus_message_new_signal(sd_bus_message_get_bus(message
), &reply
, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
193 bus_log_create_error(r
);
197 r
= sd_bus_message_append(reply
, "sss", name
, error
.name
, error
.message
);
199 bus_log_create_error(r
);
203 r
= sd_bus_send_to(NULL
, reply
, "org.freedesktop.DBus", NULL
);
205 return log_error_errno(r
, "Failed to respond with to bus activation request: %m");
211 static int mac_selinux_filter(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
212 Manager
*m
= userdata
;
213 const char *verb
, *path
;
220 /* Our own method calls are all protected individually with
221 * selinux checks, but the built-in interfaces need to be
224 if (sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Properties", "Set"))
226 else if (sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Introspectable", NULL
) ||
227 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Properties", NULL
) ||
228 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.ObjectManager", NULL
) ||
229 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Peer", NULL
))
234 path
= sd_bus_message_get_path(message
);
236 if (object_path_startswith("/org/freedesktop/systemd1", path
)) {
238 r
= mac_selinux_access_check(message
, verb
, error
);
245 if (streq_ptr(path
, "/org/freedesktop/systemd1/unit/self")) {
246 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
249 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
253 r
= sd_bus_creds_get_pid(creds
, &pid
);
257 u
= manager_get_unit_by_pid(m
, pid
);
259 r
= manager_get_job_from_dbus_path(m
, path
, &j
);
263 manager_load_unit_from_dbus_path(m
, path
, NULL
, &u
);
269 r
= mac_selinux_unit_access_check(u
, message
, verb
, error
);
277 static int bus_job_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
278 Manager
*m
= userdata
;
288 r
= manager_get_job_from_dbus_path(m
, path
, &j
);
296 static int find_unit(Manager
*m
, sd_bus
*bus
, const char *path
, Unit
**unit
, sd_bus_error
*error
) {
304 if (streq_ptr(path
, "/org/freedesktop/systemd1/unit/self")) {
305 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
306 sd_bus_message
*message
;
309 message
= sd_bus_get_current_message(bus
);
313 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
317 r
= sd_bus_creds_get_pid(creds
, &pid
);
321 u
= manager_get_unit_by_pid(m
, pid
);
323 r
= manager_load_unit_from_dbus_path(m
, path
, error
, &u
);
335 static int bus_unit_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
336 Manager
*m
= userdata
;
344 return find_unit(m
, bus
, path
, (Unit
**) found
, error
);
347 static int bus_unit_interface_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
348 Manager
*m
= userdata
;
358 r
= find_unit(m
, bus
, path
, &u
, error
);
362 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
369 static int bus_unit_cgroup_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
370 Manager
*m
= userdata
;
380 r
= find_unit(m
, bus
, path
, &u
, error
);
384 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
387 if (!UNIT_HAS_CGROUP_CONTEXT(u
))
394 static int bus_cgroup_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
395 Manager
*m
= userdata
;
406 r
= find_unit(m
, bus
, path
, &u
, error
);
410 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
413 c
= unit_get_cgroup_context(u
);
421 static int bus_exec_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
422 Manager
*m
= userdata
;
433 r
= find_unit(m
, bus
, path
, &u
, error
);
437 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
440 c
= unit_get_exec_context(u
);
448 static int bus_kill_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
449 Manager
*m
= userdata
;
460 r
= find_unit(m
, bus
, path
, &u
, error
);
464 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
467 c
= unit_get_kill_context(u
);
475 static int bus_job_enumerate(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
476 _cleanup_free_
char **l
= NULL
;
477 Manager
*m
= userdata
;
482 l
= new0(char*, hashmap_size(m
->jobs
)+1);
486 HASHMAP_FOREACH(j
, m
->jobs
, i
) {
487 l
[k
] = job_dbus_path(j
);
494 assert(hashmap_size(m
->jobs
) == k
);
502 static int bus_unit_enumerate(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
503 _cleanup_free_
char **l
= NULL
;
504 Manager
*m
= userdata
;
509 l
= new0(char*, hashmap_size(m
->units
)+1);
513 HASHMAP_FOREACH(u
, m
->units
, i
) {
514 l
[k
] = unit_dbus_path(u
);
527 static int bus_setup_api_vtables(Manager
*m
, sd_bus
*bus
) {
535 r
= sd_bus_add_filter(bus
, NULL
, mac_selinux_filter
, m
);
537 return log_error_errno(r
, "Failed to add SELinux access filter: %m");
540 r
= sd_bus_add_object_vtable(bus
, NULL
, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable
, m
);
542 return log_error_errno(r
, "Failed to register Manager vtable: %m");
544 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable
, bus_job_find
, m
);
546 return log_error_errno(r
, "Failed to register Job vtable: %m");
548 r
= sd_bus_add_node_enumerator(bus
, NULL
, "/org/freedesktop/systemd1/job", bus_job_enumerate
, m
);
550 return log_error_errno(r
, "Failed to add job enumerator: %m");
552 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable
, bus_unit_find
, m
);
554 return log_error_errno(r
, "Failed to register Unit vtable: %m");
556 r
= sd_bus_add_node_enumerator(bus
, NULL
, "/org/freedesktop/systemd1/unit", bus_unit_enumerate
, m
);
558 return log_error_errno(r
, "Failed to add job enumerator: %m");
560 for (t
= 0; t
< _UNIT_TYPE_MAX
; t
++) {
561 const char *interface
;
563 assert_se(interface
= unit_dbus_interface_from_type(t
));
565 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, unit_vtable
[t
]->bus_vtable
, bus_unit_interface_find
, m
);
567 return log_error_errno(r
, "Failed to register type specific vtable for %s: %m", interface
);
569 if (unit_vtable
[t
]->cgroup_context_offset
> 0) {
570 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_unit_cgroup_vtable
, bus_unit_cgroup_find
, m
);
572 return log_error_errno(r
, "Failed to register control group unit vtable for %s: %m", interface
);
574 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_cgroup_vtable
, bus_cgroup_context_find
, m
);
576 return log_error_errno(r
, "Failed to register control group vtable for %s: %m", interface
);
579 if (unit_vtable
[t
]->exec_context_offset
> 0) {
580 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_exec_vtable
, bus_exec_context_find
, m
);
582 return log_error_errno(r
, "Failed to register execute vtable for %s: %m", interface
);
585 if (unit_vtable
[t
]->kill_context_offset
> 0) {
586 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_kill_vtable
, bus_kill_context_find
, m
);
588 return log_error_errno(r
, "Failed to register kill vtable for %s: %m", interface
);
595 static int bus_setup_disconnected_match(Manager
*m
, sd_bus
*bus
) {
601 r
= sd_bus_add_match(
604 "sender='org.freedesktop.DBus.Local',"
606 "path='/org/freedesktop/DBus/Local',"
607 "interface='org.freedesktop.DBus.Local',"
608 "member='Disconnected'",
609 signal_disconnected
, m
);
612 return log_error_errno(r
, "Failed to register match for Disconnected message: %m");
617 static int bus_on_connection(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
618 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
619 _cleanup_close_
int nfd
= -1;
620 Manager
*m
= userdata
;
627 nfd
= accept4(fd
, NULL
, NULL
, SOCK_NONBLOCK
|SOCK_CLOEXEC
);
629 log_warning_errno(errno
, "Failed to accept private connection, ignoring: %m");
633 if (set_size(m
->private_buses
) >= CONNECTIONS_MAX
) {
634 log_warning("Too many concurrent connections, refusing");
638 r
= set_ensure_allocated(&m
->private_buses
, NULL
);
644 r
= sd_bus_new(&bus
);
646 log_warning_errno(r
, "Failed to allocate new private connection bus: %m");
650 r
= sd_bus_set_fd(bus
, nfd
, nfd
);
652 log_warning_errno(r
, "Failed to set fd on new connection bus: %m");
658 r
= bus_check_peercred(bus
);
660 log_warning_errno(r
, "Incoming private connection from unprivileged client, refusing: %m");
664 assert_se(sd_id128_randomize(&id
) >= 0);
666 r
= sd_bus_set_server(bus
, 1, id
);
668 log_warning_errno(r
, "Failed to enable server support for new connection bus: %m");
672 r
= sd_bus_negotiate_creds(bus
, 1,
673 SD_BUS_CREDS_PID
|SD_BUS_CREDS_UID
|
674 SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EFFECTIVE_CAPS
|
675 SD_BUS_CREDS_SELINUX_CONTEXT
);
677 log_warning_errno(r
, "Failed to enable credentials for new connection: %m");
681 r
= sd_bus_start(bus
);
683 log_warning_errno(r
, "Failed to start new connection bus: %m");
687 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
689 log_warning_errno(r
, "Failed to attach new connection bus to event loop: %m");
693 if (MANAGER_IS_SYSTEM(m
)) {
694 /* When we run as system instance we get the Released
695 * signal via a direct connection */
697 r
= sd_bus_add_match(
701 "interface='org.freedesktop.systemd1.Agent',"
703 "path='/org/freedesktop/systemd1/agent'",
704 signal_agent_released
, m
);
707 log_warning_errno(r
, "Failed to register Released match on new connection bus: %m");
712 r
= bus_setup_disconnected_match(m
, bus
);
716 r
= bus_setup_api_vtables(m
, bus
);
718 log_warning_errno(r
, "Failed to set up API vtables on new connection bus: %m");
722 r
= set_put(m
->private_buses
, bus
);
724 log_warning_errno(r
, "Failed to add new connection bus to set: %m");
730 log_debug("Accepted new private connection.");
735 int manager_sync_bus_names(Manager
*m
, sd_bus
*bus
) {
736 _cleanup_strv_free_
char **names
= NULL
;
745 r
= sd_bus_list_names(bus
, &names
, NULL
);
747 return log_error_errno(r
, "Failed to get initial list of names: %m");
749 /* We have to synchronize the current bus names with the
750 * list of active services. To do this, walk the list of
751 * all units with bus names. */
752 HASHMAP_FOREACH_KEY(u
, name
, m
->watch_bus
, i
) {
753 Service
*s
= SERVICE(u
);
757 if (!streq_ptr(s
->bus_name
, name
)) {
758 log_unit_warning(u
, "Bus name has changed from %s → %s, ignoring.", s
->bus_name
, name
);
762 /* Check if a service's bus name is in the list of currently
764 if (strv_contains(names
, name
)) {
765 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
768 /* If it is, determine its current owner */
769 r
= sd_bus_get_name_creds(bus
, name
, SD_BUS_CREDS_UNIQUE_NAME
, &creds
);
771 log_error_errno(r
, "Failed to get bus name owner %s: %m", name
);
775 r
= sd_bus_creds_get_unique_name(creds
, &unique
);
777 log_error_errno(r
, "Failed to get unique name for %s: %m", name
);
781 /* Now, let's compare that to the previous bus owner, and
782 * if it's still the same, all is fine, so just don't
783 * bother the service. Otherwise, the name has apparently
784 * changed, so synthesize a name owner changed signal. */
786 if (!streq_ptr(unique
, s
->bus_name_owner
))
787 UNIT_VTABLE(u
)->bus_name_owner_change(u
, name
, s
->bus_name_owner
, unique
);
789 /* So, the name we're watching is not on the bus.
790 * This either means it simply hasn't appeared yet,
791 * or it was lost during the daemon reload.
792 * Check if the service has a stored name owner,
793 * and synthesize a name loss signal in this case. */
795 if (s
->bus_name_owner
)
796 UNIT_VTABLE(u
)->bus_name_owner_change(u
, name
, s
->bus_name_owner
, NULL
);
803 static int bus_setup_api(Manager
*m
, sd_bus
*bus
) {
812 /* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
813 r
= sd_bus_negotiate_creds(bus
, 1,
814 SD_BUS_CREDS_PID
|SD_BUS_CREDS_UID
|
815 SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EFFECTIVE_CAPS
|
816 SD_BUS_CREDS_SELINUX_CONTEXT
);
818 log_warning_errno(r
, "Failed to enable credential passing, ignoring: %m");
820 r
= bus_setup_api_vtables(m
, bus
);
824 HASHMAP_FOREACH_KEY(u
, name
, m
->watch_bus
, i
) {
825 r
= unit_install_bus_match(u
, bus
, name
);
827 log_error_errno(r
, "Failed to subscribe to NameOwnerChanged signal for '%s': %m", name
);
830 r
= sd_bus_add_match(
834 "sender='org.freedesktop.DBus',"
835 "path='/org/freedesktop/DBus',"
836 "interface='org.freedesktop.systemd1.Activator',"
837 "member='ActivationRequest'",
838 signal_activation_request
, m
);
840 log_warning_errno(r
, "Failed to subscribe to activation signal: %m");
842 /* Allow replacing of our name, to ease implementation of
843 * reexecution, where we keep the old connection open until
844 * after the new connection is set up and the name installed
845 * to allow clients to synchronously wait for reexecution to
847 r
= sd_bus_request_name(bus
,"org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING
|SD_BUS_NAME_ALLOW_REPLACEMENT
);
849 return log_error_errno(r
, "Failed to register name: %m");
851 r
= manager_sync_bus_names(m
, bus
);
855 log_debug("Successfully connected to API bus.");
859 static int bus_init_api(Manager
*m
) {
860 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
866 /* The API and system bus is the same if we are running in system mode */
867 if (MANAGER_IS_SYSTEM(m
) && m
->system_bus
)
868 bus
= sd_bus_ref(m
->system_bus
);
870 if (MANAGER_IS_SYSTEM(m
))
871 r
= sd_bus_open_system(&bus
);
873 r
= sd_bus_open_user(&bus
);
876 log_debug("Failed to connect to API bus, retrying later...");
880 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
882 log_error_errno(r
, "Failed to attach API bus to event loop: %m");
886 r
= bus_setup_disconnected_match(m
, bus
);
891 r
= bus_setup_api(m
, bus
);
893 log_error_errno(r
, "Failed to set up API bus: %m");
903 static int bus_setup_system(Manager
*m
, sd_bus
*bus
) {
909 /* On kdbus or if we are a user instance we get the Released message via the system bus */
910 if (MANAGER_IS_USER(m
) || m
->kdbus_fd
>= 0) {
911 r
= sd_bus_add_match(
915 "interface='org.freedesktop.systemd1.Agent',"
917 "path='/org/freedesktop/systemd1/agent'",
918 signal_agent_released
, m
);
920 log_warning_errno(r
, "Failed to register Released match on system bus: %m");
923 log_debug("Successfully connected to system bus.");
927 static int bus_init_system(Manager
*m
) {
928 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
934 /* The API and system bus is the same if we are running in system mode */
935 if (MANAGER_IS_SYSTEM(m
) && m
->api_bus
) {
936 m
->system_bus
= sd_bus_ref(m
->api_bus
);
940 r
= sd_bus_open_system(&bus
);
942 log_debug("Failed to connect to system bus, retrying later...");
946 r
= bus_setup_disconnected_match(m
, bus
);
950 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
952 log_error_errno(r
, "Failed to attach system bus to event loop: %m");
956 r
= bus_setup_system(m
, bus
);
958 log_error_errno(r
, "Failed to set up system bus: %m");
968 static int bus_init_private(Manager
*m
) {
969 _cleanup_close_
int fd
= -1;
970 union sockaddr_union sa
= {
971 .un
.sun_family
= AF_UNIX
979 if (m
->private_listen_fd
>= 0)
982 /* We don't need the private socket if we have kdbus */
983 if (m
->kdbus_fd
>= 0)
986 if (MANAGER_IS_SYSTEM(m
)) {
988 /* We want the private bus only when running as init */
992 strcpy(sa
.un
.sun_path
, "/run/systemd/private");
993 salen
= offsetof(union sockaddr_union
, un
.sun_path
) + strlen("/run/systemd/private");
995 size_t left
= sizeof(sa
.un
.sun_path
);
996 char *p
= sa
.un
.sun_path
;
999 e
= secure_getenv("XDG_RUNTIME_DIR");
1001 log_error("Failed to determine XDG_RUNTIME_DIR");
1005 left
= strpcpy(&p
, left
, e
);
1006 left
= strpcpy(&p
, left
, "/systemd/private");
1008 salen
= sizeof(sa
.un
) - left
;
1011 (void) mkdir_parents_label(sa
.un
.sun_path
, 0755);
1012 (void) unlink(sa
.un
.sun_path
);
1014 fd
= socket(AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0);
1016 return log_error_errno(errno
, "Failed to allocate private socket: %m");
1018 r
= bind(fd
, &sa
.sa
, salen
);
1020 return log_error_errno(errno
, "Failed to bind private socket: %m");
1022 r
= listen(fd
, SOMAXCONN
);
1024 return log_error_errno(errno
, "Failed to make private socket listening: %m");
1026 r
= sd_event_add_io(m
->event
, &s
, fd
, EPOLLIN
, bus_on_connection
, m
);
1028 return log_error_errno(r
, "Failed to allocate event source: %m");
1030 (void) sd_event_source_set_description(s
, "bus-connection");
1032 m
->private_listen_fd
= fd
;
1033 m
->private_listen_event_source
= s
;
1036 log_debug("Successfully created private D-Bus server.");
1041 int bus_init(Manager
*m
, bool try_bus_connect
) {
1044 if (try_bus_connect
) {
1045 r
= bus_init_system(m
);
1049 r
= bus_init_api(m
);
1054 r
= bus_init_private(m
);
1061 static void destroy_bus(Manager
*m
, sd_bus
**bus
) {
1071 /* Get rid of tracked clients on this bus */
1072 if (m
->subscribed
&& sd_bus_track_get_bus(m
->subscribed
) == *bus
)
1073 m
->subscribed
= sd_bus_track_unref(m
->subscribed
);
1075 HASHMAP_FOREACH(j
, m
->jobs
, i
)
1076 if (j
->clients
&& sd_bus_track_get_bus(j
->clients
) == *bus
)
1077 j
->clients
= sd_bus_track_unref(j
->clients
);
1079 /* Get rid of queued message on this bus */
1080 if (m
->queued_message
&& sd_bus_message_get_bus(m
->queued_message
) == *bus
)
1081 m
->queued_message
= sd_bus_message_unref(m
->queued_message
);
1083 /* Possibly flush unwritten data, but only if we are
1084 * unprivileged, since we don't want to sync here */
1085 if (!MANAGER_IS_SYSTEM(m
))
1088 /* And destroy the object */
1090 *bus
= sd_bus_unref(*bus
);
1093 void bus_done(Manager
*m
) {
1099 destroy_bus(m
, &m
->api_bus
);
1101 destroy_bus(m
, &m
->system_bus
);
1102 while ((b
= set_steal_first(m
->private_buses
)))
1105 m
->private_buses
= set_free(m
->private_buses
);
1107 m
->subscribed
= sd_bus_track_unref(m
->subscribed
);
1108 m
->deserialized_subscribed
= strv_free(m
->deserialized_subscribed
);
1110 if (m
->private_listen_event_source
)
1111 m
->private_listen_event_source
= sd_event_source_unref(m
->private_listen_event_source
);
1113 m
->private_listen_fd
= safe_close(m
->private_listen_fd
);
1115 bus_verify_polkit_async_registry_free(m
->polkit_registry
);
1118 int bus_fdset_add_all(Manager
*m
, FDSet
*fds
) {
1126 /* When we are about to reexecute we add all D-Bus fds to the
1127 * set to pass over to the newly executed systemd. They won't
1128 * be used there however, except thatt they are closed at the
1129 * very end of deserialization, those making it possible for
1130 * clients to synchronously wait for systemd to reexec by
1131 * simply waiting for disconnection */
1134 fd
= sd_bus_get_fd(m
->api_bus
);
1136 fd
= fdset_put_dup(fds
, fd
);
1142 SET_FOREACH(b
, m
->private_buses
, i
) {
1143 fd
= sd_bus_get_fd(b
);
1145 fd
= fdset_put_dup(fds
, fd
);
1151 /* We don't offer any APIs on the system bus (well, unless it
1152 * is the same as the API bus) hence we don't bother with it
1158 int bus_foreach_bus(
1160 sd_bus_track
*subscribed2
,
1161 int (*send_message
)(sd_bus
*bus
, void *userdata
),
1168 /* Send to all direct buses, unconditionally */
1169 SET_FOREACH(b
, m
->private_buses
, i
) {
1170 r
= send_message(b
, userdata
);
1175 /* Send to API bus, but only if somebody is subscribed */
1176 if (sd_bus_track_count(m
->subscribed
) > 0 ||
1177 sd_bus_track_count(subscribed2
) > 0) {
1178 r
= send_message(m
->api_bus
, userdata
);
1186 void bus_track_serialize(sd_bus_track
*t
, FILE *f
) {
1191 for (n
= sd_bus_track_first(t
); n
; n
= sd_bus_track_next(t
))
1192 fprintf(f
, "subscribed=%s\n", n
);
1195 int bus_track_deserialize_item(char ***l
, const char *line
) {
1202 e
= startswith(line
, "subscribed=");
1206 r
= strv_extend(l
, e
);
1213 int bus_track_coldplug(Manager
*m
, sd_bus_track
**t
, char ***l
) {
1220 if (!strv_isempty(*l
) && m
->api_bus
) {
1224 r
= sd_bus_track_new(m
->api_bus
, t
, NULL
, NULL
);
1230 STRV_FOREACH(i
, *l
) {
1233 k
= sd_bus_track_add_name(*t
, *i
);
1244 int bus_verify_manage_units_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1245 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.manage-units", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1248 int bus_verify_manage_unit_files_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1249 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.manage-unit-files", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1252 int bus_verify_reload_daemon_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1253 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.reload-daemon", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1256 int bus_verify_set_environment_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1257 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.set-environment", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);