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