]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus.c
treewide: no need to negate errno for log_*_errno()
[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_errno(r, "Failed to send queued message: %m");
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_errno(r, "Failed to forward Released message: %m");
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_errno(r, "Failed to respond with to bus activation request: %m");
207 return r;
208 }
209
210 return 0;
211 }
212
213 #ifdef HAVE_SELINUX
214 static int mac_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 = mac_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 = mac_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, mac_selinux_filter, m);
540 if (r < 0) {
541 log_error_errno(r, "Failed to add SELinux access filter: %m");
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_errno(r, "Failed to register Manager vtable: %m");
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_errno(r, "Failed to register Job vtable: %m");
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_errno(r, "Failed to add job enumerator: %m");
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_errno(r, "Failed to register Unit vtable: %m");
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_errno(r, "Failed to add job enumerator: %m");
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_errno(r, "Failed to register type specific vtable for %s: %m", unit_vtable[t]->bus_interface);
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_errno(r, "Failed to register control group unit vtable for %s: %m", unit_vtable[t]->bus_interface);
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_errno(r, "Failed to register control group vtable for %s: %m", unit_vtable[t]->bus_interface);
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_errno(r, "Failed to register execute vtable for %s: %m", unit_vtable[t]->bus_interface);
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_errno(r, "Failed to register kill vtable for %s: %m", unit_vtable[t]->bus_interface);
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_errno(r, "Failed to register match for Disconnected message: %m");
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, NULL);
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_errno(r, "Failed to allocate new private connection bus: %m");
671 return 0;
672 }
673
674 r = sd_bus_set_fd(bus, nfd, nfd);
675 if (r < 0) {
676 log_warning_errno(r, "Failed to set fd on new connection bus: %m");
677 return 0;
678 }
679
680 nfd = -1;
681
682 r = bus_check_peercred(bus);
683 if (r < 0) {
684 log_warning_errno(r, "Incoming private connection from unprivileged client, refusing: %m");
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_errno(r, "Failed to enable server support for new connection bus: %m");
693 return 0;
694 }
695
696 r = sd_bus_start(bus);
697 if (r < 0) {
698 log_warning_errno(r, "Failed to start new connection bus: %m");
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_errno(r, "Failed to attach new connection bus to event loop: %m");
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_errno(r, "Failed to register Released match on new connection bus: %m");
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_errno(r, "Failed to set up API vtables on new connection bus: %m");
734 return 0;
735 }
736
737 r = set_put(m->private_buses, bus);
738 if (r < 0) {
739 log_warning_errno(r, "Failed to add new conenction bus to set: %m");
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_errno(r, "Failed to get initial list of names: %m");
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 /* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
780 r = sd_bus_negotiate_creds(bus, 1,
781 SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|
782 SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS|
783 SD_BUS_CREDS_SELINUX_CONTEXT);
784 if (r < 0)
785 log_warning_errno(r, "Failed to enable credential passing, ignoring: %m");
786
787 r = bus_setup_api_vtables(m, bus);
788 if (r < 0)
789 return r;
790
791 r = sd_bus_add_match(
792 bus,
793 NULL,
794 "type='signal',"
795 "sender='org.freedesktop.DBus',"
796 "path='/org/freedesktop/DBus',"
797 "interface='org.freedesktop.DBus',"
798 "member='NameOwnerChanged'",
799 signal_name_owner_changed, m);
800 if (r < 0)
801 log_warning_errno(r, "Failed to subscribe to NameOwnerChanged signal: %m");
802
803 r = sd_bus_add_match(
804 bus,
805 NULL,
806 "type='signal',"
807 "sender='org.freedesktop.DBus',"
808 "path='/org/freedesktop/DBus',"
809 "interface='org.freedesktop.systemd1.Activator',"
810 "member='ActivationRequest'",
811 signal_activation_request, m);
812 if (r < 0)
813 log_warning_errno(r, "Failed to subscribe to activation signal: %m");
814
815 /* Allow replacing of our name, to ease implementation of
816 * reexecution, where we keep the old connection open until
817 * after the new connection is set up and the name installed
818 * to allow clients to synchronously wait for reexecution to
819 * finish */
820 r = sd_bus_request_name(bus,"org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_ALLOW_REPLACEMENT);
821 if (r < 0) {
822 log_error_errno(r, "Failed to register name: %m");
823 return r;
824 }
825
826 bus_list_names(m, bus);
827
828 log_debug("Successfully connected to API bus.");
829 return 0;
830 }
831
832 static int bus_init_api(Manager *m) {
833 _cleanup_bus_unref_ sd_bus *bus = NULL;
834 int r;
835
836 if (m->api_bus)
837 return 0;
838
839 /* The API and system bus is the same if we are running in system mode */
840 if (m->running_as == SYSTEMD_SYSTEM && m->system_bus)
841 bus = sd_bus_ref(m->system_bus);
842 else {
843 if (m->running_as == SYSTEMD_SYSTEM)
844 r = sd_bus_open_system(&bus);
845 else
846 r = sd_bus_open_user(&bus);
847
848 if (r < 0) {
849 log_debug("Failed to connect to API bus, retrying later...");
850 return 0;
851 }
852
853 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
854 if (r < 0) {
855 log_error_errno(r, "Failed to attach API bus to event loop: %m");
856 return 0;
857 }
858
859 r = bus_setup_disconnected_match(m, bus);
860 if (r < 0)
861 return 0;
862 }
863
864 r = bus_setup_api(m, bus);
865 if (r < 0) {
866 log_error_errno(r, "Failed to set up API bus: %m");
867 return 0;
868 }
869
870 m->api_bus = bus;
871 bus = NULL;
872
873 return 0;
874 }
875
876 static int bus_setup_system(Manager *m, sd_bus *bus) {
877 int r;
878
879 assert(m);
880 assert(bus);
881
882 if (m->running_as == SYSTEMD_SYSTEM)
883 return 0;
884
885 /* If we are a user instance we get the Released message via
886 * the system bus */
887 r = sd_bus_add_match(
888 bus,
889 NULL,
890 "type='signal',"
891 "interface='org.freedesktop.systemd1.Agent',"
892 "member='Released',"
893 "path='/org/freedesktop/systemd1/agent'",
894 signal_agent_released, m);
895
896 if (r < 0)
897 log_warning_errno(r, "Failed to register Released match on system bus: %m");
898
899 log_debug("Successfully connected to system bus.");
900 return 0;
901 }
902
903 static int bus_init_system(Manager *m) {
904 _cleanup_bus_unref_ sd_bus *bus = NULL;
905 int r;
906
907 if (m->system_bus)
908 return 0;
909
910 /* The API and system bus is the same if we are running in system mode */
911 if (m->running_as == SYSTEMD_SYSTEM && m->api_bus) {
912 m->system_bus = sd_bus_ref(m->api_bus);
913 return 0;
914 }
915
916 r = sd_bus_open_system(&bus);
917 if (r < 0) {
918 log_debug("Failed to connect to system bus, retrying later...");
919 return 0;
920 }
921
922 r = bus_setup_disconnected_match(m, bus);
923 if (r < 0)
924 return 0;
925
926 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
927 if (r < 0) {
928 log_error_errno(r, "Failed to attach system bus to event loop: %m");
929 return 0;
930 }
931
932 r = bus_setup_system(m, bus);
933 if (r < 0) {
934 log_error_errno(r, "Failed to set up system bus: %m");
935 return 0;
936 }
937
938 m->system_bus = bus;
939 bus = NULL;
940
941 return 0;
942 }
943
944 static int bus_init_private(Manager *m) {
945 _cleanup_close_ int fd = -1;
946 union sockaddr_union sa = {
947 .un.sun_family = AF_UNIX
948 };
949 sd_event_source *s;
950 socklen_t salen;
951 int r;
952
953 assert(m);
954
955 if (m->private_listen_fd >= 0)
956 return 0;
957
958 /* We don't need the private socket if we have kdbus */
959 if (m->kdbus_fd >= 0)
960 return 0;
961
962 if (m->running_as == SYSTEMD_SYSTEM) {
963
964 /* We want the private bus only when running as init */
965 if (getpid() != 1)
966 return 0;
967
968 strcpy(sa.un.sun_path, "/run/systemd/private");
969 salen = offsetof(union sockaddr_union, un.sun_path) + strlen("/run/systemd/private");
970 } else {
971 size_t left = sizeof(sa.un.sun_path);
972 char *p = sa.un.sun_path;
973 const char *e;
974
975 e = secure_getenv("XDG_RUNTIME_DIR");
976 if (!e) {
977 log_error("Failed to determine XDG_RUNTIME_DIR");
978 return -EHOSTDOWN;
979 }
980
981 left = strpcpy(&p, left, e);
982 left = strpcpy(&p, left, "/systemd/private");
983
984 salen = sizeof(sa.un) - left;
985 }
986
987 (void) mkdir_parents_label(sa.un.sun_path, 0755);
988 (void) unlink(sa.un.sun_path);
989
990 fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
991 if (fd < 0) {
992 log_error("Failed to allocate private socket: %m");
993 return -errno;
994 }
995
996 r = bind(fd, &sa.sa, salen);
997 if (r < 0) {
998 log_error("Failed to bind private socket: %m");
999 return -errno;
1000 }
1001
1002 r = listen(fd, SOMAXCONN);
1003 if (r < 0) {
1004 log_error("Failed to make private socket listening: %m");
1005 return -errno;
1006 }
1007
1008 r = sd_event_add_io(m->event, &s, fd, EPOLLIN, bus_on_connection, m);
1009 if (r < 0) {
1010 log_error_errno(r, "Failed to allocate event source: %m");
1011 return r;
1012 }
1013
1014 m->private_listen_fd = fd;
1015 m->private_listen_event_source = s;
1016 fd = -1;
1017
1018 log_debug("Successfully created private D-Bus server.");
1019
1020 return 0;
1021 }
1022
1023 int bus_init(Manager *m, bool try_bus_connect) {
1024 int r;
1025
1026 if (try_bus_connect) {
1027 r = bus_init_system(m);
1028 if (r < 0)
1029 return r;
1030
1031 r = bus_init_api(m);
1032 if (r < 0)
1033 return r;
1034 }
1035
1036 r = bus_init_private(m);
1037 if (r < 0)
1038 return r;
1039
1040 return 0;
1041 }
1042
1043 static void destroy_bus(Manager *m, sd_bus **bus) {
1044 Iterator i;
1045 Job *j;
1046
1047 assert(m);
1048 assert(bus);
1049
1050 if (!*bus)
1051 return;
1052
1053 /* Get rid of tracked clients on this bus */
1054 if (m->subscribed && sd_bus_track_get_bus(m->subscribed) == *bus)
1055 m->subscribed = sd_bus_track_unref(m->subscribed);
1056
1057 HASHMAP_FOREACH(j, m->jobs, i)
1058 if (j->clients && sd_bus_track_get_bus(j->clients) == *bus)
1059 j->clients = sd_bus_track_unref(j->clients);
1060
1061 /* Get rid of queued message on this bus */
1062 if (m->queued_message_bus == *bus) {
1063 m->queued_message_bus = sd_bus_unref(m->queued_message_bus);
1064
1065 if (m->queued_message)
1066 m->queued_message = sd_bus_message_unref(m->queued_message);
1067 }
1068
1069 /* Possibly flush unwritten data, but only if we are
1070 * unprivileged, since we don't want to sync here */
1071 if (m->running_as != SYSTEMD_SYSTEM)
1072 sd_bus_flush(*bus);
1073
1074 /* And destroy the object */
1075 sd_bus_close(*bus);
1076 *bus = sd_bus_unref(*bus);
1077 }
1078
1079 void bus_done(Manager *m) {
1080 sd_bus *b;
1081
1082 assert(m);
1083
1084 if (m->api_bus)
1085 destroy_bus(m, &m->api_bus);
1086 if (m->system_bus)
1087 destroy_bus(m, &m->system_bus);
1088 while ((b = set_steal_first(m->private_buses)))
1089 destroy_bus(m, &b);
1090
1091 set_free(m->private_buses);
1092 m->private_buses = NULL;
1093
1094 m->subscribed = sd_bus_track_unref(m->subscribed);
1095 strv_free(m->deserialized_subscribed);
1096 m->deserialized_subscribed = NULL;
1097
1098 if (m->private_listen_event_source)
1099 m->private_listen_event_source = sd_event_source_unref(m->private_listen_event_source);
1100
1101 m->private_listen_fd = safe_close(m->private_listen_fd);
1102
1103 bus_verify_polkit_async_registry_free(m->polkit_registry);
1104 }
1105
1106 int bus_fdset_add_all(Manager *m, FDSet *fds) {
1107 Iterator i;
1108 sd_bus *b;
1109 int fd;
1110
1111 assert(m);
1112 assert(fds);
1113
1114 /* When we are about to reexecute we add all D-Bus fds to the
1115 * set to pass over to the newly executed systemd. They won't
1116 * be used there however, except thatt they are closed at the
1117 * very end of deserialization, those making it possible for
1118 * clients to synchronously wait for systemd to reexec by
1119 * simply waiting for disconnection */
1120
1121 if (m->api_bus) {
1122 fd = sd_bus_get_fd(m->api_bus);
1123 if (fd >= 0) {
1124 fd = fdset_put_dup(fds, fd);
1125 if (fd < 0)
1126 return fd;
1127 }
1128 }
1129
1130 SET_FOREACH(b, m->private_buses, i) {
1131 fd = sd_bus_get_fd(b);
1132 if (fd >= 0) {
1133 fd = fdset_put_dup(fds, fd);
1134 if (fd < 0)
1135 return fd;
1136 }
1137 }
1138
1139 /* We don't offer any APIs on the system bus (well, unless it
1140 * is the same as the API bus) hence we don't bother with it
1141 * here */
1142
1143 return 0;
1144 }
1145
1146 int bus_foreach_bus(
1147 Manager *m,
1148 sd_bus_track *subscribed2,
1149 int (*send_message)(sd_bus *bus, void *userdata),
1150 void *userdata) {
1151
1152 Iterator i;
1153 sd_bus *b;
1154 int r, ret = 0;
1155
1156 /* Send to all direct busses, unconditionally */
1157 SET_FOREACH(b, m->private_buses, i) {
1158 r = send_message(b, userdata);
1159 if (r < 0)
1160 ret = r;
1161 }
1162
1163 /* Send to API bus, but only if somebody is subscribed */
1164 if (sd_bus_track_count(m->subscribed) > 0 ||
1165 sd_bus_track_count(subscribed2) > 0) {
1166 r = send_message(m->api_bus, userdata);
1167 if (r < 0)
1168 ret = r;
1169 }
1170
1171 return ret;
1172 }
1173
1174 void bus_track_serialize(sd_bus_track *t, FILE *f) {
1175 const char *n;
1176
1177 assert(f);
1178
1179 for (n = sd_bus_track_first(t); n; n = sd_bus_track_next(t))
1180 fprintf(f, "subscribed=%s\n", n);
1181 }
1182
1183 int bus_track_deserialize_item(char ***l, const char *line) {
1184 const char *e;
1185
1186 assert(l);
1187 assert(line);
1188
1189 e = startswith(line, "subscribed=");
1190 if (!e)
1191 return -EINVAL;
1192
1193 return strv_extend(l, e);
1194 }
1195
1196 int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l) {
1197 int r = 0;
1198
1199 assert(m);
1200 assert(t);
1201 assert(l);
1202
1203 if (!strv_isempty(*l) && m->api_bus) {
1204 char **i;
1205
1206 if (!*t) {
1207 r = sd_bus_track_new(m->api_bus, t, NULL, NULL);
1208 if (r < 0)
1209 return r;
1210 }
1211
1212 r = 0;
1213 STRV_FOREACH(i, *l) {
1214 int k;
1215
1216 k = sd_bus_track_add_name(*t, *i);
1217 if (k < 0)
1218 r = k;
1219 }
1220 }
1221
1222 strv_free(*l);
1223 *l = NULL;
1224
1225 return r;
1226 }
1227
1228 int bus_verify_manage_unit_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1229 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-units", false, &m->polkit_registry, error);
1230 }
1231
1232 /* Same as bus_verify_manage_unit_async(), but checks for CAP_KILL instead of CAP_SYS_ADMIN */
1233 int bus_verify_manage_unit_async_for_kill(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1234 return bus_verify_polkit_async(call, CAP_KILL, "org.freedesktop.systemd1.manage-units", false, &m->polkit_registry, error);
1235 }
1236
1237 int bus_verify_manage_unit_files_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1238 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-unit-files", false, &m->polkit_registry, error);
1239 }
1240
1241 int bus_verify_reload_daemon_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1242 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.reload-daemon", false, &m->polkit_registry, error);
1243 }