]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus.c
bus-proxy: service_name_is_valid will never be < 0
[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(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, 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_message(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, NULL, 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, NULL, "/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, NULL, "/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, NULL, "/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, NULL, "/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, NULL, "/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, NULL, "/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, NULL, "/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, NULL, "/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, NULL, "/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, NULL, "/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 NULL,
626 "sender='org.freedesktop.DBus.Local',"
627 "type='signal',"
628 "path='/org/freedesktop/DBus/Local',"
629 "interface='org.freedesktop.DBus.Local',"
630 "member='Disconnected'",
631 signal_disconnected, m);
632
633 if (r < 0) {
634 log_error("Failed to register match for Disconnected message: %s", strerror(-r));
635 return r;
636 }
637
638 return 0;
639 }
640
641 static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
642 _cleanup_bus_unref_ sd_bus *bus = NULL;
643 _cleanup_close_ int nfd = -1;
644 Manager *m = userdata;
645 sd_id128_t id;
646 int r;
647
648 assert(s);
649 assert(m);
650
651 nfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
652 if (nfd < 0) {
653 log_warning("Failed to accept private connection, ignoring: %m");
654 return 0;
655 }
656
657 if (set_size(m->private_buses) >= CONNECTIONS_MAX) {
658 log_warning("Too many concurrent connections, refusing");
659 return 0;
660 }
661
662 r = set_ensure_allocated(&m->private_buses, trivial_hash_func, trivial_compare_func);
663 if (r < 0) {
664 log_oom();
665 return 0;
666 }
667
668 r = sd_bus_new(&bus);
669 if (r < 0) {
670 log_warning("Failed to allocate new private connection bus: %s", strerror(-r));
671 return 0;
672 }
673
674 r = sd_bus_set_fd(bus, nfd, nfd);
675 if (r < 0) {
676 log_warning("Failed to set fd on new connection bus: %s", strerror(-r));
677 return 0;
678 }
679
680 nfd = -1;
681
682 r = bus_check_peercred(bus);
683 if (r < 0) {
684 log_warning("Incoming private connection from unprivileged client, refusing: %s", strerror(-r));
685 return 0;
686 }
687
688 assert_se(sd_id128_randomize(&id) >= 0);
689
690 r = sd_bus_set_server(bus, 1, id);
691 if (r < 0) {
692 log_warning("Failed to enable server support for new connection bus: %s", strerror(-r));
693 return 0;
694 }
695
696 r = sd_bus_start(bus);
697 if (r < 0) {
698 log_warning("Failed to start new connection bus: %s", strerror(-r));
699 return 0;
700 }
701
702 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
703 if (r < 0) {
704 log_warning("Failed to attach new connection bus to event loop: %s", strerror(-r));
705 return 0;
706 }
707
708 if (m->running_as == SYSTEMD_SYSTEM) {
709 /* When we run as system instance we get the Released
710 * signal via a direct connection */
711
712 r = sd_bus_add_match(
713 bus,
714 NULL,
715 "type='signal',"
716 "interface='org.freedesktop.systemd1.Agent',"
717 "member='Released',"
718 "path='/org/freedesktop/systemd1/agent'",
719 signal_agent_released, m);
720
721 if (r < 0) {
722 log_warning("Failed to register Released match on new connection bus: %s", strerror(-r));
723 return 0;
724 }
725 }
726
727 r = bus_setup_disconnected_match(m, bus);
728 if (r < 0)
729 return 0;
730
731 r = bus_setup_api_vtables(m, bus);
732 if (r < 0) {
733 log_warning("Failed to set up API vtables on new connection bus: %s", strerror(-r));
734 return 0;
735 }
736
737 r = set_put(m->private_buses, bus);
738 if (r < 0) {
739 log_warning("Failed to add new conenction bus to set: %s", strerror(-r));
740 return 0;
741 }
742
743 bus = NULL;
744
745 log_debug("Accepted new private connection.");
746
747 return 0;
748 }
749
750 static int bus_list_names(Manager *m, sd_bus *bus) {
751 _cleanup_strv_free_ char **names = NULL;
752 char **i;
753 int r;
754
755 assert(m);
756 assert(bus);
757
758 r = sd_bus_list_names(bus, &names, NULL);
759 if (r < 0) {
760 log_error("Failed to get initial list of names: %s", strerror(-r));
761 return r;
762 }
763
764 /* This is a bit hacky, we say the owner of the name is the
765 * name itself, because we don't want the extra traffic to
766 * figure out the real owner. */
767 STRV_FOREACH(i, names)
768 manager_dispatch_bus_name_owner_changed(m, *i, NULL, *i);
769
770 return 0;
771 }
772
773 static int bus_setup_api(Manager *m, sd_bus *bus) {
774 int r;
775
776 assert(m);
777 assert(bus);
778
779 r = bus_setup_api_vtables(m, bus);
780 if (r < 0)
781 return r;
782
783 r = sd_bus_add_match(
784 bus,
785 NULL,
786 "type='signal',"
787 "sender='org.freedesktop.DBus',"
788 "path='/org/freedesktop/DBus',"
789 "interface='org.freedesktop.DBus',"
790 "member='NameOwnerChanged'",
791 signal_name_owner_changed, m);
792 if (r < 0)
793 log_warning("Failed to subscribe to NameOwnerChanged signal: %s", strerror(-r));
794
795 r = sd_bus_add_match(
796 bus,
797 NULL,
798 "type='signal',"
799 "sender='org.freedesktop.DBus',"
800 "path='/org/freedesktop/DBus',"
801 "interface='org.freedesktop.systemd1.Activator',"
802 "member='ActivationRequest'",
803 signal_activation_request, m);
804 if (r < 0)
805 log_warning("Failed to subscribe to activation signal: %s", strerror(-r));
806
807 /* Allow replacing of our name, to ease implementation of
808 * reexecution, where we keep the old connection open until
809 * after the new connection is set up and the name installed
810 * to allow clients to synchronously wait for reexecution to
811 * finish */
812 r = sd_bus_request_name(bus,"org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_ALLOW_REPLACEMENT);
813 if (r < 0) {
814 log_error("Failed to register name: %s", strerror(-r));
815 return r;
816 }
817
818 bus_list_names(m, bus);
819
820 log_debug("Successfully connected to API bus.");
821 return 0;
822 }
823
824 static int bus_init_api(Manager *m) {
825 _cleanup_bus_unref_ sd_bus *bus = NULL;
826 int r;
827
828 if (m->api_bus)
829 return 0;
830
831 /* The API and system bus is the same if we are running in system mode */
832 if (m->running_as == SYSTEMD_SYSTEM && m->system_bus)
833 bus = sd_bus_ref(m->system_bus);
834 else {
835 if (m->running_as == SYSTEMD_SYSTEM)
836 r = sd_bus_open_system(&bus);
837 else
838 r = sd_bus_open_user(&bus);
839
840 if (r < 0) {
841 log_debug("Failed to connect to API bus, retrying later...");
842 return 0;
843 }
844
845 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
846 if (r < 0) {
847 log_error("Failed to attach API bus to event loop: %s", strerror(-r));
848 return 0;
849 }
850
851 r = bus_setup_disconnected_match(m, bus);
852 if (r < 0)
853 return 0;
854 }
855
856 r = bus_setup_api(m, bus);
857 if (r < 0) {
858 log_error("Failed to set up API bus: %s", strerror(-r));
859 return 0;
860 }
861
862 m->api_bus = bus;
863 bus = NULL;
864
865 return 0;
866 }
867
868 static int bus_setup_system(Manager *m, sd_bus *bus) {
869 int r;
870
871 assert(m);
872 assert(bus);
873
874 if (m->running_as == SYSTEMD_SYSTEM)
875 return 0;
876
877 /* If we are a user instance we get the Released message via
878 * the system bus */
879 r = sd_bus_add_match(
880 bus,
881 NULL,
882 "type='signal',"
883 "interface='org.freedesktop.systemd1.Agent',"
884 "member='Released',"
885 "path='/org/freedesktop/systemd1/agent'",
886 signal_agent_released, m);
887
888 if (r < 0)
889 log_warning("Failed to register Released match on system bus: %s", strerror(-r));
890
891 log_debug("Successfully connected to system bus.");
892 return 0;
893 }
894
895 static int bus_init_system(Manager *m) {
896 _cleanup_bus_unref_ sd_bus *bus = NULL;
897 int r;
898
899 if (m->system_bus)
900 return 0;
901
902 /* The API and system bus is the same if we are running in system mode */
903 if (m->running_as == SYSTEMD_SYSTEM && m->api_bus) {
904 m->system_bus = sd_bus_ref(m->api_bus);
905 return 0;
906 }
907
908 r = sd_bus_open_system(&bus);
909 if (r < 0) {
910 log_debug("Failed to connect to system bus, retrying later...");
911 return 0;
912 }
913
914 r = bus_setup_disconnected_match(m, bus);
915 if (r < 0)
916 return 0;
917
918 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
919 if (r < 0) {
920 log_error("Failed to attach system bus to event loop: %s", strerror(-r));
921 return 0;
922 }
923
924 r = bus_setup_system(m, bus);
925 if (r < 0) {
926 log_error("Failed to set up system bus: %s", strerror(-r));
927 return 0;
928 }
929
930 m->system_bus = bus;
931 bus = NULL;
932
933 return 0;
934 }
935
936 static int bus_init_private(Manager *m) {
937 _cleanup_close_ int fd = -1;
938 union sockaddr_union sa = {
939 .un.sun_family = AF_UNIX
940 };
941 sd_event_source *s;
942 socklen_t salen;
943 int r;
944
945 assert(m);
946
947 if (m->private_listen_fd >= 0)
948 return 0;
949
950 /* We don't need the private socket if we have kdbus */
951 if (m->kdbus_fd >= 0)
952 return 0;
953
954 if (m->running_as == SYSTEMD_SYSTEM) {
955
956 /* We want the private bus only when running as init */
957 if (getpid() != 1)
958 return 0;
959
960 strcpy(sa.un.sun_path, "/run/systemd/private");
961 salen = offsetof(union sockaddr_union, un.sun_path) + strlen("/run/systemd/private");
962 } else {
963 size_t left = sizeof(sa.un.sun_path);
964 char *p = sa.un.sun_path;
965 const char *e;
966
967 e = secure_getenv("XDG_RUNTIME_DIR");
968 if (!e) {
969 log_error("Failed to determine XDG_RUNTIME_DIR");
970 return -EHOSTDOWN;
971 }
972
973 left = strpcpy(&p, left, e);
974 left = strpcpy(&p, left, "/systemd/private");
975
976 salen = sizeof(sa.un) - left;
977
978 mkdir_parents_label(sa.un.sun_path, 0755);
979 }
980
981 unlink(sa.un.sun_path);
982
983 fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
984 if (fd < 0) {
985 log_error("Failed to allocate private socket: %m");
986 return -errno;
987 }
988
989 r = bind(fd, &sa.sa, salen);
990 if (r < 0) {
991 log_error("Failed to bind private socket: %m");
992 return -errno;
993 }
994
995 r = listen(fd, SOMAXCONN);
996 if (r < 0) {
997 log_error("Failed to make private socket listening: %m");
998 return -errno;
999 }
1000
1001 r = sd_event_add_io(m->event, &s, fd, EPOLLIN, bus_on_connection, m);
1002 if (r < 0) {
1003 log_error("Failed to allocate event source: %s", strerror(-r));
1004 return r;
1005 }
1006
1007 m->private_listen_fd = fd;
1008 m->private_listen_event_source = s;
1009 fd = -1;
1010
1011 log_debug("Successfully created private D-Bus server.");
1012
1013 return 0;
1014 }
1015
1016 int bus_init(Manager *m, bool try_bus_connect) {
1017 int r;
1018
1019 if (try_bus_connect) {
1020 r = bus_init_system(m);
1021 if (r < 0)
1022 return r;
1023
1024 r = bus_init_api(m);
1025 if (r < 0)
1026 return r;
1027 }
1028
1029 r = bus_init_private(m);
1030 if (r < 0)
1031 return r;
1032
1033 return 0;
1034 }
1035
1036 static void destroy_bus(Manager *m, sd_bus **bus) {
1037 Iterator i;
1038 Job *j;
1039
1040 assert(m);
1041 assert(bus);
1042
1043 if (!*bus)
1044 return;
1045
1046 /* Get rid of tracked clients on this bus */
1047 if (m->subscribed && sd_bus_track_get_bus(m->subscribed) == *bus)
1048 m->subscribed = sd_bus_track_unref(m->subscribed);
1049
1050 HASHMAP_FOREACH(j, m->jobs, i)
1051 if (j->subscribed && sd_bus_track_get_bus(j->subscribed) == *bus)
1052 j->subscribed = sd_bus_track_unref(j->subscribed);
1053
1054 /* Get rid of queued message on this bus */
1055 if (m->queued_message_bus == *bus) {
1056 m->queued_message_bus = sd_bus_unref(m->queued_message_bus);
1057
1058 if (m->queued_message)
1059 m->queued_message = sd_bus_message_unref(m->queued_message);
1060 }
1061
1062 /* Possibly flush unwritten data, but only if we are
1063 * unprivileged, since we don't want to sync here */
1064 if (m->running_as != SYSTEMD_SYSTEM)
1065 sd_bus_flush(*bus);
1066
1067 /* And destroy the object */
1068 sd_bus_close(*bus);
1069 *bus = sd_bus_unref(*bus);
1070 }
1071
1072 void bus_done(Manager *m) {
1073 sd_bus *b;
1074
1075 assert(m);
1076
1077 if (m->api_bus)
1078 destroy_bus(m, &m->api_bus);
1079 if (m->system_bus)
1080 destroy_bus(m, &m->system_bus);
1081 while ((b = set_steal_first(m->private_buses)))
1082 destroy_bus(m, &b);
1083
1084 set_free(m->private_buses);
1085 m->private_buses = NULL;
1086
1087 m->subscribed = sd_bus_track_unref(m->subscribed);
1088 strv_free(m->deserialized_subscribed);
1089 m->deserialized_subscribed = NULL;
1090
1091 if (m->private_listen_event_source)
1092 m->private_listen_event_source = sd_event_source_unref(m->private_listen_event_source);
1093
1094 m->private_listen_fd = safe_close(m->private_listen_fd);
1095 }
1096
1097 int bus_fdset_add_all(Manager *m, FDSet *fds) {
1098 Iterator i;
1099 sd_bus *b;
1100 int fd;
1101
1102 assert(m);
1103 assert(fds);
1104
1105 /* When we are about to reexecute we add all D-Bus fds to the
1106 * set to pass over to the newly executed systemd. They won't
1107 * be used there however, except thatt they are closed at the
1108 * very end of deserialization, those making it possible for
1109 * clients to synchronously wait for systemd to reexec by
1110 * simply waiting for disconnection */
1111
1112 if (m->api_bus) {
1113 fd = sd_bus_get_fd(m->api_bus);
1114 if (fd >= 0) {
1115 fd = fdset_put_dup(fds, fd);
1116 if (fd < 0)
1117 return fd;
1118 }
1119 }
1120
1121 SET_FOREACH(b, m->private_buses, i) {
1122 fd = sd_bus_get_fd(b);
1123 if (fd >= 0) {
1124 fd = fdset_put_dup(fds, fd);
1125 if (fd < 0)
1126 return fd;
1127 }
1128 }
1129
1130 /* We don't offer any APIs on the system bus (well, unless it
1131 * is the same as the API bus) hence we don't bother with it
1132 * here */
1133
1134 return 0;
1135 }
1136
1137 int bus_foreach_bus(
1138 Manager *m,
1139 sd_bus_track *subscribed2,
1140 int (*send_message)(sd_bus *bus, void *userdata),
1141 void *userdata) {
1142
1143 Iterator i;
1144 sd_bus *b;
1145 int r, ret = 0;
1146
1147 /* Send to all direct busses, unconditionally */
1148 SET_FOREACH(b, m->private_buses, i) {
1149 r = send_message(b, userdata);
1150 if (r < 0)
1151 ret = r;
1152 }
1153
1154 /* Send to API bus, but only if somebody is subscribed */
1155 if (sd_bus_track_count(m->subscribed) > 0 ||
1156 sd_bus_track_count(subscribed2) > 0) {
1157 r = send_message(m->api_bus, userdata);
1158 if (r < 0)
1159 ret = r;
1160 }
1161
1162 return ret;
1163 }
1164
1165 void bus_track_serialize(sd_bus_track *t, FILE *f) {
1166 const char *n;
1167
1168 assert(f);
1169
1170 for (n = sd_bus_track_first(t); n; n = sd_bus_track_next(t))
1171 fprintf(f, "subscribed=%s\n", n);
1172 }
1173
1174 int bus_track_deserialize_item(char ***l, const char *line) {
1175 const char *e;
1176
1177 assert(l);
1178 assert(line);
1179
1180 e = startswith(line, "subscribed=");
1181 if (!e)
1182 return 0;
1183
1184 return strv_extend(l, e);
1185 }
1186
1187 int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l) {
1188 int r = 0;
1189
1190 assert(m);
1191 assert(t);
1192 assert(l);
1193
1194 if (!strv_isempty(*l) && m->api_bus) {
1195 char **i;
1196
1197 if (!*t) {
1198 r = sd_bus_track_new(m->api_bus, t, NULL, NULL);
1199 if (r < 0)
1200 return r;
1201 }
1202
1203 r = 0;
1204 STRV_FOREACH(i, *l) {
1205 int k;
1206
1207 k = sd_bus_track_add_name(*t, *i);
1208 if (k < 0)
1209 r = k;
1210 }
1211 }
1212
1213 strv_free(*l);
1214 *l = NULL;
1215
1216 return r;
1217 }