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