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