]> git.proxmox.com Git - systemd.git/blob - src/core/dbus.c
Imported Upstream version 218
[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-common-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 return log_error_errno(errno, "Failed to allocate private socket: %m");
963
964 r = bind(fd, &sa.sa, salen);
965 if (r < 0)
966 return log_error_errno(errno, "Failed to bind private socket: %m");
967
968 r = listen(fd, SOMAXCONN);
969 if (r < 0)
970 return log_error_errno(errno, "Failed to make private socket listening: %m");
971
972 r = sd_event_add_io(m->event, &s, fd, EPOLLIN, bus_on_connection, m);
973 if (r < 0)
974 return log_error_errno(r, "Failed to allocate event source: %m");
975
976 m->private_listen_fd = fd;
977 m->private_listen_event_source = s;
978 fd = -1;
979
980 log_debug("Successfully created private D-Bus server.");
981
982 return 0;
983 }
984
985 int bus_init(Manager *m, bool try_bus_connect) {
986 int r;
987
988 if (try_bus_connect) {
989 r = bus_init_system(m);
990 if (r < 0)
991 return r;
992
993 r = bus_init_api(m);
994 if (r < 0)
995 return r;
996 }
997
998 r = bus_init_private(m);
999 if (r < 0)
1000 return r;
1001
1002 return 0;
1003 }
1004
1005 static void destroy_bus(Manager *m, sd_bus **bus) {
1006 Iterator i;
1007 Job *j;
1008
1009 assert(m);
1010 assert(bus);
1011
1012 if (!*bus)
1013 return;
1014
1015 /* Get rid of tracked clients on this bus */
1016 if (m->subscribed && sd_bus_track_get_bus(m->subscribed) == *bus)
1017 m->subscribed = sd_bus_track_unref(m->subscribed);
1018
1019 HASHMAP_FOREACH(j, m->jobs, i)
1020 if (j->clients && sd_bus_track_get_bus(j->clients) == *bus)
1021 j->clients = sd_bus_track_unref(j->clients);
1022
1023 /* Get rid of queued message on this bus */
1024 if (m->queued_message_bus == *bus) {
1025 m->queued_message_bus = sd_bus_unref(m->queued_message_bus);
1026
1027 if (m->queued_message)
1028 m->queued_message = sd_bus_message_unref(m->queued_message);
1029 }
1030
1031 /* Possibly flush unwritten data, but only if we are
1032 * unprivileged, since we don't want to sync here */
1033 if (m->running_as != SYSTEMD_SYSTEM)
1034 sd_bus_flush(*bus);
1035
1036 /* And destroy the object */
1037 sd_bus_close(*bus);
1038 *bus = sd_bus_unref(*bus);
1039 }
1040
1041 void bus_done(Manager *m) {
1042 sd_bus *b;
1043
1044 assert(m);
1045
1046 if (m->api_bus)
1047 destroy_bus(m, &m->api_bus);
1048 if (m->system_bus)
1049 destroy_bus(m, &m->system_bus);
1050 while ((b = set_steal_first(m->private_buses)))
1051 destroy_bus(m, &b);
1052
1053 set_free(m->private_buses);
1054 m->private_buses = NULL;
1055
1056 m->subscribed = sd_bus_track_unref(m->subscribed);
1057 strv_free(m->deserialized_subscribed);
1058 m->deserialized_subscribed = NULL;
1059
1060 if (m->private_listen_event_source)
1061 m->private_listen_event_source = sd_event_source_unref(m->private_listen_event_source);
1062
1063 m->private_listen_fd = safe_close(m->private_listen_fd);
1064
1065 bus_verify_polkit_async_registry_free(m->polkit_registry);
1066 }
1067
1068 int bus_fdset_add_all(Manager *m, FDSet *fds) {
1069 Iterator i;
1070 sd_bus *b;
1071 int fd;
1072
1073 assert(m);
1074 assert(fds);
1075
1076 /* When we are about to reexecute we add all D-Bus fds to the
1077 * set to pass over to the newly executed systemd. They won't
1078 * be used there however, except thatt they are closed at the
1079 * very end of deserialization, those making it possible for
1080 * clients to synchronously wait for systemd to reexec by
1081 * simply waiting for disconnection */
1082
1083 if (m->api_bus) {
1084 fd = sd_bus_get_fd(m->api_bus);
1085 if (fd >= 0) {
1086 fd = fdset_put_dup(fds, fd);
1087 if (fd < 0)
1088 return fd;
1089 }
1090 }
1091
1092 SET_FOREACH(b, m->private_buses, i) {
1093 fd = sd_bus_get_fd(b);
1094 if (fd >= 0) {
1095 fd = fdset_put_dup(fds, fd);
1096 if (fd < 0)
1097 return fd;
1098 }
1099 }
1100
1101 /* We don't offer any APIs on the system bus (well, unless it
1102 * is the same as the API bus) hence we don't bother with it
1103 * here */
1104
1105 return 0;
1106 }
1107
1108 int bus_foreach_bus(
1109 Manager *m,
1110 sd_bus_track *subscribed2,
1111 int (*send_message)(sd_bus *bus, void *userdata),
1112 void *userdata) {
1113
1114 Iterator i;
1115 sd_bus *b;
1116 int r, ret = 0;
1117
1118 /* Send to all direct busses, unconditionally */
1119 SET_FOREACH(b, m->private_buses, i) {
1120 r = send_message(b, userdata);
1121 if (r < 0)
1122 ret = r;
1123 }
1124
1125 /* Send to API bus, but only if somebody is subscribed */
1126 if (sd_bus_track_count(m->subscribed) > 0 ||
1127 sd_bus_track_count(subscribed2) > 0) {
1128 r = send_message(m->api_bus, userdata);
1129 if (r < 0)
1130 ret = r;
1131 }
1132
1133 return ret;
1134 }
1135
1136 void bus_track_serialize(sd_bus_track *t, FILE *f) {
1137 const char *n;
1138
1139 assert(f);
1140
1141 for (n = sd_bus_track_first(t); n; n = sd_bus_track_next(t))
1142 fprintf(f, "subscribed=%s\n", n);
1143 }
1144
1145 int bus_track_deserialize_item(char ***l, const char *line) {
1146 const char *e;
1147 int r;
1148
1149 assert(l);
1150 assert(line);
1151
1152 e = startswith(line, "subscribed=");
1153 if (!e)
1154 return 0;
1155
1156 r = strv_extend(l, e);
1157 if (r < 0)
1158 return r;
1159
1160 return 1;
1161 }
1162
1163 int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l) {
1164 int r = 0;
1165
1166 assert(m);
1167 assert(t);
1168 assert(l);
1169
1170 if (!strv_isempty(*l) && m->api_bus) {
1171 char **i;
1172
1173 if (!*t) {
1174 r = sd_bus_track_new(m->api_bus, t, NULL, NULL);
1175 if (r < 0)
1176 return r;
1177 }
1178
1179 r = 0;
1180 STRV_FOREACH(i, *l) {
1181 int k;
1182
1183 k = sd_bus_track_add_name(*t, *i);
1184 if (k < 0)
1185 r = k;
1186 }
1187 }
1188
1189 strv_free(*l);
1190 *l = NULL;
1191
1192 return r;
1193 }
1194
1195 int bus_verify_manage_unit_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1196 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-units", false, &m->polkit_registry, error);
1197 }
1198
1199 /* Same as bus_verify_manage_unit_async(), but checks for CAP_KILL instead of CAP_SYS_ADMIN */
1200 int bus_verify_manage_unit_async_for_kill(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1201 return bus_verify_polkit_async(call, CAP_KILL, "org.freedesktop.systemd1.manage-units", false, &m->polkit_registry, error);
1202 }
1203
1204 int bus_verify_manage_unit_files_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1205 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-unit-files", false, &m->polkit_registry, error);
1206 }
1207
1208 int bus_verify_reload_daemon_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1209 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.reload-daemon", false, &m->polkit_registry, error);
1210 }