]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus.c
util-lib: split out globbing related calls into glob-util.[ch]
[thirdparty/systemd.git] / src / core / dbus.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <sys/epoll.h>
24 #include <unistd.h>
25
26 #include "sd-bus.h"
27
28 #include "bus-common-errors.h"
29 #include "bus-error.h"
30 #include "bus-internal.h"
31 #include "bus-util.h"
32 #include "dbus-cgroup.h"
33 #include "dbus-execute.h"
34 #include "dbus-job.h"
35 #include "dbus-kill.h"
36 #include "dbus-manager.h"
37 #include "dbus-unit.h"
38 #include "dbus.h"
39 #include "fd-util.h"
40 #include "log.h"
41 #include "missing.h"
42 #include "mkdir.h"
43 #include "selinux-access.h"
44 #include "special.h"
45 #include "string-util.h"
46 #include "strv.h"
47 #include "strxcpyx.h"
48 #include "user-util.h"
49
50 #define CONNECTIONS_MAX 4096
51
52 static void destroy_bus(Manager *m, sd_bus **bus);
53
54 int bus_send_queued_message(Manager *m) {
55 int r;
56
57 assert(m);
58
59 if (!m->queued_message)
60 return 0;
61
62 /* If we cannot get rid of this message we won't dispatch any
63 * D-Bus messages, so that we won't end up wanting to queue
64 * another message. */
65
66 r = sd_bus_send(NULL, m->queued_message, NULL);
67 if (r < 0)
68 log_warning_errno(r, "Failed to send queued message: %m");
69
70 m->queued_message = sd_bus_message_unref(m->queued_message);
71
72 return 0;
73 }
74
75 static int signal_agent_released(sd_bus_message *message, void *userdata, sd_bus_error *error) {
76 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
77 const char *cgroup, *me;
78 Manager *m = userdata;
79 uid_t sender_uid;
80 sd_bus *bus;
81 int r;
82
83 assert(message);
84 assert(m);
85
86 /* ignore recursive events sent by us on the system/user bus */
87 bus = sd_bus_message_get_bus(message);
88 if (!sd_bus_is_server(bus)) {
89 r = sd_bus_get_unique_name(bus, &me);
90 if (r < 0)
91 return r;
92
93 if (streq_ptr(sd_bus_message_get_sender(message), me))
94 return 0;
95 }
96
97 /* only accept org.freedesktop.systemd1.Agent from UID=0 */
98 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
99 if (r < 0)
100 return r;
101
102 r = sd_bus_creds_get_euid(creds, &sender_uid);
103 if (r < 0 || sender_uid != 0)
104 return 0;
105
106 /* parse 'cgroup-empty' notification */
107 r = sd_bus_message_read(message, "s", &cgroup);
108 if (r < 0) {
109 bus_log_parse_error(r);
110 return 0;
111 }
112
113 manager_notify_cgroup_empty(m, cgroup);
114
115 /* if running as system-instance, forward under our name */
116 if (m->running_as == MANAGER_SYSTEM && m->system_bus) {
117 r = sd_bus_message_rewind(message, 1);
118 if (r >= 0)
119 r = sd_bus_send(m->system_bus, message, NULL);
120 if (r < 0)
121 log_warning_errno(r, "Failed to forward Released message: %m");
122 }
123
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 destroy_bus(m, &m->api_bus);
137 if (bus == m->system_bus)
138 destroy_bus(m, &m->system_bus);
139 if (set_remove(m->private_buses, bus)) {
140 log_debug("Got disconnect on private connection.");
141 destroy_bus(m, &bus);
142 }
143
144 return 0;
145 }
146
147 static int signal_activation_request(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
148 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
149 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
150 Manager *m = userdata;
151 const char *name;
152 Unit *u;
153 int r;
154
155 assert(message);
156 assert(m);
157
158 r = sd_bus_message_read(message, "s", &name);
159 if (r < 0) {
160 bus_log_parse_error(r);
161 return 0;
162 }
163
164 if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) ||
165 manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) {
166 r = sd_bus_error_setf(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
167 goto failed;
168 }
169
170 r = manager_load_unit(m, name, NULL, &error, &u);
171 if (r < 0)
172 goto failed;
173
174 if (u->refuse_manual_start) {
175 r = sd_bus_error_setf(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, %s may be requested by dependency only.", u->id);
176 goto failed;
177 }
178
179 r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
180 if (r < 0)
181 goto failed;
182
183 /* Successfully queued, that's it for us */
184 return 0;
185
186 failed:
187 if (!sd_bus_error_is_set(&error))
188 sd_bus_error_set_errno(&error, r);
189
190 log_debug("D-Bus activation failed for %s: %s", name, bus_error_message(&error, r));
191
192 r = sd_bus_message_new_signal(sd_bus_message_get_bus(message), &reply, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
193 if (r < 0) {
194 bus_log_create_error(r);
195 return 0;
196 }
197
198 r = sd_bus_message_append(reply, "sss", name, error.name, error.message);
199 if (r < 0) {
200 bus_log_create_error(r);
201 return 0;
202 }
203
204 r = sd_bus_send_to(NULL, reply, "org.freedesktop.DBus", NULL);
205 if (r < 0)
206 return log_error_errno(r, "Failed to respond with to bus activation request: %m");
207
208 return 0;
209 }
210
211 #ifdef HAVE_SELINUX
212 static int mac_selinux_filter(sd_bus_message *message, void *userdata, sd_bus_error *error) {
213 Manager *m = userdata;
214 const char *verb, *path;
215 Unit *u = NULL;
216 Job *j;
217 int r;
218
219 assert(message);
220
221 /* Our own method calls are all protected individually with
222 * selinux checks, but the built-in interfaces need to be
223 * protected too. */
224
225 if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set"))
226 verb = "reload";
227 else if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", NULL) ||
228 sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", NULL) ||
229 sd_bus_message_is_method_call(message, "org.freedesktop.DBus.ObjectManager", NULL) ||
230 sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Peer", NULL))
231 verb = "status";
232 else
233 return 0;
234
235 path = sd_bus_message_get_path(message);
236
237 if (object_path_startswith("/org/freedesktop/systemd1", path)) {
238
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_bus_creds_unref_ 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
267 if (!u)
268 return 0;
269
270 r = mac_selinux_unit_access_check(u, message, verb, error);
271 if (r < 0)
272 return r;
273
274 return 0;
275 }
276 #endif
277
278 static int bus_job_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
279 Manager *m = userdata;
280 Job *j;
281 int r;
282
283 assert(bus);
284 assert(path);
285 assert(interface);
286 assert(found);
287 assert(m);
288
289 r = manager_get_job_from_dbus_path(m, path, &j);
290 if (r < 0)
291 return 0;
292
293 *found = j;
294 return 1;
295 }
296
297 static int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_bus_error *error) {
298 Unit *u;
299 int r;
300
301 assert(m);
302 assert(bus);
303 assert(path);
304
305 if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
306 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
307 sd_bus_message *message;
308 pid_t pid;
309
310 message = sd_bus_get_current_message(bus);
311 if (!message)
312 return 0;
313
314 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
315 if (r < 0)
316 return r;
317
318 r = sd_bus_creds_get_pid(creds, &pid);
319 if (r < 0)
320 return r;
321
322 u = manager_get_unit_by_pid(m, pid);
323 } else {
324 r = manager_load_unit_from_dbus_path(m, path, error, &u);
325 if (r < 0)
326 return 0;
327 }
328
329 if (!u)
330 return 0;
331
332 *unit = u;
333 return 1;
334 }
335
336 static int bus_unit_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
337 Manager *m = userdata;
338
339 assert(bus);
340 assert(path);
341 assert(interface);
342 assert(found);
343 assert(m);
344
345 return find_unit(m, bus, path, (Unit**) found, error);
346 }
347
348 static int bus_unit_interface_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
349 Manager *m = userdata;
350 Unit *u;
351 int r;
352
353 assert(bus);
354 assert(path);
355 assert(interface);
356 assert(found);
357 assert(m);
358
359 r = find_unit(m, bus, path, &u, error);
360 if (r <= 0)
361 return r;
362
363 if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
364 return 0;
365
366 *found = u;
367 return 1;
368 }
369
370 static int bus_unit_cgroup_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
371 Manager *m = userdata;
372 Unit *u;
373 int r;
374
375 assert(bus);
376 assert(path);
377 assert(interface);
378 assert(found);
379 assert(m);
380
381 r = find_unit(m, bus, path, &u, error);
382 if (r <= 0)
383 return r;
384
385 if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
386 return 0;
387
388 if (!UNIT_HAS_CGROUP_CONTEXT(u))
389 return 0;
390
391 *found = u;
392 return 1;
393 }
394
395 static int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
396 Manager *m = userdata;
397 CGroupContext *c;
398 Unit *u;
399 int r;
400
401 assert(bus);
402 assert(path);
403 assert(interface);
404 assert(found);
405 assert(m);
406
407 r = find_unit(m, bus, path, &u, error);
408 if (r <= 0)
409 return r;
410
411 if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
412 return 0;
413
414 c = unit_get_cgroup_context(u);
415 if (!c)
416 return 0;
417
418 *found = c;
419 return 1;
420 }
421
422 static int bus_exec_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
423 Manager *m = userdata;
424 ExecContext *c;
425 Unit *u;
426 int r;
427
428 assert(bus);
429 assert(path);
430 assert(interface);
431 assert(found);
432 assert(m);
433
434 r = find_unit(m, bus, path, &u, error);
435 if (r <= 0)
436 return r;
437
438 if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
439 return 0;
440
441 c = unit_get_exec_context(u);
442 if (!c)
443 return 0;
444
445 *found = c;
446 return 1;
447 }
448
449 static int bus_kill_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
450 Manager *m = userdata;
451 KillContext *c;
452 Unit *u;
453 int r;
454
455 assert(bus);
456 assert(path);
457 assert(interface);
458 assert(found);
459 assert(m);
460
461 r = find_unit(m, bus, path, &u, error);
462 if (r <= 0)
463 return r;
464
465 if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
466 return 0;
467
468 c = unit_get_kill_context(u);
469 if (!c)
470 return 0;
471
472 *found = c;
473 return 1;
474 }
475
476 static int bus_job_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
477 _cleanup_free_ char **l = NULL;
478 Manager *m = userdata;
479 unsigned k = 0;
480 Iterator i;
481 Job *j;
482
483 l = new0(char*, hashmap_size(m->jobs)+1);
484 if (!l)
485 return -ENOMEM;
486
487 HASHMAP_FOREACH(j, m->jobs, i) {
488 l[k] = job_dbus_path(j);
489 if (!l[k])
490 return -ENOMEM;
491
492 k++;
493 }
494
495 assert(hashmap_size(m->jobs) == k);
496
497 *nodes = l;
498 l = NULL;
499
500 return k;
501 }
502
503 static int bus_unit_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
504 _cleanup_free_ char **l = NULL;
505 Manager *m = userdata;
506 unsigned k = 0;
507 Iterator i;
508 Unit *u;
509
510 l = new0(char*, hashmap_size(m->units)+1);
511 if (!l)
512 return -ENOMEM;
513
514 HASHMAP_FOREACH(u, m->units, i) {
515 l[k] = unit_dbus_path(u);
516 if (!l[k])
517 return -ENOMEM;
518
519 k++;
520 }
521
522 *nodes = l;
523 l = NULL;
524
525 return k;
526 }
527
528 static int bus_setup_api_vtables(Manager *m, sd_bus *bus) {
529 UnitType t;
530 int r;
531
532 assert(m);
533 assert(bus);
534
535 #ifdef HAVE_SELINUX
536 r = sd_bus_add_filter(bus, NULL, mac_selinux_filter, m);
537 if (r < 0)
538 return log_error_errno(r, "Failed to add SELinux access filter: %m");
539 #endif
540
541 r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m);
542 if (r < 0)
543 return log_error_errno(r, "Failed to register Manager vtable: %m");
544
545 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m);
546 if (r < 0)
547 return log_error_errno(r, "Failed to register Job vtable: %m");
548
549 r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/job", bus_job_enumerate, m);
550 if (r < 0)
551 return log_error_errno(r, "Failed to add job enumerator: %m");
552
553 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, m);
554 if (r < 0)
555 return log_error_errno(r, "Failed to register Unit vtable: %m");
556
557 r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/unit", bus_unit_enumerate, m);
558 if (r < 0)
559 return log_error_errno(r, "Failed to add job enumerator: %m");
560
561 for (t = 0; t < _UNIT_TYPE_MAX; t++) {
562 const char *interface;
563
564 assert_se(interface = unit_dbus_interface_from_type(t));
565
566 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, unit_vtable[t]->bus_vtable, bus_unit_interface_find, m);
567 if (r < 0)
568 return log_error_errno(r, "Failed to register type specific vtable for %s: %m", interface);
569
570 if (unit_vtable[t]->cgroup_context_offset > 0) {
571 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_unit_cgroup_vtable, bus_unit_cgroup_find, m);
572 if (r < 0)
573 return log_error_errno(r, "Failed to register control group unit vtable for %s: %m", interface);
574
575 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_cgroup_vtable, bus_cgroup_context_find, m);
576 if (r < 0)
577 return log_error_errno(r, "Failed to register control group vtable for %s: %m", interface);
578 }
579
580 if (unit_vtable[t]->exec_context_offset > 0) {
581 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_exec_vtable, bus_exec_context_find, m);
582 if (r < 0)
583 return log_error_errno(r, "Failed to register execute vtable for %s: %m", interface);
584 }
585
586 if (unit_vtable[t]->kill_context_offset > 0) {
587 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_kill_vtable, bus_kill_context_find, m);
588 if (r < 0)
589 return log_error_errno(r, "Failed to register kill vtable for %s: %m", interface);
590 }
591 }
592
593 return 0;
594 }
595
596 static int bus_setup_disconnected_match(Manager *m, sd_bus *bus) {
597 int r;
598
599 assert(m);
600 assert(bus);
601
602 r = sd_bus_add_match(
603 bus,
604 NULL,
605 "sender='org.freedesktop.DBus.Local',"
606 "type='signal',"
607 "path='/org/freedesktop/DBus/Local',"
608 "interface='org.freedesktop.DBus.Local',"
609 "member='Disconnected'",
610 signal_disconnected, m);
611
612 if (r < 0)
613 return log_error_errno(r, "Failed to register match for Disconnected message: %m");
614
615 return 0;
616 }
617
618 static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
619 _cleanup_bus_unref_ sd_bus *bus = NULL;
620 _cleanup_close_ int nfd = -1;
621 Manager *m = userdata;
622 sd_id128_t id;
623 int r;
624
625 assert(s);
626 assert(m);
627
628 nfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
629 if (nfd < 0) {
630 log_warning_errno(errno, "Failed to accept private connection, ignoring: %m");
631 return 0;
632 }
633
634 if (set_size(m->private_buses) >= CONNECTIONS_MAX) {
635 log_warning("Too many concurrent connections, refusing");
636 return 0;
637 }
638
639 r = set_ensure_allocated(&m->private_buses, NULL);
640 if (r < 0) {
641 log_oom();
642 return 0;
643 }
644
645 r = sd_bus_new(&bus);
646 if (r < 0) {
647 log_warning_errno(r, "Failed to allocate new private connection bus: %m");
648 return 0;
649 }
650
651 r = sd_bus_set_fd(bus, nfd, nfd);
652 if (r < 0) {
653 log_warning_errno(r, "Failed to set fd on new connection bus: %m");
654 return 0;
655 }
656
657 nfd = -1;
658
659 r = bus_check_peercred(bus);
660 if (r < 0) {
661 log_warning_errno(r, "Incoming private connection from unprivileged client, refusing: %m");
662 return 0;
663 }
664
665 assert_se(sd_id128_randomize(&id) >= 0);
666
667 r = sd_bus_set_server(bus, 1, id);
668 if (r < 0) {
669 log_warning_errno(r, "Failed to enable server support for new connection bus: %m");
670 return 0;
671 }
672
673 r = sd_bus_negotiate_creds(bus, 1,
674 SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|
675 SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS|
676 SD_BUS_CREDS_SELINUX_CONTEXT);
677 if (r < 0) {
678 log_warning_errno(r, "Failed to enable credentials for new connection: %m");
679 return 0;
680 }
681
682 r = sd_bus_start(bus);
683 if (r < 0) {
684 log_warning_errno(r, "Failed to start new connection bus: %m");
685 return 0;
686 }
687
688 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
689 if (r < 0) {
690 log_warning_errno(r, "Failed to attach new connection bus to event loop: %m");
691 return 0;
692 }
693
694 if (m->running_as == MANAGER_SYSTEM) {
695 /* When we run as system instance we get the Released
696 * signal via a direct connection */
697
698 r = sd_bus_add_match(
699 bus,
700 NULL,
701 "type='signal',"
702 "interface='org.freedesktop.systemd1.Agent',"
703 "member='Released',"
704 "path='/org/freedesktop/systemd1/agent'",
705 signal_agent_released, m);
706
707 if (r < 0) {
708 log_warning_errno(r, "Failed to register Released match on new connection bus: %m");
709 return 0;
710 }
711 }
712
713 r = bus_setup_disconnected_match(m, bus);
714 if (r < 0)
715 return 0;
716
717 r = bus_setup_api_vtables(m, bus);
718 if (r < 0) {
719 log_warning_errno(r, "Failed to set up API vtables on new connection bus: %m");
720 return 0;
721 }
722
723 r = set_put(m->private_buses, bus);
724 if (r < 0) {
725 log_warning_errno(r, "Failed to add new connection bus to set: %m");
726 return 0;
727 }
728
729 bus = NULL;
730
731 log_debug("Accepted new private connection.");
732
733 return 0;
734 }
735
736 static int bus_list_names(Manager *m, sd_bus *bus) {
737 _cleanup_strv_free_ char **names = NULL;
738 char **i;
739 int r;
740
741 assert(m);
742 assert(bus);
743
744 r = sd_bus_list_names(bus, &names, NULL);
745 if (r < 0)
746 return log_error_errno(r, "Failed to get initial list of names: %m");
747
748 /* This is a bit hacky, we say the owner of the name is the
749 * name itself, because we don't want the extra traffic to
750 * figure out the real owner. */
751 STRV_FOREACH(i, names) {
752 Unit *u;
753
754 u = hashmap_get(m->watch_bus, *i);
755 if (u)
756 UNIT_VTABLE(u)->bus_name_owner_change(u, *i, NULL, *i);
757 }
758
759 return 0;
760 }
761
762 static int bus_setup_api(Manager *m, sd_bus *bus) {
763 Iterator i;
764 char *name;
765 Unit *u;
766 int r;
767
768 assert(m);
769 assert(bus);
770
771 /* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
772 r = sd_bus_negotiate_creds(bus, 1,
773 SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|
774 SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS|
775 SD_BUS_CREDS_SELINUX_CONTEXT);
776 if (r < 0)
777 log_warning_errno(r, "Failed to enable credential passing, ignoring: %m");
778
779 r = bus_setup_api_vtables(m, bus);
780 if (r < 0)
781 return r;
782
783 HASHMAP_FOREACH_KEY(u, name, m->watch_bus, i) {
784 r = unit_install_bus_match(u, bus, name);
785 if (r < 0)
786 log_error_errno(r, "Failed to subscribe to NameOwnerChanged signal: %m");
787 }
788
789 r = sd_bus_add_match(
790 bus,
791 NULL,
792 "type='signal',"
793 "sender='org.freedesktop.DBus',"
794 "path='/org/freedesktop/DBus',"
795 "interface='org.freedesktop.systemd1.Activator',"
796 "member='ActivationRequest'",
797 signal_activation_request, m);
798 if (r < 0)
799 log_warning_errno(r, "Failed to subscribe to activation signal: %m");
800
801 /* Allow replacing of our name, to ease implementation of
802 * reexecution, where we keep the old connection open until
803 * after the new connection is set up and the name installed
804 * to allow clients to synchronously wait for reexecution to
805 * finish */
806 r = sd_bus_request_name(bus,"org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_ALLOW_REPLACEMENT);
807 if (r < 0)
808 return log_error_errno(r, "Failed to register name: %m");
809
810 bus_list_names(m, bus);
811
812 log_debug("Successfully connected to API bus.");
813 return 0;
814 }
815
816 static int bus_init_api(Manager *m) {
817 _cleanup_bus_unref_ sd_bus *bus = NULL;
818 int r;
819
820 if (m->api_bus)
821 return 0;
822
823 /* The API and system bus is the same if we are running in system mode */
824 if (m->running_as == MANAGER_SYSTEM && m->system_bus)
825 bus = sd_bus_ref(m->system_bus);
826 else {
827 if (m->running_as == MANAGER_SYSTEM)
828 r = sd_bus_open_system(&bus);
829 else
830 r = sd_bus_open_user(&bus);
831
832 if (r < 0) {
833 log_debug("Failed to connect to API bus, retrying later...");
834 return 0;
835 }
836
837 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
838 if (r < 0) {
839 log_error_errno(r, "Failed to attach API bus to event loop: %m");
840 return 0;
841 }
842
843 r = bus_setup_disconnected_match(m, bus);
844 if (r < 0)
845 return 0;
846 }
847
848 r = bus_setup_api(m, bus);
849 if (r < 0) {
850 log_error_errno(r, "Failed to set up API bus: %m");
851 return 0;
852 }
853
854 m->api_bus = bus;
855 bus = NULL;
856
857 return 0;
858 }
859
860 static int bus_setup_system(Manager *m, sd_bus *bus) {
861 int r;
862
863 assert(m);
864 assert(bus);
865
866 /* On kdbus or if we are a user instance we get the Released message via the system bus */
867 if (m->running_as == MANAGER_USER || m->kdbus_fd >= 0) {
868 r = sd_bus_add_match(
869 bus,
870 NULL,
871 "type='signal',"
872 "interface='org.freedesktop.systemd1.Agent',"
873 "member='Released',"
874 "path='/org/freedesktop/systemd1/agent'",
875 signal_agent_released, m);
876 if (r < 0)
877 log_warning_errno(r, "Failed to register Released match on system bus: %m");
878 }
879
880 log_debug("Successfully connected to system bus.");
881 return 0;
882 }
883
884 static int bus_init_system(Manager *m) {
885 _cleanup_bus_unref_ sd_bus *bus = NULL;
886 int r;
887
888 if (m->system_bus)
889 return 0;
890
891 /* The API and system bus is the same if we are running in system mode */
892 if (m->running_as == MANAGER_SYSTEM && m->api_bus) {
893 m->system_bus = sd_bus_ref(m->api_bus);
894 return 0;
895 }
896
897 r = sd_bus_open_system(&bus);
898 if (r < 0) {
899 log_debug("Failed to connect to system bus, retrying later...");
900 return 0;
901 }
902
903 r = bus_setup_disconnected_match(m, bus);
904 if (r < 0)
905 return 0;
906
907 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
908 if (r < 0) {
909 log_error_errno(r, "Failed to attach system bus to event loop: %m");
910 return 0;
911 }
912
913 r = bus_setup_system(m, bus);
914 if (r < 0) {
915 log_error_errno(r, "Failed to set up system bus: %m");
916 return 0;
917 }
918
919 m->system_bus = bus;
920 bus = NULL;
921
922 return 0;
923 }
924
925 static int bus_init_private(Manager *m) {
926 _cleanup_close_ int fd = -1;
927 union sockaddr_union sa = {
928 .un.sun_family = AF_UNIX
929 };
930 sd_event_source *s;
931 socklen_t salen;
932 int r;
933
934 assert(m);
935
936 if (m->private_listen_fd >= 0)
937 return 0;
938
939 /* We don't need the private socket if we have kdbus */
940 if (m->kdbus_fd >= 0)
941 return 0;
942
943 if (m->running_as == MANAGER_SYSTEM) {
944
945 /* We want the private bus only when running as init */
946 if (getpid() != 1)
947 return 0;
948
949 strcpy(sa.un.sun_path, "/run/systemd/private");
950 salen = offsetof(union sockaddr_union, un.sun_path) + strlen("/run/systemd/private");
951 } else {
952 size_t left = sizeof(sa.un.sun_path);
953 char *p = sa.un.sun_path;
954 const char *e;
955
956 e = secure_getenv("XDG_RUNTIME_DIR");
957 if (!e) {
958 log_error("Failed to determine XDG_RUNTIME_DIR");
959 return -EHOSTDOWN;
960 }
961
962 left = strpcpy(&p, left, e);
963 left = strpcpy(&p, left, "/systemd/private");
964
965 salen = sizeof(sa.un) - left;
966 }
967
968 (void) mkdir_parents_label(sa.un.sun_path, 0755);
969 (void) unlink(sa.un.sun_path);
970
971 fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
972 if (fd < 0)
973 return log_error_errno(errno, "Failed to allocate private socket: %m");
974
975 r = bind(fd, &sa.sa, salen);
976 if (r < 0)
977 return log_error_errno(errno, "Failed to bind private socket: %m");
978
979 r = listen(fd, SOMAXCONN);
980 if (r < 0)
981 return log_error_errno(errno, "Failed to make private socket listening: %m");
982
983 r = sd_event_add_io(m->event, &s, fd, EPOLLIN, bus_on_connection, m);
984 if (r < 0)
985 return log_error_errno(r, "Failed to allocate event source: %m");
986
987 (void) sd_event_source_set_description(s, "bus-connection");
988
989 m->private_listen_fd = fd;
990 m->private_listen_event_source = s;
991 fd = -1;
992
993 log_debug("Successfully created private D-Bus server.");
994
995 return 0;
996 }
997
998 int bus_init(Manager *m, bool try_bus_connect) {
999 int r;
1000
1001 if (try_bus_connect) {
1002 r = bus_init_system(m);
1003 if (r < 0)
1004 return r;
1005
1006 r = bus_init_api(m);
1007 if (r < 0)
1008 return r;
1009 }
1010
1011 r = bus_init_private(m);
1012 if (r < 0)
1013 return r;
1014
1015 return 0;
1016 }
1017
1018 static void destroy_bus(Manager *m, sd_bus **bus) {
1019 Iterator i;
1020 Job *j;
1021
1022 assert(m);
1023 assert(bus);
1024
1025 if (!*bus)
1026 return;
1027
1028 /* Get rid of tracked clients on this bus */
1029 if (m->subscribed && sd_bus_track_get_bus(m->subscribed) == *bus)
1030 m->subscribed = sd_bus_track_unref(m->subscribed);
1031
1032 HASHMAP_FOREACH(j, m->jobs, i)
1033 if (j->clients && sd_bus_track_get_bus(j->clients) == *bus)
1034 j->clients = sd_bus_track_unref(j->clients);
1035
1036 /* Get rid of queued message on this bus */
1037 if (m->queued_message && sd_bus_message_get_bus(m->queued_message) == *bus)
1038 m->queued_message = sd_bus_message_unref(m->queued_message);
1039
1040 /* Possibly flush unwritten data, but only if we are
1041 * unprivileged, since we don't want to sync here */
1042 if (m->running_as != MANAGER_SYSTEM)
1043 sd_bus_flush(*bus);
1044
1045 /* And destroy the object */
1046 sd_bus_close(*bus);
1047 *bus = sd_bus_unref(*bus);
1048 }
1049
1050 void bus_done(Manager *m) {
1051 sd_bus *b;
1052
1053 assert(m);
1054
1055 if (m->api_bus)
1056 destroy_bus(m, &m->api_bus);
1057 if (m->system_bus)
1058 destroy_bus(m, &m->system_bus);
1059 while ((b = set_steal_first(m->private_buses)))
1060 destroy_bus(m, &b);
1061
1062 m->private_buses = set_free(m->private_buses);
1063
1064 m->subscribed = sd_bus_track_unref(m->subscribed);
1065 m->deserialized_subscribed = strv_free(m->deserialized_subscribed);
1066
1067 if (m->private_listen_event_source)
1068 m->private_listen_event_source = sd_event_source_unref(m->private_listen_event_source);
1069
1070 m->private_listen_fd = safe_close(m->private_listen_fd);
1071
1072 bus_verify_polkit_async_registry_free(m->polkit_registry);
1073 }
1074
1075 int bus_fdset_add_all(Manager *m, FDSet *fds) {
1076 Iterator i;
1077 sd_bus *b;
1078 int fd;
1079
1080 assert(m);
1081 assert(fds);
1082
1083 /* When we are about to reexecute we add all D-Bus fds to the
1084 * set to pass over to the newly executed systemd. They won't
1085 * be used there however, except thatt they are closed at the
1086 * very end of deserialization, those making it possible for
1087 * clients to synchronously wait for systemd to reexec by
1088 * simply waiting for disconnection */
1089
1090 if (m->api_bus) {
1091 fd = sd_bus_get_fd(m->api_bus);
1092 if (fd >= 0) {
1093 fd = fdset_put_dup(fds, fd);
1094 if (fd < 0)
1095 return fd;
1096 }
1097 }
1098
1099 SET_FOREACH(b, m->private_buses, i) {
1100 fd = sd_bus_get_fd(b);
1101 if (fd >= 0) {
1102 fd = fdset_put_dup(fds, fd);
1103 if (fd < 0)
1104 return fd;
1105 }
1106 }
1107
1108 /* We don't offer any APIs on the system bus (well, unless it
1109 * is the same as the API bus) hence we don't bother with it
1110 * here */
1111
1112 return 0;
1113 }
1114
1115 int bus_foreach_bus(
1116 Manager *m,
1117 sd_bus_track *subscribed2,
1118 int (*send_message)(sd_bus *bus, void *userdata),
1119 void *userdata) {
1120
1121 Iterator i;
1122 sd_bus *b;
1123 int r, ret = 0;
1124
1125 /* Send to all direct buses, unconditionally */
1126 SET_FOREACH(b, m->private_buses, i) {
1127 r = send_message(b, userdata);
1128 if (r < 0)
1129 ret = r;
1130 }
1131
1132 /* Send to API bus, but only if somebody is subscribed */
1133 if (sd_bus_track_count(m->subscribed) > 0 ||
1134 sd_bus_track_count(subscribed2) > 0) {
1135 r = send_message(m->api_bus, userdata);
1136 if (r < 0)
1137 ret = r;
1138 }
1139
1140 return ret;
1141 }
1142
1143 void bus_track_serialize(sd_bus_track *t, FILE *f) {
1144 const char *n;
1145
1146 assert(f);
1147
1148 for (n = sd_bus_track_first(t); n; n = sd_bus_track_next(t))
1149 fprintf(f, "subscribed=%s\n", n);
1150 }
1151
1152 int bus_track_deserialize_item(char ***l, const char *line) {
1153 const char *e;
1154 int r;
1155
1156 assert(l);
1157 assert(line);
1158
1159 e = startswith(line, "subscribed=");
1160 if (!e)
1161 return 0;
1162
1163 r = strv_extend(l, e);
1164 if (r < 0)
1165 return r;
1166
1167 return 1;
1168 }
1169
1170 int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l) {
1171 int r = 0;
1172
1173 assert(m);
1174 assert(t);
1175 assert(l);
1176
1177 if (!strv_isempty(*l) && m->api_bus) {
1178 char **i;
1179
1180 if (!*t) {
1181 r = sd_bus_track_new(m->api_bus, t, NULL, NULL);
1182 if (r < 0)
1183 return r;
1184 }
1185
1186 r = 0;
1187 STRV_FOREACH(i, *l) {
1188 int k;
1189
1190 k = sd_bus_track_add_name(*t, *i);
1191 if (k < 0)
1192 r = k;
1193 }
1194 }
1195
1196 *l = strv_free(*l);
1197
1198 return r;
1199 }
1200
1201 int bus_verify_manage_units_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1202 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-units", NULL, false, UID_INVALID, &m->polkit_registry, error);
1203 }
1204
1205 int bus_verify_manage_unit_files_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1206 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-unit-files", NULL, false, UID_INVALID, &m->polkit_registry, error);
1207 }
1208
1209 int bus_verify_reload_daemon_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1210 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.reload-daemon", NULL, false, UID_INVALID, &m->polkit_registry, error);
1211 }
1212
1213 int bus_verify_set_environment_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1214 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.set-environment", NULL, false, UID_INVALID, &m->polkit_registry, error);
1215 }