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