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