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