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