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