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