]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus.c
223c0b79d217c0049be45460c121f79781fe5ae9
[thirdparty/systemd.git] / src / core / dbus.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <unistd.h>
4
5 #include "sd-bus.h"
6 #include "sd-id128.h"
7
8 #include "alloc-util.h"
9 #include "bus-common-errors.h"
10 #include "bus-error.h"
11 #include "bus-internal.h"
12 #include "bus-object.h"
13 #include "bus-util.h"
14 #include "dbus.h"
15 #include "dbus-automount.h"
16 #include "dbus-cgroup.h"
17 #include "dbus-device.h"
18 #include "dbus-execute.h"
19 #include "dbus-job.h"
20 #include "dbus-kill.h"
21 #include "dbus-manager.h"
22 #include "dbus-mount.h"
23 #include "dbus-path.h"
24 #include "dbus-scope.h"
25 #include "dbus-service.h"
26 #include "dbus-slice.h"
27 #include "dbus-socket.h"
28 #include "dbus-swap.h"
29 #include "dbus-target.h"
30 #include "dbus-timer.h"
31 #include "dbus-unit.h"
32 #include "errno-util.h"
33 #include "fd-util.h"
34 #include "fdset.h"
35 #include "format-util.h"
36 #include "fs-util.h"
37 #include "log.h"
38 #include "manager.h"
39 #include "path-util.h"
40 #include "pidref.h"
41 #include "process-util.h"
42 #include "selinux-access.h"
43 #include "serialize.h"
44 #include "set.h"
45 #include "special.h"
46 #include "string-util.h"
47 #include "strv.h"
48 #include "umask-util.h"
49
50 #define CONNECTIONS_MAX 4096
51
52 static void destroy_bus(Manager *m, sd_bus **bus);
53
54 void bus_send_pending_reload_message(Manager *m) {
55 int r;
56
57 assert(m);
58
59 if (!m->pending_reload_message)
60 return;
61
62 /* If we cannot get rid of this message we won't dispatch any D-Bus messages, so that we won't end up wanting
63 * to queue another message. */
64
65 r = sd_bus_message_send(m->pending_reload_message);
66 if (r < 0)
67 log_warning_errno(r, "Failed to send queued reload message, ignoring: %m");
68
69 m->pending_reload_message = sd_bus_message_unref(m->pending_reload_message);
70
71 return;
72 }
73
74 static int signal_disconnected(sd_bus_message *message, void *userdata, sd_bus_error *error) {
75 Manager *m = ASSERT_PTR(userdata);
76 sd_bus *bus;
77
78 assert(message);
79 assert_se(bus = sd_bus_message_get_bus(message));
80
81 if (bus == m->api_bus) {
82 log_notice("Got disconnect on API bus.");
83 bus_done_api(m);
84 }
85 if (bus == m->system_bus) {
86 /* If we are the system manager, this is already logged by the API bus. */
87 if (!MANAGER_IS_SYSTEM(m))
88 log_notice("Got disconnect on system bus.");
89 bus_done_system(m);
90 }
91
92 if (set_remove(m->private_buses, bus)) {
93 log_debug("Got disconnect on private connection.");
94 destroy_bus(m, &bus);
95 }
96
97 return 0;
98 }
99
100 static int signal_activation_request(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
101 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
102 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
103 Manager *m = ASSERT_PTR(userdata);
104 const char *name;
105 Unit *u;
106 int r;
107
108 assert(message);
109
110 r = sd_bus_message_read(message, "s", &name);
111 if (r < 0) {
112 bus_log_parse_error(r);
113 return 0;
114 }
115
116 if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET) ||
117 manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE)) {
118 r = sd_bus_error_set(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
119 goto failed;
120 }
121
122 r = manager_load_unit(m, name, NULL, &error, &u);
123 if (r < 0)
124 goto failed;
125
126 if (u->refuse_manual_start) {
127 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);
128 goto failed;
129 }
130
131 r = manager_add_job(m, JOB_START, u, JOB_REPLACE, &error, /* ret = */ NULL);
132 if (r < 0)
133 goto failed;
134
135 /* Successfully queued, that's it for us */
136 return 0;
137
138 failed:
139 if (!sd_bus_error_is_set(&error))
140 sd_bus_error_set_errno(&error, r);
141
142 log_debug("D-Bus activation failed for %s: %s", name, bus_error_message(&error, r));
143
144 r = sd_bus_message_new_signal(sd_bus_message_get_bus(message), &reply, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
145 if (r < 0) {
146 bus_log_create_error(r);
147 return 0;
148 }
149
150 r = sd_bus_message_append(reply, "sss", name, error.name, error.message);
151 if (r < 0) {
152 bus_log_create_error(r);
153 return 0;
154 }
155
156 r = sd_bus_send_to(NULL, reply, "org.freedesktop.DBus", NULL);
157 if (r < 0)
158 return log_error_errno(r, "Failed to respond with to bus activation request: %m");
159
160 return 0;
161 }
162
163 #if HAVE_SELINUX
164 static int mac_selinux_filter(sd_bus_message *message, void *userdata, sd_bus_error *error) {
165 Manager *m = userdata;
166 const char *verb, *path;
167 Unit *u = NULL;
168 Job *j;
169 int r;
170
171 assert(message);
172
173 /* Our own method calls are all protected individually with
174 * selinux checks, but the built-in interfaces need to be
175 * protected too. */
176
177 if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set"))
178 verb = "reload";
179 else if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", NULL) ||
180 sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", NULL) ||
181 sd_bus_message_is_method_call(message, "org.freedesktop.DBus.ObjectManager", NULL) ||
182 sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Peer", NULL))
183 verb = "status";
184 else
185 return 0;
186
187 path = sd_bus_message_get_path(message);
188 if (!path)
189 return 0;
190
191 if (object_path_startswith("/org/freedesktop/systemd1", path)) {
192 r = mac_selinux_access_check(message, verb, error);
193 if (r < 0)
194 return r;
195
196 return 0;
197 }
198
199 if (streq(path, "/org/freedesktop/systemd1/unit/self")) {
200 _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
201
202 r = bus_query_sender_pidref(message, &pidref);
203 if (r < 0)
204 return 0;
205
206 u = manager_get_unit_by_pidref(m, &pidref);
207 } else {
208 r = manager_get_job_from_dbus_path(m, path, &j);
209 if (r >= 0)
210 u = j->unit;
211 else
212 (void) manager_load_unit_from_dbus_path(m, path, NULL, &u);
213 }
214 if (!u)
215 return 0;
216
217 r = mac_selinux_unit_access_check(u, message, verb, error);
218 if (r < 0)
219 return r;
220
221 return 0;
222 }
223 #endif
224
225 static int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_bus_error *error) {
226 Unit *u = NULL; /* just to appease gcc, initialization is not really necessary */
227 int r;
228
229 assert(m);
230 assert(bus);
231 assert(path);
232
233 if (streq(path, "/org/freedesktop/systemd1/unit/self")) {
234 _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
235 sd_bus_message *message;
236
237 message = sd_bus_get_current_message(bus);
238 if (!message)
239 return 0;
240
241 r = bus_query_sender_pidref(message, &pidref);
242 if (r < 0)
243 return r;
244
245 u = manager_get_unit_by_pidref(m, &pidref);
246 if (!u)
247 return 0;
248 } else {
249 r = manager_load_unit_from_dbus_path(m, path, error, &u);
250 if (r < 0)
251 return 0;
252 assert(u);
253 }
254
255 *unit = u;
256 return 1;
257 }
258
259 static int bus_unit_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
260 Manager *m = ASSERT_PTR(userdata);
261
262 assert(bus);
263 assert(path);
264 assert(interface);
265 assert(found);
266
267 return find_unit(m, bus, path, (Unit**) found, error);
268 }
269
270 static int bus_unit_interface_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
271 Manager *m = ASSERT_PTR(userdata);
272 Unit *u;
273 int r;
274
275 assert(bus);
276 assert(path);
277 assert(interface);
278 assert(found);
279
280 r = find_unit(m, bus, path, &u, error);
281 if (r <= 0)
282 return r;
283
284 if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
285 return 0;
286
287 *found = u;
288 return 1;
289 }
290
291 static int bus_unit_cgroup_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
292 Manager *m = ASSERT_PTR(userdata);
293 Unit *u;
294 int r;
295
296 assert(bus);
297 assert(path);
298 assert(interface);
299 assert(found);
300
301 r = find_unit(m, bus, path, &u, error);
302 if (r <= 0)
303 return r;
304
305 if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
306 return 0;
307
308 if (!UNIT_HAS_CGROUP_CONTEXT(u))
309 return 0;
310
311 *found = u;
312 return 1;
313 }
314
315 static int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
316 Manager *m = ASSERT_PTR(userdata);
317 CGroupContext *c;
318 Unit *u;
319 int r;
320
321 assert(bus);
322 assert(path);
323 assert(interface);
324 assert(found);
325
326 r = find_unit(m, bus, path, &u, error);
327 if (r <= 0)
328 return r;
329
330 if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
331 return 0;
332
333 c = unit_get_cgroup_context(u);
334 if (!c)
335 return 0;
336
337 *found = c;
338 return 1;
339 }
340
341 static int bus_exec_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
342 Manager *m = ASSERT_PTR(userdata);
343 ExecContext *c;
344 Unit *u;
345 int r;
346
347 assert(bus);
348 assert(path);
349 assert(interface);
350 assert(found);
351
352 r = find_unit(m, bus, path, &u, error);
353 if (r <= 0)
354 return r;
355
356 if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
357 return 0;
358
359 c = unit_get_exec_context(u);
360 if (!c)
361 return 0;
362
363 *found = c;
364 return 1;
365 }
366
367 static int bus_kill_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
368 Manager *m = ASSERT_PTR(userdata);
369 KillContext *c;
370 Unit *u;
371 int r;
372
373 assert(bus);
374 assert(path);
375 assert(interface);
376 assert(found);
377
378 r = find_unit(m, bus, path, &u, error);
379 if (r <= 0)
380 return r;
381
382 if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
383 return 0;
384
385 c = unit_get_kill_context(u);
386 if (!c)
387 return 0;
388
389 *found = c;
390 return 1;
391 }
392
393 static int bus_unit_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
394 _cleanup_strv_free_ char **l = NULL;
395 Manager *m = userdata;
396 unsigned k = 0;
397 Unit *u;
398
399 l = new0(char*, hashmap_size(m->units)+1);
400 if (!l)
401 return -ENOMEM;
402
403 HASHMAP_FOREACH(u, m->units) {
404 l[k] = unit_dbus_path(u);
405 if (!l[k])
406 return -ENOMEM;
407
408 k++;
409 }
410
411 *nodes = TAKE_PTR(l);
412
413 return k;
414 }
415
416 static const BusObjectImplementation unit_object = {
417 "/org/freedesktop/systemd1/unit",
418 "org.freedesktop.systemd1.Unit",
419 .fallback_vtables = BUS_FALLBACK_VTABLES(
420 { bus_unit_vtable, bus_unit_find }),
421 .node_enumerator = bus_unit_enumerate,
422 };
423
424 static const BusObjectImplementation bus_automount_object = {
425 "/org/freedesktop/systemd1/unit",
426 "org.freedesktop.systemd1.Automount",
427 .fallback_vtables = BUS_FALLBACK_VTABLES(
428 { bus_automount_vtable, bus_unit_interface_find }),
429 };
430
431 static const BusObjectImplementation bus_device_object = {
432 "/org/freedesktop/systemd1/unit",
433 "org.freedesktop.systemd1.Device",
434 .fallback_vtables = BUS_FALLBACK_VTABLES(
435 { bus_device_vtable, bus_unit_interface_find }),
436 };
437
438 static const BusObjectImplementation bus_mount_object = {
439 "/org/freedesktop/systemd1/unit",
440 "org.freedesktop.systemd1.Mount",
441 .fallback_vtables = BUS_FALLBACK_VTABLES(
442 { bus_mount_vtable, bus_unit_interface_find },
443 { bus_unit_cgroup_vtable, bus_unit_cgroup_find },
444 { bus_cgroup_vtable, bus_cgroup_context_find },
445 { bus_exec_vtable, bus_exec_context_find },
446 { bus_kill_vtable, bus_kill_context_find }),
447 };
448
449 static const BusObjectImplementation bus_path_object = {
450 "/org/freedesktop/systemd1/unit",
451 "org.freedesktop.systemd1.Path",
452 .fallback_vtables = BUS_FALLBACK_VTABLES(
453 { bus_path_vtable, bus_unit_interface_find }),
454 };
455
456 static const BusObjectImplementation bus_scope_object = {
457 "/org/freedesktop/systemd1/unit",
458 "org.freedesktop.systemd1.Scope",
459 .fallback_vtables = BUS_FALLBACK_VTABLES(
460 { bus_scope_vtable, bus_unit_interface_find },
461 { bus_unit_cgroup_vtable, bus_unit_cgroup_find },
462 { bus_cgroup_vtable, bus_cgroup_context_find },
463 { bus_kill_vtable, bus_kill_context_find }),
464 };
465
466 static const BusObjectImplementation bus_service_object = {
467 "/org/freedesktop/systemd1/unit",
468 "org.freedesktop.systemd1.Service",
469 .fallback_vtables = BUS_FALLBACK_VTABLES(
470 { bus_service_vtable, bus_unit_interface_find },
471 { bus_unit_cgroup_vtable, bus_unit_cgroup_find },
472 { bus_cgroup_vtable, bus_cgroup_context_find },
473 { bus_exec_vtable, bus_exec_context_find },
474 { bus_kill_vtable, bus_kill_context_find }),
475 };
476
477 static const BusObjectImplementation bus_slice_object = {
478 "/org/freedesktop/systemd1/unit",
479 "org.freedesktop.systemd1.Slice",
480 .fallback_vtables = BUS_FALLBACK_VTABLES(
481 { bus_slice_vtable, bus_unit_interface_find },
482 { bus_unit_cgroup_vtable, bus_unit_cgroup_find },
483 { bus_cgroup_vtable, bus_cgroup_context_find }),
484 };
485
486 static const BusObjectImplementation bus_socket_object = {
487 "/org/freedesktop/systemd1/unit",
488 "org.freedesktop.systemd1.Socket",
489 .fallback_vtables = BUS_FALLBACK_VTABLES(
490 { bus_socket_vtable, bus_unit_interface_find },
491 { bus_unit_cgroup_vtable, bus_unit_cgroup_find },
492 { bus_cgroup_vtable, bus_cgroup_context_find },
493 { bus_exec_vtable, bus_exec_context_find },
494 { bus_kill_vtable, bus_kill_context_find }),
495 };
496
497 static const BusObjectImplementation bus_swap_object = {
498 "/org/freedesktop/systemd1/unit",
499 "org.freedesktop.systemd1.Swap",
500 .fallback_vtables = BUS_FALLBACK_VTABLES(
501 { bus_swap_vtable, bus_unit_interface_find },
502 { bus_unit_cgroup_vtable, bus_unit_cgroup_find },
503 { bus_cgroup_vtable, bus_cgroup_context_find },
504 { bus_exec_vtable, bus_exec_context_find },
505 { bus_kill_vtable, bus_kill_context_find }),
506 };
507
508 static const BusObjectImplementation bus_target_object = {
509 "/org/freedesktop/systemd1/unit",
510 "org.freedesktop.systemd1.Target",
511 .fallback_vtables = BUS_FALLBACK_VTABLES(
512 { bus_target_vtable, bus_unit_interface_find }),
513 };
514
515 static const BusObjectImplementation bus_timer_object = {
516 "/org/freedesktop/systemd1/unit",
517 "org.freedesktop.systemd1.Timer",
518 .fallback_vtables = BUS_FALLBACK_VTABLES(
519 { bus_timer_vtable, bus_unit_interface_find }),
520 };
521
522 static const BusObjectImplementation bus_manager_object = {
523 "/org/freedesktop/systemd1",
524 "org.freedesktop.systemd1.Manager",
525 .vtables = BUS_VTABLES(bus_manager_vtable),
526 .children = BUS_IMPLEMENTATIONS(
527 &job_object,
528 &unit_object,
529 &bus_automount_object,
530 &bus_device_object,
531 &bus_mount_object,
532 &bus_path_object,
533 &bus_scope_object,
534 &bus_service_object,
535 &bus_slice_object,
536 &bus_socket_object,
537 &bus_swap_object,
538 &bus_target_object,
539 &bus_timer_object),
540 };
541
542 static const BusObjectImplementation manager_log_control_object = {
543 "/org/freedesktop/LogControl1",
544 "org.freedesktop.LogControl1",
545 .vtables = BUS_VTABLES(bus_manager_log_control_vtable),
546 };
547
548 int bus_manager_introspect_implementations(FILE *out, const char *pattern) {
549 return bus_introspect_implementations(
550 out,
551 pattern,
552 BUS_IMPLEMENTATIONS(&bus_manager_object,
553 &manager_log_control_object));
554 }
555
556 static int bus_setup_api_vtables(Manager *m, sd_bus *bus) {
557 int r;
558
559 assert(m);
560 assert(bus);
561
562 #if HAVE_SELINUX
563 r = sd_bus_add_filter(bus, NULL, mac_selinux_filter, m);
564 if (r < 0)
565 return log_error_errno(r, "Failed to add SELinux access filter: %m");
566 #endif
567
568 r = bus_add_implementation(bus, &bus_manager_object, m);
569 if (r < 0)
570 return r;
571
572 return bus_add_implementation(bus, &manager_log_control_object, m);
573 }
574
575 static int bus_setup_disconnected_match(Manager *m, sd_bus *bus) {
576 int r;
577
578 assert(m);
579 assert(bus);
580
581 r = sd_bus_match_signal_async(
582 bus,
583 NULL,
584 "org.freedesktop.DBus.Local",
585 "/org/freedesktop/DBus/Local",
586 "org.freedesktop.DBus.Local",
587 "Disconnected",
588 signal_disconnected, NULL, m);
589 if (r < 0)
590 return log_error_errno(r, "Failed to request match for Disconnected message: %m");
591
592 return 0;
593 }
594
595 static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
596 _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
597 _cleanup_close_ int nfd = -EBADF;
598 Manager *m = ASSERT_PTR(userdata);
599 sd_id128_t id;
600 int r;
601
602 assert(s);
603
604 nfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
605 if (nfd < 0) {
606 if (ERRNO_IS_ACCEPT_AGAIN(errno))
607 return 0;
608
609 log_warning_errno(errno, "Failed to accept private connection, ignoring: %m");
610 return 0;
611 }
612
613 if (set_size(m->private_buses) >= CONNECTIONS_MAX) {
614 log_warning("Too many concurrent connections, refusing");
615 return 0;
616 }
617
618 r = sd_bus_new(&bus);
619 if (r < 0) {
620 log_warning_errno(r, "Failed to allocate new private connection bus: %m");
621 return 0;
622 }
623
624 (void) sd_bus_set_description(bus, "private-bus-connection");
625
626 r = sd_bus_set_fd(bus, nfd, nfd);
627 if (r < 0) {
628 log_warning_errno(r, "Failed to set fd on new connection bus: %m");
629 return 0;
630 }
631
632 TAKE_FD(nfd);
633
634 r = bus_check_peercred(bus);
635 if (r < 0) {
636 log_warning_errno(r, "Incoming private connection from unprivileged client, refusing: %m");
637 return 0;
638 }
639
640 assert_se(sd_id128_randomize(&id) >= 0);
641
642 r = sd_bus_set_server(bus, 1, id);
643 if (r < 0) {
644 log_warning_errno(r, "Failed to enable server support for new connection bus: %m");
645 return 0;
646 }
647
648 r = sd_bus_negotiate_creds(bus, 1,
649 SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|
650 SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS|
651 SD_BUS_CREDS_SELINUX_CONTEXT|
652 SD_BUS_CREDS_COMM|SD_BUS_CREDS_DESCRIPTION);
653 if (r < 0) {
654 log_warning_errno(r, "Failed to enable credentials for new connection: %m");
655 return 0;
656 }
657
658 r = sd_bus_set_sender(bus, "org.freedesktop.systemd1");
659 if (r < 0) {
660 log_warning_errno(r, "Failed to set direct connection sender: %m");
661 return 0;
662 }
663
664 r = sd_bus_start(bus);
665 if (r < 0) {
666 log_warning_errno(r, "Failed to start new connection bus: %m");
667 return 0;
668 }
669
670 if (DEBUG_LOGGING) {
671 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
672 const char *comm = NULL, *description = NULL;
673 pid_t pid = 0;
674
675 r = sd_bus_get_owner_creds(bus, SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|SD_BUS_CREDS_DESCRIPTION, &c);
676 if (r < 0)
677 log_warning_errno(r, "Failed to get peer creds, ignoring: %m");
678 else {
679 (void) sd_bus_creds_get_pid(c, &pid);
680 (void) sd_bus_creds_get_comm(c, &comm);
681 (void) sd_bus_creds_get_description(c, &description);
682 }
683
684 log_debug("Accepting direct incoming connection from " PID_FMT " (%s) [%s]", pid, strna(comm), strna(description));
685 }
686
687 r = sd_bus_attach_event(bus, m->event, EVENT_PRIORITY_IPC);
688 if (r < 0) {
689 log_warning_errno(r, "Failed to attach new connection bus to event loop: %m");
690 return 0;
691 }
692
693 r = bus_setup_disconnected_match(m, bus);
694 if (r < 0)
695 return 0;
696
697 r = bus_setup_api_vtables(m, bus);
698 if (r < 0) {
699 log_warning_errno(r, "Failed to set up API vtables on new connection bus: %m");
700 return 0;
701 }
702
703 r = bus_register_malloc_status(bus, "org.freedesktop.systemd1");
704 if (r < 0)
705 log_warning_errno(r, "Failed to register MemoryAllocation1, ignoring: %m");
706
707 r = set_ensure_put(&m->private_buses, NULL, bus);
708 if (r == -ENOMEM) {
709 log_oom();
710 return 0;
711 }
712 if (r < 0) {
713 log_warning_errno(r, "Failed to add new connection bus to set: %m");
714 return 0;
715 }
716
717 TAKE_PTR(bus);
718
719 log_debug("Accepted new private connection.");
720
721 return 0;
722 }
723
724 static int bus_track_coldplug(sd_bus *bus, sd_bus_track **t, char * const *l) {
725 int r;
726
727 assert(bus);
728 assert(t);
729
730 if (strv_isempty(l))
731 return 0;
732
733 if (!*t) {
734 r = sd_bus_track_new(bus, t, NULL, NULL);
735 if (r < 0)
736 return r;
737 }
738
739 return bus_track_add_name_many(*t, l);
740 }
741
742 static int bus_setup_api(Manager *m, sd_bus *bus) {
743 char *name;
744 Unit *u;
745 int r;
746
747 assert(m);
748 assert(bus);
749
750 /* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
751 r = sd_bus_negotiate_creds(bus, 1,
752 SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|
753 SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS|
754 SD_BUS_CREDS_SELINUX_CONTEXT);
755 if (r < 0)
756 log_warning_errno(r, "Failed to enable credential passing, ignoring: %m");
757
758 r = bus_setup_api_vtables(m, bus);
759 if (r < 0)
760 return r;
761
762 HASHMAP_FOREACH_KEY(u, name, m->watch_bus) {
763 r = unit_install_bus_match(u, bus, name);
764 if (r < 0)
765 log_error_errno(r, "Failed to subscribe to NameOwnerChanged signal for '%s': %m", name);
766 }
767
768 r = sd_bus_match_signal_async(
769 bus,
770 NULL,
771 "org.freedesktop.DBus",
772 "/org/freedesktop/DBus",
773 "org.freedesktop.systemd1.Activator",
774 "ActivationRequest",
775 signal_activation_request, NULL, m);
776 if (r < 0)
777 log_warning_errno(r, "Failed to subscribe to activation signal: %m");
778
779 /* Allow replacing of our name, to ease implementation of reexecution, where we keep the old connection open
780 * until after the new connection is set up and the name installed to allow clients to synchronously wait for
781 * reexecution to finish */
782 r = sd_bus_request_name_async(bus, NULL, "org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_ALLOW_REPLACEMENT, NULL, NULL);
783 if (r < 0)
784 return log_error_errno(r, "Failed to request name: %m");
785
786 r = bus_register_malloc_status(bus, "org.freedesktop.systemd1");
787 if (r < 0)
788 log_warning_errno(r, "Failed to register MemoryAllocation1, ignoring: %m");
789
790 log_debug("Successfully connected to API bus.");
791
792 return 0;
793 }
794
795 int bus_init_api(Manager *m) {
796 _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
797 int r;
798
799 assert(m);
800
801 if (m->api_bus)
802 return 0;
803
804 /* The API and system bus is the same if we are running in system mode */
805 if (MANAGER_IS_SYSTEM(m) && m->system_bus)
806 bus = sd_bus_ref(m->system_bus);
807 else {
808 if (MANAGER_IS_SYSTEM(m))
809 r = sd_bus_open_system_with_description(&bus, "bus-api-system");
810 else
811 r = sd_bus_open_user_with_description(&bus, "bus-api-user");
812 if (r < 0)
813 return log_error_errno(r, "Failed to connect to API bus: %m");
814
815 r = sd_bus_attach_event(bus, m->event, EVENT_PRIORITY_IPC);
816 if (r < 0)
817 return log_error_errno(r, "Failed to attach API bus to event loop: %m");
818
819 r = bus_setup_disconnected_match(m, bus);
820 if (r < 0)
821 return r;
822 }
823
824 r = bus_setup_api(m, bus);
825 if (r < 0)
826 return log_error_errno(r, "Failed to set up API bus: %m");
827
828 r = bus_get_instance_id(bus, &m->bus_id);
829 if (r < 0)
830 log_warning_errno(r, "Failed to query API bus instance ID, not deserializing subscriptions: %m");
831 else if (sd_id128_is_null(m->deserialized_bus_id) || sd_id128_equal(m->bus_id, m->deserialized_bus_id))
832 (void) bus_track_coldplug(bus, &m->subscribed, m->subscribed_as_strv);
833 m->subscribed_as_strv = strv_free(m->subscribed_as_strv);
834 m->deserialized_bus_id = SD_ID128_NULL;
835
836 m->api_bus = TAKE_PTR(bus);
837 return 0;
838 }
839
840 int bus_init_system(Manager *m) {
841 _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
842 int r;
843
844 if (m->system_bus)
845 return 0;
846
847 /* The API and system bus is the same if we are running in system mode */
848 if (MANAGER_IS_SYSTEM(m) && m->api_bus)
849 bus = sd_bus_ref(m->api_bus);
850 else {
851 r = sd_bus_open_system_with_description(&bus, "bus-system");
852 if (r < 0)
853 return log_error_errno(r, "Failed to connect to system bus: %m");
854
855 r = sd_bus_attach_event(bus, m->event, EVENT_PRIORITY_IPC);
856 if (r < 0)
857 return log_error_errno(r, "Failed to attach system bus to event loop: %m");
858
859 r = bus_setup_disconnected_match(m, bus);
860 if (r < 0)
861 return r;
862 }
863
864 m->system_bus = TAKE_PTR(bus);
865
866 log_debug("Successfully connected to system bus.");
867
868 return 0;
869 }
870
871 int bus_init_private(Manager *m) {
872 _cleanup_close_ int fd = -EBADF;
873 union sockaddr_union sa;
874 socklen_t sa_len;
875 sd_event_source *s;
876 int r;
877
878 assert(m);
879
880 if (m->private_listen_fd >= 0)
881 return 0;
882
883 if (MANAGER_IS_SYSTEM(m)) {
884
885 /* We want the private bus only when running as init */
886 if (getpid_cached() != 1)
887 return 0;
888
889 r = sockaddr_un_set_path(&sa.un, "/run/systemd/private");
890 } else {
891 _cleanup_free_ char *p = NULL;
892
893 p = path_join(m->prefix[EXEC_DIRECTORY_RUNTIME], "systemd/private");
894 if (!p)
895 return log_oom();
896
897 r = sockaddr_un_set_path(&sa.un, p);
898 }
899 if (r < 0)
900 return log_error_errno(r, "Failed set socket path for private bus: %m");
901 sa_len = r;
902
903 (void) sockaddr_un_unlink(&sa.un);
904
905 fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
906 if (fd < 0)
907 return log_error_errno(errno, "Failed to allocate private socket: %m");
908
909 WITH_UMASK(0077)
910 r = bind(fd, &sa.sa, sa_len);
911 if (r < 0)
912 return log_error_errno(errno, "Failed to bind private socket: %m");
913
914 r = listen(fd, SOMAXCONN_DELUXE);
915 if (r < 0)
916 return log_error_errno(errno, "Failed to make private socket listening: %m");
917
918 /* Generate an inotify event in case somebody waits for this socket to appear using inotify() */
919 (void) touch(sa.un.sun_path);
920
921 r = sd_event_add_io(m->event, &s, fd, EPOLLIN, bus_on_connection, m);
922 if (r < 0)
923 return log_error_errno(r, "Failed to allocate event source: %m");
924
925 (void) sd_event_source_set_description(s, "bus-connection");
926
927 m->private_listen_fd = TAKE_FD(fd);
928 m->private_listen_event_source = s;
929
930 log_debug("Successfully created private D-Bus server.");
931
932 return 0;
933 }
934
935 static void destroy_bus(Manager *m, sd_bus **bus) {
936 Unit *u;
937 Job *j;
938
939 assert(m);
940 assert(bus);
941
942 if (!*bus)
943 return;
944
945 /* Make sure all bus slots watching names are released. */
946 HASHMAP_FOREACH(u, m->watch_bus) {
947 if (u->match_bus_slot && sd_bus_slot_get_bus(u->match_bus_slot) == *bus)
948 u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot);
949 if (u->get_name_owner_slot && sd_bus_slot_get_bus(u->get_name_owner_slot) == *bus)
950 u->get_name_owner_slot = sd_bus_slot_unref(u->get_name_owner_slot);
951 }
952
953 /* Get rid of tracked clients on this bus */
954 if (m->subscribed && sd_bus_track_get_bus(m->subscribed) == *bus) {
955 _cleanup_strv_free_ char **subscribed = NULL;
956 int r;
957
958 r = bus_track_to_strv(m->subscribed, &subscribed);
959 if (r < 0)
960 log_warning_errno(r, "Failed to serialize api subscribers, ignoring: %m");
961 strv_free_and_replace(m->subscribed_as_strv, subscribed);
962
963 m->deserialized_bus_id = m->bus_id;
964 m->bus_id = SD_ID128_NULL;
965
966 m->subscribed = sd_bus_track_unref(m->subscribed);
967 }
968
969 HASHMAP_FOREACH(j, m->jobs)
970 if (j->bus_track && sd_bus_track_get_bus(j->bus_track) == *bus)
971 j->bus_track = sd_bus_track_unref(j->bus_track);
972
973 HASHMAP_FOREACH(u, m->units) {
974 if (u->bus_track && sd_bus_track_get_bus(u->bus_track) == *bus)
975 u->bus_track = sd_bus_track_unref(u->bus_track);
976
977 /* Get rid of pending freezer messages on this bus */
978 if (u->pending_freezer_invocation && sd_bus_message_get_bus(u->pending_freezer_invocation) == *bus)
979 u->pending_freezer_invocation = sd_bus_message_unref(u->pending_freezer_invocation);
980 }
981
982 /* Get rid of queued message on this bus */
983 if (m->pending_reload_message && sd_bus_message_get_bus(m->pending_reload_message) == *bus)
984 m->pending_reload_message = sd_bus_message_unref(m->pending_reload_message);
985
986 /* Possibly flush unwritten data, but only if we are
987 * unprivileged, since we don't want to sync here */
988 if (!MANAGER_IS_SYSTEM(m))
989 sd_bus_flush(*bus);
990
991 /* And destroy the object */
992 *bus = sd_bus_close_unref(*bus);
993 }
994
995 void bus_done_api(Manager *m) {
996 destroy_bus(m, &m->api_bus);
997 }
998
999 void bus_done_system(Manager *m) {
1000 destroy_bus(m, &m->system_bus);
1001 }
1002
1003 void bus_done_private(Manager *m) {
1004 sd_bus *b;
1005
1006 assert(m);
1007
1008 while ((b = set_steal_first(m->private_buses)))
1009 destroy_bus(m, &b);
1010
1011 m->private_buses = set_free(m->private_buses);
1012
1013 m->private_listen_event_source = sd_event_source_disable_unref(m->private_listen_event_source);
1014 m->private_listen_fd = safe_close(m->private_listen_fd);
1015 }
1016
1017 void bus_done(Manager *m) {
1018 assert(m);
1019
1020 bus_done_api(m);
1021 bus_done_system(m);
1022 bus_done_private(m);
1023
1024 assert(!m->subscribed);
1025
1026 m->polkit_registry = hashmap_free(m->polkit_registry);
1027 }
1028
1029 int bus_fdset_add_all(Manager *m, FDSet *fds) {
1030 sd_bus *b;
1031 int fd;
1032
1033 assert(m);
1034 assert(fds);
1035
1036 /* When we are about to reexecute we add all D-Bus fds to the
1037 * set to pass over to the newly executed systemd. They won't
1038 * be used there however, except thatt they are closed at the
1039 * very end of deserialization, those making it possible for
1040 * clients to synchronously wait for systemd to reexec by
1041 * simply waiting for disconnection */
1042
1043 if (m->api_bus) {
1044 fd = sd_bus_get_fd(m->api_bus);
1045 if (fd >= 0) {
1046 fd = fdset_put_dup(fds, fd);
1047 if (fd < 0)
1048 return fd;
1049 }
1050 }
1051
1052 SET_FOREACH(b, m->private_buses) {
1053 fd = sd_bus_get_fd(b);
1054 if (fd >= 0) {
1055 fd = fdset_put_dup(fds, fd);
1056 if (fd < 0)
1057 return fd;
1058 }
1059 }
1060
1061 /* We don't offer any APIs on the system bus (well, unless it
1062 * is the same as the API bus) hence we don't bother with it
1063 * here */
1064
1065 return 0;
1066 }
1067
1068 int bus_foreach_bus(
1069 Manager *m,
1070 sd_bus_track *subscribed2,
1071 int (*send_message)(sd_bus *bus, void *userdata),
1072 void *userdata) {
1073
1074 int r = 0;
1075
1076 assert(m);
1077 assert(send_message);
1078
1079 /* Send to all direct buses, unconditionally */
1080 sd_bus *b;
1081 SET_FOREACH(b, m->private_buses) {
1082
1083 /* Don't bother with enqueuing these messages to clients that haven't started yet */
1084 if (sd_bus_is_ready(b) <= 0)
1085 continue;
1086
1087 RET_GATHER(r, send_message(b, userdata));
1088 }
1089
1090 /* Send to API bus, but only if somebody is subscribed */
1091 if (m->api_bus &&
1092 (sd_bus_track_count(m->subscribed) > 0 ||
1093 sd_bus_track_count(subscribed2) > 0))
1094 RET_GATHER(r, send_message(m->api_bus, userdata));
1095
1096 return r;
1097 }
1098
1099 void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix) {
1100 const char *n;
1101
1102 assert(f);
1103 assert(prefix);
1104
1105 for (n = sd_bus_track_first(t); n; n = sd_bus_track_next(t)) {
1106 int c, j;
1107
1108 c = sd_bus_track_count_name(t, n);
1109 for (j = 0; j < c; j++)
1110 (void) serialize_item(f, prefix, n);
1111 }
1112 }
1113
1114 uint64_t manager_bus_n_queued_write(Manager *m) {
1115 uint64_t c = 0;
1116 sd_bus *b;
1117 int r;
1118
1119 /* Returns the total number of messages queued for writing on all our direct and API buses. */
1120
1121 SET_FOREACH(b, m->private_buses) {
1122 uint64_t k;
1123
1124 r = sd_bus_get_n_queued_write(b, &k);
1125 if (r < 0)
1126 log_debug_errno(r, "Failed to query queued messages for private bus: %m");
1127 else
1128 c += k;
1129 }
1130
1131 if (m->api_bus) {
1132 uint64_t k;
1133
1134 r = sd_bus_get_n_queued_write(m->api_bus, &k);
1135 if (r < 0)
1136 log_debug_errno(r, "Failed to query queued messages for API bus: %m");
1137 else
1138 c += k;
1139 }
1140
1141 return c;
1142 }
1143
1144 static void vtable_dump_bus_properties(FILE *f, const sd_bus_vtable *table) {
1145 const sd_bus_vtable *i;
1146
1147 for (i = table; i->type != _SD_BUS_VTABLE_END; i++) {
1148 if (!IN_SET(i->type, _SD_BUS_VTABLE_PROPERTY, _SD_BUS_VTABLE_WRITABLE_PROPERTY) ||
1149 (i->flags & (SD_BUS_VTABLE_DEPRECATED | SD_BUS_VTABLE_HIDDEN)) != 0)
1150 continue;
1151
1152 fprintf(f, "%s\n", i->x.property.member);
1153 }
1154 }
1155
1156 void dump_bus_properties(FILE *f) {
1157 assert(f);
1158
1159 vtable_dump_bus_properties(f, bus_automount_vtable);
1160 vtable_dump_bus_properties(f, bus_cgroup_vtable);
1161 vtable_dump_bus_properties(f, bus_device_vtable);
1162 vtable_dump_bus_properties(f, bus_exec_vtable);
1163 vtable_dump_bus_properties(f, bus_job_vtable);
1164 vtable_dump_bus_properties(f, bus_kill_vtable);
1165 vtable_dump_bus_properties(f, bus_manager_vtable);
1166 vtable_dump_bus_properties(f, bus_mount_vtable);
1167 vtable_dump_bus_properties(f, bus_path_vtable);
1168 vtable_dump_bus_properties(f, bus_scope_vtable);
1169 vtable_dump_bus_properties(f, bus_service_vtable);
1170 vtable_dump_bus_properties(f, bus_slice_vtable);
1171 vtable_dump_bus_properties(f, bus_socket_vtable);
1172 vtable_dump_bus_properties(f, bus_swap_vtable);
1173 vtable_dump_bus_properties(f, bus_target_vtable);
1174 vtable_dump_bus_properties(f, bus_timer_vtable);
1175 vtable_dump_bus_properties(f, bus_unit_vtable);
1176 vtable_dump_bus_properties(f, bus_unit_cgroup_vtable);
1177 }