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