chiark / gitweb /
core: do not use quotes around virt and arch
[elogind.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 <errno.h>
24 #include <unistd.h>
25
26 #include "sd-bus.h"
27 #include "log.h"
28 #include "strv.h"
29 #include "mkdir.h"
30 #include "missing.h"
31 #include "dbus-unit.h"
32 #include "dbus-job.h"
33 #include "dbus-manager.h"
34 #include "dbus-execute.h"
35 #include "dbus-kill.h"
36 #include "dbus-cgroup.h"
37 #include "special.h"
38 #include "dbus.h"
39 #include "bus-util.h"
40 #include "bus-error.h"
41 #include "bus-common-errors.h"
42 #include "strxcpyx.h"
43 #include "bus-internal.h"
44 #include "selinux-access.h"
45
46 #define CONNECTIONS_MAX 4096
47
48 static void destroy_bus(Manager *m, sd_bus **bus);
49
50 int bus_send_queued_message(Manager *m) {
51         int r;
52
53         assert(m);
54
55         if (!m->queued_message)
56                 return 0;
57
58         assert(m->queued_message_bus);
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(m->queued_message_bus, 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         m->queued_message_bus = sd_bus_unref(m->queued_message_bus);
70
71         return 0;
72 }
73
74 static int signal_agent_released(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
75         Manager *m = userdata;
76         const char *cgroup;
77         int r;
78
79         assert(bus);
80         assert(message);
81         assert(m);
82
83         r = sd_bus_message_read(message, "s", &cgroup);
84         if (r < 0) {
85                 bus_log_parse_error(r);
86                 return 0;
87         }
88
89         manager_notify_cgroup_empty(m, cgroup);
90
91         /* only forward to system bus if running as system instance */
92         if (m->running_as != SYSTEMD_SYSTEM || !m->system_bus)
93                 return 0;
94
95         r = sd_bus_message_rewind(message, 1);
96         if (r < 0)
97                 goto exit;
98
99         r = sd_bus_send(m->system_bus, message, NULL);
100
101 exit:
102         if (r < 0)
103                 log_warning_errno(r, "Failed to forward Released message: %m");
104         return 0;
105 }
106
107 static int signal_disconnected(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
108         Manager *m = userdata;
109
110         assert(bus);
111         assert(message);
112         assert(m);
113
114         if (bus == m->api_bus)
115                 destroy_bus(m, &m->api_bus);
116         if (bus == m->system_bus)
117                 destroy_bus(m, &m->system_bus);
118         if (set_remove(m->private_buses, bus)) {
119                 log_debug("Got disconnect on private connection.");
120                 destroy_bus(m, &bus);
121         }
122
123         return 0;
124 }
125
126 static int signal_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
127         const char *name, *old_owner, *new_owner;
128         Manager *m = userdata;
129         int r;
130
131         assert(bus);
132         assert(message);
133         assert(m);
134
135         r = sd_bus_message_read(message, "sss", &name, &old_owner, &new_owner);
136         if (r < 0) {
137                 bus_log_parse_error(r);
138                 return 0;
139         }
140
141         manager_dispatch_bus_name_owner_changed(
142                         m, name,
143                         isempty(old_owner) ? NULL : old_owner,
144                         isempty(new_owner) ? NULL : new_owner);
145
146         return 0;
147 }
148
149 static int signal_activation_request(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
150         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
151         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
152         Manager *m = userdata;
153         const char *name;
154         Unit *u;
155         int r;
156
157         assert(bus);
158         assert(message);
159         assert(m);
160
161         r = sd_bus_message_read(message, "s", &name);
162         if (r < 0) {
163                 bus_log_parse_error(r);
164                 return 0;
165         }
166
167         if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) ||
168             manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) {
169                 r = sd_bus_error_setf(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
170                 goto failed;
171         }
172
173         r = manager_load_unit(m, name, NULL, &error, &u);
174         if (r < 0)
175                 goto failed;
176
177         if (u->refuse_manual_start) {
178                 r = sd_bus_error_setf(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, %s may be requested by dependency only.", u->id);
179                 goto failed;
180         }
181
182         r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
183         if (r < 0)
184                 goto failed;
185
186         /* Successfully queued, that's it for us */
187         return 0;
188
189 failed:
190         if (!sd_bus_error_is_set(&error))
191                 sd_bus_error_set_errno(&error, r);
192
193         log_debug("D-Bus activation failed for %s: %s", name, bus_error_message(&error, r));
194
195         r = sd_bus_message_new_signal(bus, &reply, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
196         if (r < 0) {
197                 bus_log_create_error(r);
198                 return 0;
199         }
200
201         r = sd_bus_message_append(reply, "sss", name, error.name, error.message);
202         if (r < 0) {
203                 bus_log_create_error(r);
204                 return 0;
205         }
206
207         r = sd_bus_send_to(bus, reply, "org.freedesktop.DBus", NULL);
208         if (r < 0)
209                 return log_error_errno(r, "Failed to respond with to bus activation request: %m");
210
211         return 0;
212 }
213
214 #ifdef HAVE_SELINUX
215 static int mac_selinux_filter(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
216         Manager *m = userdata;
217         const char *verb, *path;
218         Unit *u = NULL;
219         Job *j;
220         int r;
221
222         assert(bus);
223         assert(message);
224
225         /* Our own method calls are all protected individually with
226          * selinux checks, but the built-in interfaces need to be
227          * protected too. */
228
229         if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set"))
230                 verb = "reload";
231         else if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", NULL) ||
232                  sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", NULL) ||
233                  sd_bus_message_is_method_call(message, "org.freedesktop.DBus.ObjectManager", NULL) ||
234                  sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Peer", NULL))
235                 verb = "status";
236         else
237                 return 0;
238
239         path = sd_bus_message_get_path(message);
240
241         if (object_path_startswith("/org/freedesktop/systemd1", path)) {
242
243                 r = mac_selinux_access_check(message, verb, error);
244                 if (r < 0)
245                         return r;
246
247                 return 0;
248         }
249
250         if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
251                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
252                 pid_t pid;
253
254                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
255                 if (r < 0)
256                         return 0;
257
258                 r = sd_bus_creds_get_pid(creds, &pid);
259                 if (r < 0)
260                         return 0;
261
262                 u = manager_get_unit_by_pid(m, pid);
263         } else {
264                 r = manager_get_job_from_dbus_path(m, path, &j);
265                 if (r >= 0)
266                         u = j->unit;
267                 else
268                         manager_load_unit_from_dbus_path(m, path, NULL, &u);
269         }
270
271         if (!u)
272                 return 0;
273
274         r = mac_selinux_unit_access_check(u, message, verb, error);
275         if (r < 0)
276                 return r;
277
278         return 0;
279 }
280 #endif
281
282 static int bus_job_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
283         Manager *m = userdata;
284         Job *j;
285         int r;
286
287         assert(bus);
288         assert(path);
289         assert(interface);
290         assert(found);
291         assert(m);
292
293         r = manager_get_job_from_dbus_path(m, path, &j);
294         if (r < 0)
295                 return 0;
296
297         *found = j;
298         return 1;
299 }
300
301 static int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_bus_error *error) {
302         Unit *u;
303         int r;
304
305         assert(m);
306         assert(bus);
307         assert(path);
308
309         if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
310                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
311                 sd_bus_message *message;
312                 pid_t pid;
313
314                 message = sd_bus_get_current_message(bus);
315                 if (!message)
316                         return 0;
317
318                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
319                 if (r < 0)
320                         return r;
321
322                 r = sd_bus_creds_get_pid(creds, &pid);
323                 if (r < 0)
324                         return r;
325
326                 u = manager_get_unit_by_pid(m, pid);
327         } else {
328                 r = manager_load_unit_from_dbus_path(m, path, error, &u);
329                 if (r < 0)
330                         return 0;
331         }
332
333         if (!u)
334                 return 0;
335
336         *unit = u;
337         return 1;
338 }
339
340 static int bus_unit_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
341         Manager *m = userdata;
342
343         assert(bus);
344         assert(path);
345         assert(interface);
346         assert(found);
347         assert(m);
348
349         return find_unit(m, bus, path, (Unit**) found, error);
350 }
351
352 static int bus_unit_interface_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
353         Manager *m = userdata;
354         Unit *u;
355         int r;
356
357         assert(bus);
358         assert(path);
359         assert(interface);
360         assert(found);
361         assert(m);
362
363         r = find_unit(m, bus, path, &u, error);
364         if (r <= 0)
365                 return r;
366
367         if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
368                 return 0;
369
370         *found = u;
371         return 1;
372 }
373
374 static int bus_unit_cgroup_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
375         Manager *m = userdata;
376         Unit *u;
377         int r;
378
379         assert(bus);
380         assert(path);
381         assert(interface);
382         assert(found);
383         assert(m);
384
385         r = find_unit(m, bus, path, &u, error);
386         if (r <= 0)
387                 return r;
388
389         if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
390                 return 0;
391
392         if (!unit_get_cgroup_context(u))
393                 return 0;
394
395         *found = u;
396         return 1;
397 }
398
399 static int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
400         Manager *m = userdata;
401         CGroupContext *c;
402         Unit *u;
403         int r;
404
405         assert(bus);
406         assert(path);
407         assert(interface);
408         assert(found);
409         assert(m);
410
411         r = find_unit(m, bus, path, &u, error);
412         if (r <= 0)
413                 return r;
414
415         if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
416                 return 0;
417
418         c = unit_get_cgroup_context(u);
419         if (!c)
420                 return 0;
421
422         *found = c;
423         return 1;
424 }
425
426 static int bus_exec_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
427         Manager *m = userdata;
428         ExecContext *c;
429         Unit *u;
430         int r;
431
432         assert(bus);
433         assert(path);
434         assert(interface);
435         assert(found);
436         assert(m);
437
438         r = find_unit(m, bus, path, &u, error);
439         if (r <= 0)
440                 return r;
441
442         if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
443                 return 0;
444
445         c = unit_get_exec_context(u);
446         if (!c)
447                 return 0;
448
449         *found = c;
450         return 1;
451 }
452
453 static int bus_kill_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
454         Manager *m = userdata;
455         KillContext *c;
456         Unit *u;
457         int r;
458
459         assert(bus);
460         assert(path);
461         assert(interface);
462         assert(found);
463         assert(m);
464
465         r = find_unit(m, bus, path, &u, error);
466         if (r <= 0)
467                 return r;
468
469         if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
470                 return 0;
471
472         c = unit_get_kill_context(u);
473         if (!c)
474                 return 0;
475
476         *found = c;
477         return 1;
478 }
479
480 static int bus_job_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
481         _cleanup_free_ char **l = NULL;
482         Manager *m = userdata;
483         unsigned k = 0;
484         Iterator i;
485         Job *j;
486
487         l = new0(char*, hashmap_size(m->jobs)+1);
488         if (!l)
489                 return -ENOMEM;
490
491         HASHMAP_FOREACH(j, m->jobs, i) {
492                 l[k] = job_dbus_path(j);
493                 if (!l[k])
494                         return -ENOMEM;
495
496                 k++;
497         }
498
499         assert(hashmap_size(m->jobs) == k);
500
501         *nodes = l;
502         l = NULL;
503
504         return k;
505 }
506
507 static int bus_unit_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
508         _cleanup_free_ char **l = NULL;
509         Manager *m = userdata;
510         unsigned k = 0;
511         Iterator i;
512         Unit *u;
513
514         l = new0(char*, hashmap_size(m->units)+1);
515         if (!l)
516                 return -ENOMEM;
517
518         HASHMAP_FOREACH(u, m->units, i) {
519                 l[k] = unit_dbus_path(u);
520                 if (!l[k])
521                         return -ENOMEM;
522
523                 k++;
524         }
525
526         *nodes = l;
527         l = NULL;
528
529         return k;
530 }
531
532 static int bus_setup_api_vtables(Manager *m, sd_bus *bus) {
533         UnitType t;
534         int r;
535
536         assert(m);
537         assert(bus);
538
539 #ifdef HAVE_SELINUX
540         r = sd_bus_add_filter(bus, NULL, mac_selinux_filter, m);
541         if (r < 0)
542                 return log_error_errno(r, "Failed to add SELinux access filter: %m");
543 #endif
544
545         r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m);
546         if (r < 0)
547                 return log_error_errno(r, "Failed to register Manager vtable: %m");
548
549         r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m);
550         if (r < 0)
551                 return log_error_errno(r, "Failed to register Job vtable: %m");
552
553         r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/job", bus_job_enumerate, m);
554         if (r < 0)
555                 return log_error_errno(r, "Failed to add job enumerator: %m");
556
557         r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, m);
558         if (r < 0)
559                 return log_error_errno(r, "Failed to register Unit vtable: %m");
560
561         r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/unit", bus_unit_enumerate, m);
562         if (r < 0)
563                 return log_error_errno(r, "Failed to add job enumerator: %m");
564
565         for (t = 0; t < _UNIT_TYPE_MAX; t++) {
566                 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);
567                 if (r < 0)
568                         return log_error_errno(r, "Failed to register type specific vtable for %s: %m", unit_vtable[t]->bus_interface);
569
570                 if (unit_vtable[t]->cgroup_context_offset > 0) {
571                         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);
572                         if (r < 0)
573                                 return log_error_errno(r, "Failed to register control group unit vtable for %s: %m", unit_vtable[t]->bus_interface);
574
575                         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);
576                         if (r < 0)
577                                 return log_error_errno(r, "Failed to register control group vtable for %s: %m", unit_vtable[t]->bus_interface);
578                 }
579
580                 if (unit_vtable[t]->exec_context_offset > 0) {
581                         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);
582                         if (r < 0)
583                                 return log_error_errno(r, "Failed to register execute vtable for %s: %m", unit_vtable[t]->bus_interface);
584                 }
585
586                 if (unit_vtable[t]->kill_context_offset > 0) {
587                         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);
588                         if (r < 0)
589                                 return log_error_errno(r, "Failed to register kill vtable for %s: %m", unit_vtable[t]->bus_interface);
590                 }
591         }
592
593         return 0;
594 }
595
596 static int bus_setup_disconnected_match(Manager *m, sd_bus *bus) {
597         int r;
598
599         assert(m);
600         assert(bus);
601
602         r = sd_bus_add_match(
603                         bus,
604                         NULL,
605                         "sender='org.freedesktop.DBus.Local',"
606                         "type='signal',"
607                         "path='/org/freedesktop/DBus/Local',"
608                         "interface='org.freedesktop.DBus.Local',"
609                         "member='Disconnected'",
610                         signal_disconnected, m);
611
612         if (r < 0)
613                 return log_error_errno(r, "Failed to register match for Disconnected message: %m");
614
615         return 0;
616 }
617
618 static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
619         _cleanup_bus_unref_ sd_bus *bus = NULL;
620         _cleanup_close_ int nfd = -1;
621         Manager *m = userdata;
622         sd_id128_t id;
623         int r;
624
625         assert(s);
626         assert(m);
627
628         nfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
629         if (nfd < 0) {
630                 log_warning_errno(errno, "Failed to accept private connection, ignoring: %m");
631                 return 0;
632         }
633
634         if (set_size(m->private_buses) >= CONNECTIONS_MAX) {
635                 log_warning("Too many concurrent connections, refusing");
636                 return 0;
637         }
638
639         r = set_ensure_allocated(&m->private_buses, NULL);
640         if (r < 0) {
641                 log_oom();
642                 return 0;
643         }
644
645         r = sd_bus_new(&bus);
646         if (r < 0) {
647                 log_warning_errno(r, "Failed to allocate new private connection bus: %m");
648                 return 0;
649         }
650
651         r = sd_bus_set_fd(bus, nfd, nfd);
652         if (r < 0) {
653                 log_warning_errno(r, "Failed to set fd on new connection bus: %m");
654                 return 0;
655         }
656
657         nfd = -1;
658
659         r = bus_check_peercred(bus);
660         if (r < 0) {
661                 log_warning_errno(r, "Incoming private connection from unprivileged client, refusing: %m");
662                 return 0;
663         }
664
665         assert_se(sd_id128_randomize(&id) >= 0);
666
667         r = sd_bus_set_server(bus, 1, id);
668         if (r < 0) {
669                 log_warning_errno(r, "Failed to enable server support for new connection bus: %m");
670                 return 0;
671         }
672
673         r = sd_bus_start(bus);
674         if (r < 0) {
675                 log_warning_errno(r, "Failed to start new connection bus: %m");
676                 return 0;
677         }
678
679         r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
680         if (r < 0) {
681                 log_warning_errno(r, "Failed to attach new connection bus to event loop: %m");
682                 return 0;
683         }
684
685         if (m->running_as == SYSTEMD_SYSTEM) {
686                 /* When we run as system instance we get the Released
687                  * signal via a direct connection */
688
689                 r = sd_bus_add_match(
690                                 bus,
691                                 NULL,
692                                 "type='signal',"
693                                 "interface='org.freedesktop.systemd1.Agent',"
694                                 "member='Released',"
695                                 "path='/org/freedesktop/systemd1/agent'",
696                                 signal_agent_released, m);
697
698                 if (r < 0) {
699                         log_warning_errno(r, "Failed to register Released match on new connection bus: %m");
700                         return 0;
701                 }
702         }
703
704         r = bus_setup_disconnected_match(m, bus);
705         if (r < 0)
706                 return 0;
707
708         r = bus_setup_api_vtables(m, bus);
709         if (r < 0) {
710                 log_warning_errno(r, "Failed to set up API vtables on new connection bus: %m");
711                 return 0;
712         }
713
714         r = set_put(m->private_buses, bus);
715         if (r < 0) {
716                 log_warning_errno(r, "Failed to add new conenction bus to set: %m");
717                 return 0;
718         }
719
720         bus = NULL;
721
722         log_debug("Accepted new private connection.");
723
724         return 0;
725 }
726
727 static int bus_list_names(Manager *m, sd_bus *bus) {
728         _cleanup_strv_free_ char **names = NULL;
729         char **i;
730         int r;
731
732         assert(m);
733         assert(bus);
734
735         r = sd_bus_list_names(bus, &names, NULL);
736         if (r < 0)
737                 return log_error_errno(r, "Failed to get initial list of names: %m");
738
739         /* This is a bit hacky, we say the owner of the name is the
740          * name itself, because we don't want the extra traffic to
741          * figure out the real owner. */
742         STRV_FOREACH(i, names)
743                 manager_dispatch_bus_name_owner_changed(m, *i, NULL, *i);
744
745         return 0;
746 }
747
748 static int bus_setup_api(Manager *m, sd_bus *bus) {
749         int r;
750
751         assert(m);
752         assert(bus);
753
754         /* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
755         r = sd_bus_negotiate_creds(bus, 1,
756                                    SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|
757                                    SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS|
758                                    SD_BUS_CREDS_SELINUX_CONTEXT);
759         if (r < 0)
760                 log_warning_errno(r, "Failed to enable credential passing, ignoring: %m");
761
762         r = bus_setup_api_vtables(m, bus);
763         if (r < 0)
764                 return r;
765
766         r = sd_bus_add_match(
767                         bus,
768                         NULL,
769                         "type='signal',"
770                         "sender='org.freedesktop.DBus',"
771                         "path='/org/freedesktop/DBus',"
772                         "interface='org.freedesktop.DBus',"
773                         "member='NameOwnerChanged'",
774                         signal_name_owner_changed, m);
775         if (r < 0)
776                 log_warning_errno(r, "Failed to subscribe to NameOwnerChanged signal: %m");
777
778         r = sd_bus_add_match(
779                         bus,
780                         NULL,
781                         "type='signal',"
782                         "sender='org.freedesktop.DBus',"
783                         "path='/org/freedesktop/DBus',"
784                         "interface='org.freedesktop.systemd1.Activator',"
785                         "member='ActivationRequest'",
786                         signal_activation_request, m);
787         if (r < 0)
788                 log_warning_errno(r, "Failed to subscribe to activation signal: %m");
789
790         /* Allow replacing of our name, to ease implementation of
791          * reexecution, where we keep the old connection open until
792          * after the new connection is set up and the name installed
793          * to allow clients to synchronously wait for reexecution to
794          * finish */
795         r = sd_bus_request_name(bus,"org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_ALLOW_REPLACEMENT);
796         if (r < 0)
797                 return log_error_errno(r, "Failed to register name: %m");
798
799         bus_list_names(m, bus);
800
801         log_debug("Successfully connected to API bus.");
802         return 0;
803 }
804
805 static int bus_init_api(Manager *m) {
806         _cleanup_bus_unref_ sd_bus *bus = NULL;
807         int r;
808
809         if (m->api_bus)
810                 return 0;
811
812         /* The API and system bus is the same if we are running in system mode */
813         if (m->running_as == SYSTEMD_SYSTEM && m->system_bus)
814                 bus = sd_bus_ref(m->system_bus);
815         else {
816                 if (m->running_as == SYSTEMD_SYSTEM)
817                         r = sd_bus_open_system(&bus);
818                 else
819                         r = sd_bus_open_user(&bus);
820
821                 if (r < 0) {
822                         log_debug("Failed to connect to API bus, retrying later...");
823                         return 0;
824                 }
825
826                 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
827                 if (r < 0) {
828                         log_error_errno(r, "Failed to attach API bus to event loop: %m");
829                         return 0;
830                 }
831
832                 r = bus_setup_disconnected_match(m, bus);
833                 if (r < 0)
834                         return 0;
835         }
836
837         r = bus_setup_api(m, bus);
838         if (r < 0) {
839                 log_error_errno(r, "Failed to set up API bus: %m");
840                 return 0;
841         }
842
843         m->api_bus = bus;
844         bus = NULL;
845
846         return 0;
847 }
848
849 static int bus_setup_system(Manager *m, sd_bus *bus) {
850         int r;
851
852         assert(m);
853         assert(bus);
854
855         /* On kdbus or if we are a user instance we get the Released message via the system bus */
856         if (m->running_as == SYSTEMD_USER || m->kdbus_fd >= 0) {
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                 if (r < 0)
866                         log_warning_errno(r, "Failed to register Released match on system bus: %m");
867         }
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_units_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, UID_INVALID, &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_units_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, UID_INVALID, &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, UID_INVALID, &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, UID_INVALID, &m->polkit_registry, error);
1210 }
1211
1212 int bus_verify_set_environment_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1213         return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.set-environment", false, UID_INVALID, &m->polkit_registry, error);
1214 }