]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - src/core/dbus-unit.c
seccomp-util: allowlist open_tree() as part of @file-system
[thirdparty/systemd.git] / src / core / dbus-unit.c
... / ...
CommitLineData
1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3#include <unistd.h>
4
5#include "sd-bus.h"
6
7#include "alloc-util.h"
8#include "bitfield.h"
9#include "bus-common-errors.h"
10#include "bus-get-properties.h"
11#include "bus-util.h"
12#include "cgroup-util.h"
13#include "condition.h"
14#include "dbus.h"
15#include "dbus-job.h"
16#include "dbus-manager.h"
17#include "dbus-unit.h"
18#include "dbus-util.h"
19#include "fd-util.h"
20#include "format-util.h"
21#include "install.h"
22#include "locale-util.h"
23#include "log.h"
24#include "manager.h"
25#include "namespace-util.h"
26#include "path-util.h"
27#include "process-util.h"
28#include "selinux-access.h"
29#include "service.h"
30#include "set.h"
31#include "signal-util.h"
32#include "special.h"
33#include "string-util.h"
34#include "strv.h"
35#include "transaction.h"
36#include "unit-name.h"
37#include "web-util.h"
38
39static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_collect_mode, collect_mode, CollectMode);
40static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state, unit_load_state, UnitLoadState);
41static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_job_mode, job_mode, JobMode);
42static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_freezer_state, freezer_state, FreezerState);
43static BUS_DEFINE_PROPERTY_GET(property_get_description, "s", Unit, unit_description);
44static BUS_DEFINE_PROPERTY_GET2(property_get_active_state, "s", Unit, unit_active_state, unit_active_state_to_string);
45static BUS_DEFINE_PROPERTY_GET(property_get_sub_state, "s", Unit, unit_sub_state_to_string);
46static BUS_DEFINE_PROPERTY_GET2(property_get_unit_file_state, "s", Unit, unit_get_unit_file_state, unit_file_state_to_string);
47static BUS_DEFINE_PROPERTY_GET(property_get_can_reload, "b", Unit, unit_can_reload);
48static BUS_DEFINE_PROPERTY_GET(property_get_can_start, "b", Unit, unit_can_start_refuse_manual);
49static BUS_DEFINE_PROPERTY_GET(property_get_can_stop, "b", Unit, unit_can_stop_refuse_manual);
50static BUS_DEFINE_PROPERTY_GET(property_get_can_isolate, "b", Unit, unit_can_isolate_refuse_manual);
51static BUS_DEFINE_PROPERTY_GET(property_get_can_freeze, "b", Unit, unit_can_freeze);
52static BUS_DEFINE_PROPERTY_GET(property_get_need_daemon_reload, "b", Unit, unit_need_daemon_reload);
53static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_empty_strv, "as", 0);
54
55static int property_get_can_clean(
56 sd_bus *bus,
57 const char *path,
58 const char *interface,
59 const char *property,
60 sd_bus_message *reply,
61 void *userdata,
62 sd_bus_error *error) {
63
64 Unit *u = userdata;
65 ExecCleanMask mask;
66 int r;
67
68 assert(bus);
69 assert(reply);
70
71 r = unit_can_clean(u, &mask);
72 if (r < 0)
73 return r;
74
75 r = sd_bus_message_open_container(reply, 'a', "s");
76 if (r < 0)
77 return r;
78
79 for (ExecDirectoryType t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) {
80 if (!BIT_SET(mask, t))
81 continue;
82
83 r = sd_bus_message_append(reply, "s", exec_resource_type_to_string(t));
84 if (r < 0)
85 return r;
86 }
87
88 if (FLAGS_SET(mask, EXEC_CLEAN_FDSTORE)) {
89 r = sd_bus_message_append(reply, "s", "fdstore");
90 if (r < 0)
91 return r;
92 }
93
94 return sd_bus_message_close_container(reply);
95}
96
97static int property_get_can_live_mount(
98 sd_bus *bus,
99 const char *path,
100 const char *interface,
101 const char *property,
102 sd_bus_message *reply,
103 void *userdata,
104 sd_bus_error *error) {
105
106 Unit *u = ASSERT_PTR(userdata);
107
108 assert(bus);
109 assert(reply);
110
111 return sd_bus_message_append(reply, "b", unit_can_live_mount(u, /* error= */ NULL) >= 0);
112}
113
114static int property_get_names(
115 sd_bus *bus,
116 const char *path,
117 const char *interface,
118 const char *property,
119 sd_bus_message *reply,
120 void *userdata,
121 sd_bus_error *error) {
122
123 Unit *u = ASSERT_PTR(userdata);
124 const char *t;
125 int r;
126
127 assert(bus);
128 assert(reply);
129
130 r = sd_bus_message_open_container(reply, 'a', "s");
131 if (r < 0)
132 return r;
133
134 r = sd_bus_message_append(reply, "s", u->id);
135 if (r < 0)
136 return r;
137
138 SET_FOREACH(t, u->aliases) {
139 r = sd_bus_message_append(reply, "s", t);
140 if (r < 0)
141 return r;
142 }
143
144 return sd_bus_message_close_container(reply);
145}
146
147static int property_get_following(
148 sd_bus *bus,
149 const char *path,
150 const char *interface,
151 const char *property,
152 sd_bus_message *reply,
153 void *userdata,
154 sd_bus_error *error) {
155
156 Unit *u = userdata, *f;
157
158 assert(bus);
159 assert(reply);
160 assert(u);
161
162 f = unit_following(u);
163 return sd_bus_message_append(reply, "s", f ? f->id : NULL);
164}
165
166static int property_get_dependencies(
167 sd_bus *bus,
168 const char *path,
169 const char *interface,
170 const char *property,
171 sd_bus_message *reply,
172 void *userdata,
173 sd_bus_error *error) {
174
175 Unit *u = userdata, *other;
176 UnitDependency d;
177 Hashmap *deps;
178 void *v;
179 int r;
180
181 assert(bus);
182 assert(reply);
183 assert(u);
184
185 d = unit_dependency_from_string(property);
186 assert_se(d >= 0);
187
188 deps = unit_get_dependencies(u, d);
189
190 r = sd_bus_message_open_container(reply, 'a', "s");
191 if (r < 0)
192 return r;
193
194 HASHMAP_FOREACH_KEY(v, other, deps) {
195 r = sd_bus_message_append(reply, "s", other->id);
196 if (r < 0)
197 return r;
198 }
199
200 return sd_bus_message_close_container(reply);
201}
202
203static int property_get_mounts_for(
204 sd_bus *bus,
205 const char *path,
206 const char *interface,
207 const char *property,
208 sd_bus_message *reply,
209 void *userdata,
210 sd_bus_error *error) {
211
212 Hashmap **h = ASSERT_PTR(userdata);
213 const char *p;
214 void *v;
215 int r;
216
217 assert(bus);
218 assert(reply);
219
220 r = sd_bus_message_open_container(reply, 'a', "s");
221 if (r < 0)
222 return r;
223
224 HASHMAP_FOREACH_KEY(v, p, *h) {
225 r = sd_bus_message_append(reply, "s", p);
226 if (r < 0)
227 return r;
228 }
229
230 return sd_bus_message_close_container(reply);
231}
232
233static int property_get_unit_file_preset(
234 sd_bus *bus,
235 const char *path,
236 const char *interface,
237 const char *property,
238 sd_bus_message *reply,
239 void *userdata,
240 sd_bus_error *error) {
241
242 Unit *u = ASSERT_PTR(userdata);
243 int r;
244
245 assert(bus);
246 assert(reply);
247
248 r = unit_get_unit_file_preset(u);
249
250 return sd_bus_message_append(reply, "s", preset_action_past_tense_to_string(r));
251}
252
253static int property_get_job(
254 sd_bus *bus,
255 const char *path,
256 const char *interface,
257 const char *property,
258 sd_bus_message *reply,
259 void *userdata,
260 sd_bus_error *error) {
261
262 _cleanup_free_ char *p = NULL;
263 Job **j = ASSERT_PTR(userdata);
264
265 assert(bus);
266 assert(reply);
267
268 if (!*j)
269 return sd_bus_message_append(reply, "(uo)", 0, "/");
270
271 p = job_dbus_path(*j);
272 if (!p)
273 return -ENOMEM;
274
275 return sd_bus_message_append(reply, "(uo)", (*j)->id, p);
276}
277
278static int property_get_conditions(
279 sd_bus *bus,
280 const char *path,
281 const char *interface,
282 const char *property,
283 sd_bus_message *reply,
284 void *userdata,
285 sd_bus_error *error) {
286
287 const char *(*to_string)(ConditionType type) = NULL;
288 Condition **list = ASSERT_PTR(userdata);
289 int r;
290
291 assert(bus);
292 assert(reply);
293
294 to_string = streq(property, "Asserts") ? assert_type_to_string : condition_type_to_string;
295
296 r = sd_bus_message_open_container(reply, 'a', "(sbbsi)");
297 if (r < 0)
298 return r;
299
300 LIST_FOREACH(conditions, c, *list) {
301 int tristate;
302
303 tristate =
304 c->result == CONDITION_UNTESTED ? 0 :
305 c->result == CONDITION_SUCCEEDED ? 1 : -1;
306
307 r = sd_bus_message_append(reply, "(sbbsi)",
308 to_string(c->type),
309 c->trigger, c->negate,
310 c->parameter, tristate);
311 if (r < 0)
312 return r;
313
314 }
315
316 return sd_bus_message_close_container(reply);
317}
318
319static int property_get_load_error(
320 sd_bus *bus,
321 const char *path,
322 const char *interface,
323 const char *property,
324 sd_bus_message *reply,
325 void *userdata,
326 sd_bus_error *error) {
327
328 _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
329 Unit *u = ASSERT_PTR(userdata);
330 int r;
331
332 assert(bus);
333 assert(reply);
334
335 r = bus_unit_validate_load_state(u, &e);
336 if (r < 0)
337 return sd_bus_message_append(reply, "(ss)", e.name, e.message);
338
339 return sd_bus_message_append(reply, "(ss)", NULL, NULL);
340}
341
342static int property_get_markers(
343 sd_bus *bus,
344 const char *path,
345 const char *interface,
346 const char *property,
347 sd_bus_message *reply,
348 void *userdata,
349 sd_bus_error *error) {
350
351 unsigned *markers = ASSERT_PTR(userdata);
352 int r;
353
354 assert(bus);
355 assert(reply);
356
357 r = sd_bus_message_open_container(reply, 'a', "s");
358 if (r < 0)
359 return r;
360
361 BIT_FOREACH(m, *markers) {
362 r = sd_bus_message_append(reply, "s", unit_marker_to_string(m));
363 if (r < 0)
364 return r;
365 }
366
367 return sd_bus_message_close_container(reply);
368}
369
370static const char *const polkit_message_for_job[_JOB_TYPE_MAX] = {
371 [JOB_START] = N_("Authentication is required to start '$(unit)'."),
372 [JOB_STOP] = N_("Authentication is required to stop '$(unit)'."),
373 [JOB_RELOAD] = N_("Authentication is required to reload '$(unit)'."),
374 [JOB_RESTART] = N_("Authentication is required to restart '$(unit)'."),
375 [JOB_TRY_RESTART] = N_("Authentication is required to restart '$(unit)'."),
376};
377
378int bus_unit_method_start_generic(
379 sd_bus_message *message,
380 Unit *u,
381 JobType job_type,
382 bool reload_if_possible,
383 sd_bus_error *error) {
384
385 BusUnitQueueFlags job_flags = reload_if_possible ? BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE : 0;
386 const char *smode, *verb;
387 JobMode mode;
388 int r;
389
390 assert(message);
391 assert(u);
392 assert(job_type >= 0 && job_type < _JOB_TYPE_MAX);
393
394 r = mac_selinux_unit_access_check(
395 u, message,
396 job_type_to_access_method(job_type),
397 error);
398 if (r < 0)
399 return r;
400
401 r = sd_bus_message_read(message, "s", &smode);
402 if (r < 0)
403 return r;
404
405 mode = job_mode_from_string(smode);
406 if (mode < 0)
407 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s invalid", smode);
408
409 if (reload_if_possible)
410 verb = strjoina("reload-or-", job_type_to_string(job_type));
411 else
412 verb = job_type_to_string(job_type);
413
414 if (sd_bus_message_is_method_call(message, NULL, "StartUnitWithFlags")) {
415 uint64_t input_flags = 0;
416
417 r = sd_bus_message_read(message, "t", &input_flags);
418 if (r < 0)
419 return r;
420 /* Let clients know that this version doesn't support any flags at the moment. */
421 if (input_flags != 0)
422 return sd_bus_reply_method_errorf(message, SD_BUS_ERROR_INVALID_ARGS,
423 "Invalid 'flags' parameter '%" PRIu64 "'",
424 input_flags);
425 }
426
427 r = bus_verify_manage_units_async_full(
428 u,
429 verb,
430 polkit_message_for_job[job_type],
431 message,
432 error);
433 if (r < 0)
434 return r;
435 if (r == 0)
436 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
437
438 return bus_unit_queue_job(message, u, job_type, mode, job_flags, error);
439}
440
441static int bus_unit_method_start(sd_bus_message *message, void *userdata, sd_bus_error *error) {
442 return bus_unit_method_start_generic(message, userdata, JOB_START, false, error);
443}
444
445static int bus_unit_method_stop(sd_bus_message *message, void *userdata, sd_bus_error *error) {
446 return bus_unit_method_start_generic(message, userdata, JOB_STOP, false, error);
447}
448
449static int bus_unit_method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) {
450 return bus_unit_method_start_generic(message, userdata, JOB_RELOAD, false, error);
451}
452
453static int bus_unit_method_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) {
454 return bus_unit_method_start_generic(message, userdata, JOB_RESTART, false, error);
455}
456
457static int bus_unit_method_try_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) {
458 return bus_unit_method_start_generic(message, userdata, JOB_TRY_RESTART, false, error);
459}
460
461static int bus_unit_method_reload_or_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) {
462 return bus_unit_method_start_generic(message, userdata, JOB_RESTART, true, error);
463}
464
465static int bus_unit_method_reload_or_try_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) {
466 return bus_unit_method_start_generic(message, userdata, JOB_TRY_RESTART, true, error);
467}
468
469int bus_unit_method_enqueue_job(sd_bus_message *message, void *userdata, sd_bus_error *error) {
470 BusUnitQueueFlags flags = BUS_UNIT_QUEUE_VERBOSE_REPLY;
471 const char *jtype, *smode;
472 Unit *u = ASSERT_PTR(userdata);
473 JobType type;
474 JobMode mode;
475 int r;
476
477 assert(message);
478
479 r = sd_bus_message_read(message, "ss", &jtype, &smode);
480 if (r < 0)
481 return r;
482
483 /* Parse the two magic reload types "reload-or-…" manually */
484 if (streq(jtype, "reload-or-restart")) {
485 type = JOB_RESTART;
486 flags |= BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE;
487 } else if (streq(jtype, "reload-or-try-restart")) {
488 type = JOB_TRY_RESTART;
489 flags |= BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE;
490 } else {
491 /* And the rest generically */
492 type = job_type_from_string(jtype);
493 if (type < 0)
494 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job type %s invalid", jtype);
495 }
496
497 mode = job_mode_from_string(smode);
498 if (mode < 0)
499 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s invalid", smode);
500
501 r = mac_selinux_unit_access_check(
502 u, message,
503 job_type_to_access_method(type),
504 error);
505 if (r < 0)
506 return r;
507
508 r = bus_verify_manage_units_async_full(
509 u,
510 jtype,
511 polkit_message_for_job[type],
512 message,
513 error);
514 if (r < 0)
515 return r;
516 if (r == 0)
517 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
518
519 return bus_unit_queue_job(message, u, type, mode, flags, error);
520}
521
522int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) {
523 Unit *u = ASSERT_PTR(userdata);
524 int32_t value = 0;
525 const char *swhom;
526 int32_t signo;
527 KillWhom whom;
528 int r, code;
529
530 assert(message);
531
532 r = mac_selinux_unit_access_check(u, message, "stop", error);
533 if (r < 0)
534 return r;
535
536 r = sd_bus_message_read(message, "si", &swhom, &signo);
537 if (r < 0)
538 return r;
539
540 if (startswith(sd_bus_message_get_member(message), "QueueSignal")) {
541 r = sd_bus_message_read(message, "i", &value);
542 if (r < 0)
543 return r;
544
545 code = SI_QUEUE;
546 } else
547 code = SI_USER;
548
549 if (isempty(swhom))
550 whom = KILL_ALL;
551 else {
552 whom = kill_whom_from_string(swhom);
553 if (whom < 0)
554 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid whom argument: %s", swhom);
555 }
556
557 if (!SIGNAL_VALID(signo))
558 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Signal number out of range.");
559
560 if (code == SI_QUEUE && !((signo >= SIGRTMIN) && (signo <= SIGRTMAX)))
561 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
562 "Value parameter only accepted for realtime signals (SIGRTMIN…SIGRTMAX), refusing for signal SIG%s.", signal_to_string(signo));
563
564 r = bus_verify_manage_units_async_full(
565 u,
566 "kill",
567 N_("Authentication is required to send a UNIX signal to the processes of '$(unit)'."),
568 message,
569 error);
570 if (r < 0)
571 return r;
572 if (r == 0)
573 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
574
575 r = unit_kill(u, whom, signo, code, value, error);
576 if (r < 0)
577 return r;
578
579 return sd_bus_reply_method_return(message, NULL);
580}
581
582int bus_unit_method_reset_failed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
583 Unit *u = ASSERT_PTR(userdata);
584 int r;
585
586 assert(message);
587
588 r = mac_selinux_unit_access_check(u, message, "reload", error);
589 if (r < 0)
590 return r;
591
592 r = bus_verify_manage_units_async_full(
593 u,
594 "reset-failed",
595 N_("Authentication is required to reset the \"failed\" state of '$(unit)'."),
596 message,
597 error);
598 if (r < 0)
599 return r;
600 if (r == 0)
601 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
602
603 unit_reset_failed(u);
604
605 return sd_bus_reply_method_return(message, NULL);
606}
607
608int bus_unit_method_set_properties(sd_bus_message *message, void *userdata, sd_bus_error *error) {
609 Unit *u = ASSERT_PTR(userdata);
610 int runtime, r;
611
612 assert(message);
613
614 r = mac_selinux_unit_access_check(u, message, "start", error);
615 if (r < 0)
616 return r;
617
618 r = sd_bus_message_read(message, "b", &runtime);
619 if (r < 0)
620 return r;
621
622 r = bus_verify_manage_units_async_full(
623 u,
624 "set-property",
625 N_("Authentication is required to set properties on '$(unit)'."),
626 message,
627 error);
628 if (r < 0)
629 return r;
630 if (r == 0)
631 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
632
633 r = bus_unit_set_properties(u, message, runtime ? UNIT_RUNTIME : UNIT_PERSISTENT, true, error);
634 if (r < 0)
635 return r;
636
637 return sd_bus_reply_method_return(message, NULL);
638}
639
640int bus_unit_method_ref(sd_bus_message *message, void *userdata, sd_bus_error *error) {
641 Unit *u = ASSERT_PTR(userdata);
642 int r;
643
644 assert(message);
645
646 r = mac_selinux_unit_access_check(u, message, "start", error);
647 if (r < 0)
648 return r;
649
650 r = bus_verify_manage_units_async_full(
651 u,
652 "ref",
653 /* polkit_message= */ NULL,
654 message,
655 error);
656 if (r < 0)
657 return r;
658 if (r == 0)
659 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
660
661 r = bus_unit_track_add_sender(u, message);
662 if (r < 0)
663 return r;
664
665 return sd_bus_reply_method_return(message, NULL);
666}
667
668int bus_unit_method_unref(sd_bus_message *message, void *userdata, sd_bus_error *error) {
669 Unit *u = ASSERT_PTR(userdata);
670 int r;
671
672 assert(message);
673
674 r = bus_unit_track_remove_sender(u, message);
675 if (r == -EUNATCH)
676 return sd_bus_error_set(error, BUS_ERROR_NOT_REFERENCED, "Unit has not been referenced yet.");
677 if (r < 0)
678 return r;
679
680 return sd_bus_reply_method_return(message, NULL);
681}
682
683int bus_unit_method_clean(sd_bus_message *message, void *userdata, sd_bus_error *error) {
684 ExecCleanMask mask = 0;
685 Unit *u = ASSERT_PTR(userdata);
686 int r;
687
688 assert(message);
689
690 r = mac_selinux_unit_access_check(u, message, "stop", error);
691 if (r < 0)
692 return r;
693
694 r = sd_bus_message_enter_container(message, 'a', "s");
695 if (r < 0)
696 return r;
697
698 for (;;) {
699 ExecCleanMask m;
700 const char *i;
701
702 r = sd_bus_message_read(message, "s", &i);
703 if (r < 0)
704 return r;
705 if (r == 0)
706 break;
707
708 m = exec_clean_mask_from_string(i);
709 if (m < 0)
710 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid resource type: %s", i);
711
712 mask |= m;
713 }
714
715 r = sd_bus_message_exit_container(message);
716 if (r < 0)
717 return r;
718
719 r = bus_verify_manage_units_async_full(
720 u,
721 "clean",
722 N_("Authentication is required to delete files and directories associated with '$(unit)'."),
723 message,
724 error);
725 if (r < 0)
726 return r;
727 if (r == 0)
728 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
729
730 r = unit_clean(u, mask);
731 if (r == -EOPNOTSUPP)
732 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Unit '%s' does not support cleaning.", u->id);
733 if (r == -EUNATCH)
734 return sd_bus_error_set(error, BUS_ERROR_NOTHING_TO_CLEAN, "No matching resources found.");
735 if (r == -EBUSY)
736 return sd_bus_error_set(error, BUS_ERROR_UNIT_BUSY, "Unit is not inactive or has pending job.");
737 if (r < 0)
738 return r;
739
740 return sd_bus_reply_method_return(message, NULL);
741}
742
743static int bus_unit_method_freezer_generic(sd_bus_message *message, void *userdata, sd_bus_error *error, FreezerAction action) {
744 Unit *u = ASSERT_PTR(userdata);
745 int r;
746
747 assert(message);
748 assert(IN_SET(action, FREEZER_FREEZE, FREEZER_THAW));
749
750 const char *perm = action == FREEZER_FREEZE ? "stop" : "start";
751
752 r = mac_selinux_unit_access_check(u, message, perm, error);
753 if (r < 0)
754 return r;
755
756 r = bus_verify_manage_units_async_full(
757 u,
758 perm,
759 N_("Authentication is required to freeze or thaw the processes of '$(unit)' unit."),
760 message,
761 error);
762 if (r < 0)
763 return r;
764 if (r == 0)
765 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
766
767 r = unit_freezer_action(u, action);
768 if (r == -EOPNOTSUPP)
769 return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Unit does not support freeze/thaw");
770 if (r == -EBUSY)
771 return sd_bus_error_set(error, BUS_ERROR_UNIT_BUSY, "Unit has a pending job");
772 if (r == -EHOSTDOWN)
773 return sd_bus_error_set(error, BUS_ERROR_UNIT_INACTIVE, "Unit is not active");
774 if (r == -EALREADY)
775 return sd_bus_error_set(error, BUS_ERROR_UNIT_BUSY, "Previously requested freezer operation for unit is still in progress");
776 if (r == -EDEADLK)
777 return sd_bus_error_set(error, BUS_ERROR_FROZEN_BY_PARENT, "Unit is frozen by a parent slice");
778 if (r < 0)
779 return r;
780
781 bool reply_now = r == 0;
782
783 if (u->pending_freezer_invocation) {
784 bus_unit_send_pending_freezer_message(u, true);
785 assert(!u->pending_freezer_invocation);
786 }
787
788 u->pending_freezer_invocation = sd_bus_message_ref(message);
789
790 if (reply_now) {
791 r = bus_unit_send_pending_freezer_message(u, false);
792 if (r < 0)
793 return r;
794 }
795
796 return 1;
797}
798
799int bus_unit_method_thaw(sd_bus_message *message, void *userdata, sd_bus_error *error) {
800 return bus_unit_method_freezer_generic(message, userdata, error, FREEZER_THAW);
801}
802
803int bus_unit_method_freeze(sd_bus_message *message, void *userdata, sd_bus_error *error) {
804 return bus_unit_method_freezer_generic(message, userdata, error, FREEZER_FREEZE);
805}
806
807static int property_get_refs(
808 sd_bus *bus,
809 const char *path,
810 const char *interface,
811 const char *property,
812 sd_bus_message *reply,
813 void *userdata,
814 sd_bus_error *error) {
815
816 Unit *u = userdata;
817 int r;
818
819 assert(bus);
820 assert(reply);
821
822 r = sd_bus_message_open_container(reply, 'a', "s");
823 if (r < 0)
824 return r;
825
826 for (const char *i = sd_bus_track_first(u->bus_track); i; i = sd_bus_track_next(u->bus_track)) {
827 int c;
828
829 c = sd_bus_track_count_name(u->bus_track, i);
830 if (c < 0)
831 return c;
832
833 /* Add the item multiple times if the ref count for each is above 1 */
834 for (int k = 0; k < c; k++) {
835 r = sd_bus_message_append(reply, "s", i);
836 if (r < 0)
837 return r;
838 }
839 }
840
841 return sd_bus_message_close_container(reply);
842}
843
844const sd_bus_vtable bus_unit_vtable[] = {
845 SD_BUS_VTABLE_START(0),
846
847 SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Unit, id), SD_BUS_VTABLE_PROPERTY_CONST),
848 SD_BUS_PROPERTY("Names", "as", property_get_names, 0, SD_BUS_VTABLE_PROPERTY_CONST),
849 SD_BUS_PROPERTY("Following", "s", property_get_following, 0, 0),
850 SD_BUS_PROPERTY("Requires", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
851 SD_BUS_PROPERTY("Requisite", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
852 SD_BUS_PROPERTY("Wants", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
853 SD_BUS_PROPERTY("BindsTo", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
854 SD_BUS_PROPERTY("PartOf", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
855 SD_BUS_PROPERTY("Upholds", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
856 SD_BUS_PROPERTY("RequiredBy", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
857 SD_BUS_PROPERTY("RequisiteOf", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
858 SD_BUS_PROPERTY("WantedBy", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
859 SD_BUS_PROPERTY("BoundBy", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
860 SD_BUS_PROPERTY("UpheldBy", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
861 SD_BUS_PROPERTY("ConsistsOf", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
862 SD_BUS_PROPERTY("Conflicts", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
863 SD_BUS_PROPERTY("ConflictedBy", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
864 SD_BUS_PROPERTY("Before", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
865 SD_BUS_PROPERTY("After", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
866 SD_BUS_PROPERTY("OnSuccess", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
867 SD_BUS_PROPERTY("OnSuccessOf", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
868 SD_BUS_PROPERTY("OnFailure", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
869 SD_BUS_PROPERTY("OnFailureOf", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
870 SD_BUS_PROPERTY("Triggers", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
871 SD_BUS_PROPERTY("TriggeredBy", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
872 SD_BUS_PROPERTY("PropagatesReloadTo", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
873 SD_BUS_PROPERTY("ReloadPropagatedFrom", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
874 SD_BUS_PROPERTY("PropagatesStopTo", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
875 SD_BUS_PROPERTY("StopPropagatedFrom", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
876 SD_BUS_PROPERTY("JoinsNamespaceOf", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
877 SD_BUS_PROPERTY("SliceOf", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
878 SD_BUS_PROPERTY("RequiresMountsFor", "as", property_get_mounts_for, offsetof(Unit, mounts_for[UNIT_MOUNT_REQUIRES]), SD_BUS_VTABLE_PROPERTY_CONST),
879 SD_BUS_PROPERTY("WantsMountsFor", "as", property_get_mounts_for, offsetof(Unit, mounts_for[UNIT_MOUNT_WANTS]), SD_BUS_VTABLE_PROPERTY_CONST),
880 SD_BUS_PROPERTY("Documentation", "as", NULL, offsetof(Unit, documentation), SD_BUS_VTABLE_PROPERTY_CONST),
881 SD_BUS_PROPERTY("Description", "s", property_get_description, 0, SD_BUS_VTABLE_PROPERTY_CONST),
882 SD_BUS_PROPERTY("AccessSELinuxContext", "s", NULL, offsetof(Unit, access_selinux_context), SD_BUS_VTABLE_PROPERTY_CONST),
883 SD_BUS_PROPERTY("LoadState", "s", property_get_load_state, offsetof(Unit, load_state), SD_BUS_VTABLE_PROPERTY_CONST),
884 SD_BUS_PROPERTY("ActiveState", "s", property_get_active_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
885 SD_BUS_PROPERTY("FreezerState", "s", property_get_freezer_state, offsetof(Unit, freezer_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
886 SD_BUS_PROPERTY("SubState", "s", property_get_sub_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
887 SD_BUS_PROPERTY("FragmentPath", "s", NULL, offsetof(Unit, fragment_path), SD_BUS_VTABLE_PROPERTY_CONST),
888 SD_BUS_PROPERTY("SourcePath", "s", NULL, offsetof(Unit, source_path), SD_BUS_VTABLE_PROPERTY_CONST),
889 SD_BUS_PROPERTY("DropInPaths", "as", NULL, offsetof(Unit, dropin_paths), SD_BUS_VTABLE_PROPERTY_CONST),
890 SD_BUS_PROPERTY("UnitFileState", "s", property_get_unit_file_state, 0, 0),
891 SD_BUS_PROPERTY("UnitFilePreset", "s", property_get_unit_file_preset, 0, 0),
892 BUS_PROPERTY_DUAL_TIMESTAMP("StateChangeTimestamp", offsetof(Unit, state_change_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
893 BUS_PROPERTY_DUAL_TIMESTAMP("InactiveExitTimestamp", offsetof(Unit, inactive_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
894 BUS_PROPERTY_DUAL_TIMESTAMP("ActiveEnterTimestamp", offsetof(Unit, active_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
895 BUS_PROPERTY_DUAL_TIMESTAMP("ActiveExitTimestamp", offsetof(Unit, active_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
896 BUS_PROPERTY_DUAL_TIMESTAMP("InactiveEnterTimestamp", offsetof(Unit, inactive_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
897 SD_BUS_PROPERTY("CanStart", "b", property_get_can_start, 0, SD_BUS_VTABLE_PROPERTY_CONST),
898 SD_BUS_PROPERTY("CanStop", "b", property_get_can_stop, 0, SD_BUS_VTABLE_PROPERTY_CONST),
899 SD_BUS_PROPERTY("CanReload", "b", property_get_can_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST),
900 SD_BUS_PROPERTY("CanIsolate", "b", property_get_can_isolate, 0, SD_BUS_VTABLE_PROPERTY_CONST),
901 SD_BUS_PROPERTY("CanClean", "as", property_get_can_clean, 0, SD_BUS_VTABLE_PROPERTY_CONST),
902 SD_BUS_PROPERTY("CanFreeze", "b", property_get_can_freeze, 0, SD_BUS_VTABLE_PROPERTY_CONST),
903 SD_BUS_PROPERTY("CanLiveMount", "b", property_get_can_live_mount, 0, SD_BUS_VTABLE_PROPERTY_CONST),
904 SD_BUS_PROPERTY("Job", "(uo)", property_get_job, offsetof(Unit, job), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
905 SD_BUS_PROPERTY("StopWhenUnneeded", "b", bus_property_get_bool, offsetof(Unit, stop_when_unneeded), SD_BUS_VTABLE_PROPERTY_CONST),
906 SD_BUS_PROPERTY("RefuseManualStart", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_start), SD_BUS_VTABLE_PROPERTY_CONST),
907 SD_BUS_PROPERTY("RefuseManualStop", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_stop), SD_BUS_VTABLE_PROPERTY_CONST),
908 SD_BUS_PROPERTY("AllowIsolate", "b", bus_property_get_bool, offsetof(Unit, allow_isolate), SD_BUS_VTABLE_PROPERTY_CONST),
909 SD_BUS_PROPERTY("DefaultDependencies", "b", bus_property_get_bool, offsetof(Unit, default_dependencies), SD_BUS_VTABLE_PROPERTY_CONST),
910 SD_BUS_PROPERTY("SurviveFinalKillSignal", "b", bus_property_get_bool, offsetof(Unit, survive_final_kill_signal), SD_BUS_VTABLE_PROPERTY_CONST),
911 SD_BUS_PROPERTY("OnSuccesJobMode", "s", property_get_job_mode, offsetof(Unit, on_success_job_mode), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), /* deprecated */
912 SD_BUS_PROPERTY("OnSuccessJobMode", "s", property_get_job_mode, offsetof(Unit, on_success_job_mode), SD_BUS_VTABLE_PROPERTY_CONST),
913 SD_BUS_PROPERTY("OnFailureJobMode", "s", property_get_job_mode, offsetof(Unit, on_failure_job_mode), SD_BUS_VTABLE_PROPERTY_CONST),
914 SD_BUS_PROPERTY("IgnoreOnIsolate", "b", bus_property_get_bool, offsetof(Unit, ignore_on_isolate), SD_BUS_VTABLE_PROPERTY_CONST),
915 SD_BUS_PROPERTY("NeedDaemonReload", "b", property_get_need_daemon_reload, 0, 0),
916 SD_BUS_PROPERTY("Markers", "as", property_get_markers, offsetof(Unit, markers), 0),
917 SD_BUS_PROPERTY("JobTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_timeout), SD_BUS_VTABLE_PROPERTY_CONST),
918 SD_BUS_PROPERTY("JobRunningTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_running_timeout), SD_BUS_VTABLE_PROPERTY_CONST),
919 SD_BUS_PROPERTY("JobTimeoutAction", "s", bus_property_get_emergency_action, offsetof(Unit, job_timeout_action), SD_BUS_VTABLE_PROPERTY_CONST),
920 SD_BUS_PROPERTY("JobTimeoutRebootArgument", "s", NULL, offsetof(Unit, job_timeout_reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
921 SD_BUS_PROPERTY("ConditionResult", "b", bus_property_get_bool, offsetof(Unit, condition_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
922 SD_BUS_PROPERTY("AssertResult", "b", bus_property_get_bool, offsetof(Unit, assert_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
923 BUS_PROPERTY_DUAL_TIMESTAMP("ConditionTimestamp", offsetof(Unit, condition_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
924 BUS_PROPERTY_DUAL_TIMESTAMP("AssertTimestamp", offsetof(Unit, assert_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
925 SD_BUS_PROPERTY("Conditions", "a(sbbsi)", property_get_conditions, offsetof(Unit, conditions), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
926 SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
927 SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST),
928 SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST),
929 SD_BUS_PROPERTY("Perpetual", "b", bus_property_get_bool, offsetof(Unit, perpetual), SD_BUS_VTABLE_PROPERTY_CONST),
930 SD_BUS_PROPERTY("StartLimitIntervalUSec", "t", bus_property_get_usec, offsetof(Unit, start_ratelimit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
931 SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_ratelimit.burst), SD_BUS_VTABLE_PROPERTY_CONST),
932 SD_BUS_PROPERTY("StartLimitAction", "s", bus_property_get_emergency_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST),
933 SD_BUS_PROPERTY("FailureAction", "s", bus_property_get_emergency_action, offsetof(Unit, failure_action), SD_BUS_VTABLE_PROPERTY_CONST),
934 SD_BUS_PROPERTY("FailureActionExitStatus", "i", bus_property_get_int, offsetof(Unit, failure_action_exit_status), SD_BUS_VTABLE_PROPERTY_CONST),
935 SD_BUS_PROPERTY("SuccessAction", "s", bus_property_get_emergency_action, offsetof(Unit, success_action), SD_BUS_VTABLE_PROPERTY_CONST),
936 SD_BUS_PROPERTY("SuccessActionExitStatus", "i", bus_property_get_int, offsetof(Unit, success_action_exit_status), SD_BUS_VTABLE_PROPERTY_CONST),
937 SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
938 SD_BUS_PROPERTY("InvocationID", "ay", bus_property_get_id128, offsetof(Unit, invocation_id), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
939 SD_BUS_PROPERTY("CollectMode", "s", property_get_collect_mode, offsetof(Unit, collect_mode), SD_BUS_VTABLE_PROPERTY_CONST),
940 SD_BUS_PROPERTY("Refs", "as", property_get_refs, 0, 0),
941 SD_BUS_PROPERTY("ActivationDetails", "a(ss)", bus_property_get_activation_details, offsetof(Unit, activation_details), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
942 SD_BUS_PROPERTY("DebugInvocation", "b", bus_property_get_bool, offsetof(Unit, debug_invocation), 0),
943
944 SD_BUS_METHOD_WITH_ARGS("Start",
945 SD_BUS_ARGS("s", mode),
946 SD_BUS_RESULT("o", job),
947 bus_unit_method_start,
948 SD_BUS_VTABLE_UNPRIVILEGED),
949 SD_BUS_METHOD_WITH_ARGS("Stop",
950 SD_BUS_ARGS("s", mode),
951 SD_BUS_RESULT("o", job),
952 bus_unit_method_stop,
953 SD_BUS_VTABLE_UNPRIVILEGED),
954 SD_BUS_METHOD_WITH_ARGS("Reload",
955 SD_BUS_ARGS("s", mode),
956 SD_BUS_RESULT("o", job),
957 bus_unit_method_reload,
958 SD_BUS_VTABLE_UNPRIVILEGED),
959 SD_BUS_METHOD_WITH_ARGS("Restart",
960 SD_BUS_ARGS("s", mode),
961 SD_BUS_RESULT("o", job),
962 bus_unit_method_restart,
963 SD_BUS_VTABLE_UNPRIVILEGED),
964 SD_BUS_METHOD_WITH_ARGS("TryRestart",
965 SD_BUS_ARGS("s", mode),
966 SD_BUS_RESULT("o", job),
967 bus_unit_method_try_restart,
968 SD_BUS_VTABLE_UNPRIVILEGED),
969 SD_BUS_METHOD_WITH_ARGS("ReloadOrRestart",
970 SD_BUS_ARGS("s", mode),
971 SD_BUS_RESULT("o", job),
972 bus_unit_method_reload_or_restart,
973 SD_BUS_VTABLE_UNPRIVILEGED),
974 SD_BUS_METHOD_WITH_ARGS("ReloadOrTryRestart",
975 SD_BUS_ARGS("s", mode),
976 SD_BUS_RESULT("o", job),
977 bus_unit_method_reload_or_try_restart,
978 SD_BUS_VTABLE_UNPRIVILEGED),
979 SD_BUS_METHOD_WITH_ARGS("EnqueueJob",
980 SD_BUS_ARGS("s", job_type, "s", job_mode),
981 SD_BUS_RESULT("u", job_id, "o", job_path, "s", unit_id, "o", unit_path, "s", job_type, "a(uosos)", affected_jobs),
982 bus_unit_method_enqueue_job,
983 SD_BUS_VTABLE_UNPRIVILEGED),
984 SD_BUS_METHOD_WITH_ARGS("Kill",
985 SD_BUS_ARGS("s", whom, "i", signal),
986 SD_BUS_NO_RESULT,
987 bus_unit_method_kill,
988 SD_BUS_VTABLE_UNPRIVILEGED),
989 SD_BUS_METHOD_WITH_ARGS("QueueSignal",
990 SD_BUS_ARGS("s", whom, "i", signal, "i", value),
991 SD_BUS_NO_RESULT,
992 bus_unit_method_kill,
993 SD_BUS_VTABLE_UNPRIVILEGED),
994 SD_BUS_METHOD("ResetFailed",
995 NULL,
996 NULL,
997 bus_unit_method_reset_failed,
998 SD_BUS_VTABLE_UNPRIVILEGED),
999 SD_BUS_METHOD_WITH_ARGS("SetProperties",
1000 SD_BUS_ARGS("b", runtime, "a(sv)", properties),
1001 SD_BUS_NO_RESULT,
1002 bus_unit_method_set_properties,
1003 SD_BUS_VTABLE_UNPRIVILEGED),
1004 SD_BUS_METHOD("Ref",
1005 NULL,
1006 NULL,
1007 bus_unit_method_ref,
1008 SD_BUS_VTABLE_UNPRIVILEGED),
1009 SD_BUS_METHOD("Unref",
1010 NULL,
1011 NULL,
1012 bus_unit_method_unref,
1013 SD_BUS_VTABLE_UNPRIVILEGED),
1014 SD_BUS_METHOD_WITH_ARGS("Clean",
1015 SD_BUS_ARGS("as", mask),
1016 SD_BUS_NO_RESULT,
1017 bus_unit_method_clean,
1018 SD_BUS_VTABLE_UNPRIVILEGED),
1019 SD_BUS_METHOD("Freeze",
1020 NULL,
1021 NULL,
1022 bus_unit_method_freeze,
1023 SD_BUS_VTABLE_UNPRIVILEGED),
1024 SD_BUS_METHOD("Thaw",
1025 NULL,
1026 NULL,
1027 bus_unit_method_thaw,
1028 SD_BUS_VTABLE_UNPRIVILEGED),
1029
1030 /* For dependency types we don't support anymore always return an empty array */
1031 SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN),
1032 SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN),
1033 SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN),
1034 SD_BUS_PROPERTY("RequisiteOfOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN),
1035 /* Obsolete alias names */
1036 SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_ratelimit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
1037 SD_BUS_PROPERTY("StartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Unit, start_ratelimit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
1038
1039 SD_BUS_VTABLE_END
1040};
1041
1042static int property_get_slice(
1043 sd_bus *bus,
1044 const char *path,
1045 const char *interface,
1046 const char *property,
1047 sd_bus_message *reply,
1048 void *userdata,
1049 sd_bus_error *error) {
1050
1051 Unit *u = ASSERT_PTR(userdata);
1052
1053 assert(bus);
1054 assert(reply);
1055
1056 return sd_bus_message_append(reply, "s", unit_slice_name(u));
1057}
1058
1059static int property_get_available_memory(
1060 sd_bus *bus,
1061 const char *path,
1062 const char *interface,
1063 const char *property,
1064 sd_bus_message *reply,
1065 void *userdata,
1066 sd_bus_error *error) {
1067
1068 uint64_t sz = UINT64_MAX;
1069 Unit *u = ASSERT_PTR(userdata);
1070 int r;
1071
1072 assert(bus);
1073 assert(reply);
1074
1075 r = unit_get_memory_available(u, &sz);
1076 if (r < 0 && r != -ENODATA)
1077 log_unit_warning_errno(u, r, "Failed to get total available memory from cgroup: %m");
1078
1079 return sd_bus_message_append(reply, "t", sz);
1080}
1081
1082static int property_get_memory_accounting(
1083 sd_bus *bus,
1084 const char *path,
1085 const char *interface,
1086 const char *property,
1087 sd_bus_message *reply,
1088 void *userdata,
1089 sd_bus_error *error) {
1090
1091 Unit *u = ASSERT_PTR(userdata);
1092 CGroupMemoryAccountingMetric metric;
1093 uint64_t sz = UINT64_MAX;
1094
1095 assert(bus);
1096 assert(reply);
1097
1098 assert_se((metric = cgroup_memory_accounting_metric_from_string(property)) >= 0);
1099 (void) unit_get_memory_accounting(u, metric, &sz);
1100 return sd_bus_message_append(reply, "t", sz);
1101}
1102
1103static int property_get_current_tasks(
1104 sd_bus *bus,
1105 const char *path,
1106 const char *interface,
1107 const char *property,
1108 sd_bus_message *reply,
1109 void *userdata,
1110 sd_bus_error *error) {
1111
1112 uint64_t cn = UINT64_MAX;
1113 Unit *u = ASSERT_PTR(userdata);
1114 int r;
1115
1116 assert(bus);
1117 assert(reply);
1118
1119 r = unit_get_tasks_current(u, &cn);
1120 if (r < 0 && r != -ENODATA)
1121 log_unit_warning_errno(u, r, "Failed to get pids.current attribute: %m");
1122
1123 return sd_bus_message_append(reply, "t", cn);
1124}
1125
1126static int property_get_cpu_usage(
1127 sd_bus *bus,
1128 const char *path,
1129 const char *interface,
1130 const char *property,
1131 sd_bus_message *reply,
1132 void *userdata,
1133 sd_bus_error *error) {
1134
1135 nsec_t ns = NSEC_INFINITY;
1136 Unit *u = ASSERT_PTR(userdata);
1137 int r;
1138
1139 assert(bus);
1140 assert(reply);
1141
1142 r = unit_get_cpu_usage(u, &ns);
1143 if (r < 0 && r != -ENODATA)
1144 log_unit_warning_errno(u, r, "Failed to get cpuacct.usage attribute: %m");
1145
1146 return sd_bus_message_append(reply, "t", ns);
1147}
1148
1149static int property_get_cpuset_cpus(
1150 sd_bus *bus,
1151 const char *path,
1152 const char *interface,
1153 const char *property,
1154 sd_bus_message *reply,
1155 void *userdata,
1156 sd_bus_error *error) {
1157
1158 Unit *u = ASSERT_PTR(userdata);
1159 _cleanup_(cpu_set_done) CPUSet cpus = {};
1160 _cleanup_free_ uint8_t *array = NULL;
1161 size_t allocated;
1162
1163 assert(bus);
1164 assert(reply);
1165
1166 (void) unit_get_cpuset(u, &cpus, "cpuset.cpus.effective");
1167 (void) cpu_set_to_dbus(&cpus, &array, &allocated);
1168 return sd_bus_message_append_array(reply, 'y', array, allocated);
1169}
1170
1171static int property_get_cpuset_mems(
1172 sd_bus *bus,
1173 const char *path,
1174 const char *interface,
1175 const char *property,
1176 sd_bus_message *reply,
1177 void *userdata,
1178 sd_bus_error *error) {
1179
1180 Unit *u = ASSERT_PTR(userdata);
1181 _cleanup_(cpu_set_done) CPUSet mems = {};
1182 _cleanup_free_ uint8_t *array = NULL;
1183 size_t allocated;
1184
1185 assert(bus);
1186 assert(reply);
1187
1188 (void) unit_get_cpuset(u, &mems, "cpuset.mems.effective");
1189 (void) cpu_set_to_dbus(&mems, &array, &allocated);
1190 return sd_bus_message_append_array(reply, 'y', array, allocated);
1191}
1192
1193static int property_get_cgroup(
1194 sd_bus *bus,
1195 const char *path,
1196 const char *interface,
1197 const char *property,
1198 sd_bus_message *reply,
1199 void *userdata,
1200 sd_bus_error *error) {
1201
1202 Unit *u = ASSERT_PTR(userdata);
1203 const char *t = NULL;
1204
1205 assert(bus);
1206 assert(reply);
1207
1208 /* Three cases: a) u->cgroup_path is NULL, in which case the
1209 * unit has no control group, which we report as the empty
1210 * string. b) u->cgroup_path is the empty string, which
1211 * indicates the root cgroup, which we report as "/". c) all
1212 * other cases we report as-is. */
1213
1214 CGroupRuntime *crt = unit_get_cgroup_runtime(u);
1215
1216 if (crt && crt->cgroup_path)
1217 t = empty_to_root(crt->cgroup_path);
1218
1219 return sd_bus_message_append(reply, "s", t);
1220}
1221
1222static int property_get_cgroup_id(
1223 sd_bus *bus,
1224 const char *path,
1225 const char *interface,
1226 const char *property,
1227 sd_bus_message *reply,
1228 void *userdata,
1229 sd_bus_error *error) {
1230
1231 Unit *u = ASSERT_PTR(userdata);
1232
1233 assert(bus);
1234 assert(reply);
1235
1236 CGroupRuntime *crt = unit_get_cgroup_runtime(u);
1237 return sd_bus_message_append(reply, "t", crt ? crt->cgroup_id : UINT64_C(0));
1238}
1239
1240static int append_process(sd_bus_message *reply, const char *p, PidRef *pid, Set *pids) {
1241 _cleanup_free_ char *buf = NULL, *cmdline = NULL;
1242 int r;
1243
1244 assert(reply);
1245 assert(pidref_is_set(pid));
1246
1247 r = set_put(pids, PID_TO_PTR(pid->pid));
1248 if (IN_SET(r, 0, -EEXIST))
1249 return 0;
1250 if (r < 0)
1251 return r;
1252
1253 if (!p) {
1254 r = cg_pidref_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &buf);
1255 if (r == -ESRCH)
1256 return 0;
1257 if (r < 0)
1258 return r;
1259
1260 p = buf;
1261 }
1262
1263 (void) pidref_get_cmdline(
1264 pid,
1265 SIZE_MAX,
1266 PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_QUOTE,
1267 &cmdline);
1268
1269 return sd_bus_message_append(reply,
1270 "(sus)",
1271 p,
1272 (uint32_t) pid->pid,
1273 cmdline);
1274}
1275
1276static int append_cgroup(sd_bus_message *reply, const char *p, Set *pids) {
1277 _cleanup_closedir_ DIR *d = NULL;
1278 _cleanup_fclose_ FILE *f = NULL;
1279 int r;
1280
1281 assert(reply);
1282 assert(p);
1283
1284 r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, p, &f);
1285 if (r == -ENOENT)
1286 return 0;
1287 if (r < 0)
1288 return r;
1289
1290 for (;;) {
1291 _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
1292
1293 /* libvirt / qemu uses threaded mode and cgroup.procs cannot be read at the lower levels.
1294 * From https://docs.kernel.org/admin-guide/cgroup-v2.html#threads, “cgroup.procs” in a
1295 * threaded domain cgroup contains the PIDs of all processes in the subtree and is not
1296 * readable in the subtree proper. */
1297
1298 r = cg_read_pidref(f, &pidref, /* flags = */ 0);
1299 if (IN_SET(r, 0, -EOPNOTSUPP))
1300 break;
1301 if (r < 0)
1302 return r;
1303
1304 r = pidref_is_kernel_thread(&pidref);
1305 if (r == -ESRCH) /* gone by now */
1306 continue;
1307 if (r < 0)
1308 log_debug_errno(r, "Failed to determine if " PID_FMT " is a kernel thread, assuming not: %m", pidref.pid);
1309 if (r > 0)
1310 continue;
1311
1312 r = append_process(reply, p, &pidref, pids);
1313 if (r < 0)
1314 return r;
1315 }
1316
1317 r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, p, &d);
1318 if (r == -ENOENT)
1319 return 0;
1320 if (r < 0)
1321 return r;
1322
1323 for (;;) {
1324 _cleanup_free_ char *g = NULL, *j = NULL;
1325
1326 r = cg_read_subgroup(d, &g);
1327 if (r < 0)
1328 return r;
1329 if (r == 0)
1330 break;
1331
1332 j = path_join(empty_to_root(p), g);
1333 if (!j)
1334 return -ENOMEM;
1335
1336 r = append_cgroup(reply, j, pids);
1337 if (r < 0)
1338 return r;
1339 }
1340
1341 return 0;
1342}
1343
1344int bus_unit_method_get_processes(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1345 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1346 _cleanup_set_free_ Set *pids = NULL;
1347 Unit *u = userdata;
1348 int r;
1349
1350 assert(message);
1351
1352 r = mac_selinux_unit_access_check(u, message, "status", error);
1353 if (r < 0)
1354 return r;
1355
1356 pids = set_new(NULL);
1357 if (!pids)
1358 return -ENOMEM;
1359
1360 r = sd_bus_message_new_method_return(message, &reply);
1361 if (r < 0)
1362 return r;
1363
1364 r = sd_bus_message_open_container(reply, 'a', "(sus)");
1365 if (r < 0)
1366 return r;
1367
1368 CGroupRuntime *crt = unit_get_cgroup_runtime(u);
1369 if (crt && crt->cgroup_path) {
1370 r = append_cgroup(reply, crt->cgroup_path, pids);
1371 if (r < 0)
1372 return r;
1373 }
1374
1375 /* The main and control pids might live outside of the cgroup, hence fetch them separately */
1376 PidRef *pid = unit_main_pid(u);
1377 if (pidref_is_set(pid)) {
1378 r = append_process(reply, NULL, pid, pids);
1379 if (r < 0)
1380 return r;
1381 }
1382
1383 pid = unit_control_pid(u);
1384 if (pidref_is_set(pid)) {
1385 r = append_process(reply, NULL, pid, pids);
1386 if (r < 0)
1387 return r;
1388 }
1389
1390 r = sd_bus_message_close_container(reply);
1391 if (r < 0)
1392 return r;
1393
1394 return sd_bus_message_send(reply);
1395}
1396
1397static int property_get_ip_counter(
1398 sd_bus *bus,
1399 const char *path,
1400 const char *interface,
1401 const char *property,
1402 sd_bus_message *reply,
1403 void *userdata,
1404 sd_bus_error *error) {
1405
1406 uint64_t value = UINT64_MAX;
1407 Unit *u = ASSERT_PTR(userdata);
1408 CGroupIPAccountingMetric metric;
1409
1410 assert(bus);
1411 assert(reply);
1412 assert(property);
1413
1414 assert_se((metric = cgroup_ip_accounting_metric_from_string(property)) >= 0);
1415 (void) unit_get_ip_accounting(u, metric, &value);
1416 return sd_bus_message_append(reply, "t", value);
1417}
1418
1419static int property_get_io_counter(
1420 sd_bus *bus,
1421 const char *path,
1422 const char *interface,
1423 const char *property,
1424 sd_bus_message *reply,
1425 void *userdata,
1426 sd_bus_error *error) {
1427
1428 uint64_t value = UINT64_MAX;
1429 Unit *u = ASSERT_PTR(userdata);
1430 ssize_t metric;
1431
1432 assert(bus);
1433 assert(reply);
1434 assert(property);
1435
1436 assert_se((metric = cgroup_io_accounting_metric_from_string(property)) >= 0);
1437 (void) unit_get_io_accounting(u, metric, &value);
1438 return sd_bus_message_append(reply, "t", value);
1439}
1440
1441static int property_get_effective_limit(
1442 sd_bus *bus,
1443 const char *path,
1444 const char *interface,
1445 const char *property,
1446 sd_bus_message *reply,
1447 void *userdata,
1448 sd_bus_error *error) {
1449
1450 uint64_t value = CGROUP_LIMIT_MAX;
1451 Unit *u = ASSERT_PTR(userdata);
1452 ssize_t type;
1453
1454 assert(bus);
1455 assert(reply);
1456 assert(property);
1457
1458 assert_se((type = cgroup_effective_limit_type_from_string(property)) >= 0);
1459 (void) unit_get_effective_limit(u, type, &value);
1460 return sd_bus_message_append(reply, "t", value);
1461}
1462
1463int bus_unit_method_attach_processes(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1464 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
1465 _cleanup_set_free_ Set *pids = NULL;
1466 Unit *u = userdata;
1467 const char *path;
1468 int r;
1469
1470 assert(message);
1471
1472 /* This migrates the processes with the specified PIDs into the cgroup of this unit, optionally below a
1473 * specified cgroup path. Obviously this only works for units that actually maintain a cgroup
1474 * representation. If a process is already in the cgroup no operation is executed – in this case the specified
1475 * subcgroup path has no effect! */
1476
1477 r = mac_selinux_unit_access_check(u, message, "start", error);
1478 if (r < 0)
1479 return r;
1480
1481 r = sd_bus_message_read(message, "s", &path);
1482 if (r < 0)
1483 return r;
1484
1485 path = empty_to_null(path);
1486 if (path) {
1487 if (!path_is_absolute(path))
1488 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Control group path is not absolute: %s", path);
1489
1490 if (!path_is_normalized(path))
1491 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Control group path is not normalized: %s", path);
1492 }
1493
1494 if (!unit_cgroup_delegate(u))
1495 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Process migration not available on non-delegated units.");
1496
1497 if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(u)))
1498 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Unit is not active, refusing.");
1499
1500 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_PIDFD, &creds);
1501 if (r < 0)
1502 return r;
1503
1504 r = sd_bus_message_enter_container(message, 'a', "u");
1505 if (r < 0)
1506 return r;
1507 for (;;) {
1508 _cleanup_(pidref_freep) PidRef *pidref = NULL;
1509 uid_t sender_uid;
1510 uint32_t upid;
1511
1512 r = sd_bus_message_read(message, "u", &upid);
1513 if (r < 0)
1514 return r;
1515 if (r == 0)
1516 break;
1517
1518 if (upid == 0) {
1519 _cleanup_(pidref_done) PidRef p = PIDREF_NULL;
1520 r = bus_creds_get_pidref(creds, &p);
1521 if (r < 0)
1522 return r;
1523
1524 r = pidref_dup(&p, &pidref);
1525 } else
1526 r = pidref_new_from_pid(upid, &pidref);
1527 if (r < 0)
1528 return r;
1529
1530 /* Filter out duplicates */
1531 if (set_contains(pids, pidref))
1532 continue;
1533
1534 /* Check if this process is suitable for attaching to this unit */
1535 r = unit_pid_attachable(u, pidref, error);
1536 if (r < 0)
1537 return r;
1538
1539 /* Let's query the sender's UID, so that we can make our security decisions */
1540 r = sd_bus_creds_get_euid(creds, &sender_uid);
1541 if (r < 0)
1542 return r;
1543
1544 /* Let's validate security: if the sender is root or the owner of the service manager, then
1545 * all is OK. If the sender is any other user, then the process in question must be owned by
1546 * both the sender and the target unit's UID. Note that ownership here means either direct
1547 * ownership, or indirect via a userns that is owned by the right UID. */
1548 if (sender_uid != 0 && sender_uid != getuid()) {
1549 r = process_is_owned_by_uid(pidref, sender_uid);
1550 if (r < 0)
1551 return sd_bus_error_set_errnof(error, r, "Failed to check if process " PID_FMT " is owned by client's UID: %m", pidref->pid);
1552 if (r == 0)
1553 return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Process " PID_FMT " not owned by client's UID. Refusing.", pidref->pid);
1554
1555 r = process_is_owned_by_uid(pidref, u->ref_uid);
1556 if (r < 0)
1557 return sd_bus_error_set_errnof(error, r, "Failed to check if process " PID_FMT " is owned by target unit's UID: %m", pidref->pid);
1558 if (r == 0)
1559 return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Process " PID_FMT " not owned by target unit's UID. Refusing.", pidref->pid);
1560 }
1561
1562 r = set_ensure_consume(&pids, &pidref_hash_ops_free, TAKE_PTR(pidref));
1563 if (r < 0)
1564 return r;
1565 }
1566
1567 r = sd_bus_message_exit_container(message);
1568 if (r < 0)
1569 return r;
1570
1571 r = unit_attach_pids_to_cgroup(u, pids, path);
1572 if (r < 0)
1573 return sd_bus_error_set_errnof(error, r, "Failed to attach processes to control group: %m");
1574
1575 return sd_bus_reply_method_return(message, NULL);
1576}
1577
1578int bus_unit_method_remove_subgroup(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1579 Unit *u = ASSERT_PTR(userdata);
1580 int r;
1581
1582 assert(message);
1583
1584 /* This removes a subcgroup of the unit, regardless which user owns the subcgroup. This is useful
1585 * when cgroup delegation is enabled for a unit, and the unit subdelegates the cgroup further */
1586
1587 r = mac_selinux_unit_access_check(u, message, "stop", error);
1588 if (r < 0)
1589 return r;
1590
1591 const char *path;
1592 uint64_t flags;
1593 r = sd_bus_message_read(message, "st", &path, &flags);
1594 if (r < 0)
1595 return r;
1596
1597 /* No flags defined for now. */
1598 if (flags != 0)
1599 return sd_bus_reply_method_errorf(message, SD_BUS_ERROR_INVALID_ARGS, "Invalid 'flags' parameter '%" PRIu64 "'", flags);
1600
1601 if (!unit_cgroup_delegate(u))
1602 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Subcgroup removal not available on non-delegated units.");
1603
1604 if (!path_is_absolute(path))
1605 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Control group path is not absolute: %s", path);
1606
1607 if (!path_is_normalized(path))
1608 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Control group path is not normalized: %s", path);
1609
1610 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
1611 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1612 if (r < 0)
1613 return r;
1614
1615 uid_t sender_uid;
1616 r = sd_bus_creds_get_euid(creds, &sender_uid);
1617 if (r < 0)
1618 return r;
1619
1620 /* Allow this only if the client is privileged, is us, or is the user of the unit itself. */
1621 if (sender_uid != 0 && sender_uid != getuid() && sender_uid != u->ref_uid)
1622 return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Client is not permitted to alter cgroup.");
1623
1624 r = unit_remove_subcgroup(u, path);
1625 if (r < 0)
1626 return sd_bus_error_set_errnof(error, r, "Failed to remove subgroup %s: %m", path);
1627
1628 return sd_bus_reply_method_return(message, NULL);
1629}
1630
1631const sd_bus_vtable bus_unit_cgroup_vtable[] = {
1632 SD_BUS_VTABLE_START(0),
1633 SD_BUS_PROPERTY("Slice", "s", property_get_slice, 0, 0),
1634 SD_BUS_PROPERTY("ControlGroup", "s", property_get_cgroup, 0, 0),
1635 SD_BUS_PROPERTY("ControlGroupId", "t", property_get_cgroup_id, 0, 0),
1636 SD_BUS_PROPERTY("MemoryCurrent", "t", property_get_memory_accounting, 0, 0),
1637 SD_BUS_PROPERTY("MemoryPeak", "t", property_get_memory_accounting, 0, 0),
1638 SD_BUS_PROPERTY("MemorySwapCurrent", "t", property_get_memory_accounting, 0, 0),
1639 SD_BUS_PROPERTY("MemorySwapPeak", "t", property_get_memory_accounting, 0, 0),
1640 SD_BUS_PROPERTY("MemoryZSwapCurrent", "t", property_get_memory_accounting, 0, 0),
1641 SD_BUS_PROPERTY("MemoryAvailable", "t", property_get_available_memory, 0, 0),
1642 SD_BUS_PROPERTY("EffectiveMemoryMax", "t", property_get_effective_limit, 0, 0),
1643 SD_BUS_PROPERTY("EffectiveMemoryHigh", "t", property_get_effective_limit, 0, 0),
1644 SD_BUS_PROPERTY("CPUUsageNSec", "t", property_get_cpu_usage, 0, 0),
1645 SD_BUS_PROPERTY("EffectiveCPUs", "ay", property_get_cpuset_cpus, 0, 0),
1646 SD_BUS_PROPERTY("EffectiveMemoryNodes", "ay", property_get_cpuset_mems, 0, 0),
1647 SD_BUS_PROPERTY("TasksCurrent", "t", property_get_current_tasks, 0, 0),
1648 SD_BUS_PROPERTY("EffectiveTasksMax", "t", property_get_effective_limit, 0, 0),
1649 SD_BUS_PROPERTY("IPIngressBytes", "t", property_get_ip_counter, 0, 0),
1650 SD_BUS_PROPERTY("IPIngressPackets", "t", property_get_ip_counter, 0, 0),
1651 SD_BUS_PROPERTY("IPEgressBytes", "t", property_get_ip_counter, 0, 0),
1652 SD_BUS_PROPERTY("IPEgressPackets", "t", property_get_ip_counter, 0, 0),
1653 SD_BUS_PROPERTY("IOReadBytes", "t", property_get_io_counter, 0, 0),
1654 SD_BUS_PROPERTY("IOReadOperations", "t", property_get_io_counter, 0, 0),
1655 SD_BUS_PROPERTY("IOWriteBytes", "t", property_get_io_counter, 0, 0),
1656 SD_BUS_PROPERTY("IOWriteOperations", "t", property_get_io_counter, 0, 0),
1657
1658 SD_BUS_METHOD_WITH_ARGS("GetProcesses",
1659 SD_BUS_NO_ARGS,
1660 SD_BUS_ARGS("a(sus)", processes),
1661 bus_unit_method_get_processes,
1662 SD_BUS_VTABLE_UNPRIVILEGED),
1663
1664 SD_BUS_METHOD_WITH_ARGS("AttachProcesses",
1665 SD_BUS_ARGS("s", subcgroup, "au", pids),
1666 SD_BUS_NO_RESULT,
1667 bus_unit_method_attach_processes,
1668 SD_BUS_VTABLE_UNPRIVILEGED),
1669
1670 SD_BUS_METHOD_WITH_ARGS("RemoveSubgroup",
1671 SD_BUS_ARGS("s", subcgroup, "t", flags),
1672 SD_BUS_NO_RESULT,
1673 bus_unit_method_remove_subgroup,
1674 SD_BUS_VTABLE_UNPRIVILEGED),
1675
1676 SD_BUS_VTABLE_END
1677};
1678
1679static int send_new_signal(sd_bus *bus, void *userdata) {
1680 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1681 _cleanup_free_ char *p = NULL;
1682 Unit *u = ASSERT_PTR(userdata);
1683 int r;
1684
1685 assert(bus);
1686
1687 p = unit_dbus_path(u);
1688 if (!p)
1689 return -ENOMEM;
1690
1691 r = sd_bus_message_new_signal(
1692 bus,
1693 &m,
1694 "/org/freedesktop/systemd1",
1695 "org.freedesktop.systemd1.Manager",
1696 "UnitNew");
1697 if (r < 0)
1698 return r;
1699
1700 r = sd_bus_message_append(m, "so", u->id, p);
1701 if (r < 0)
1702 return r;
1703
1704 return sd_bus_send(bus, m, NULL);
1705}
1706
1707static int send_changed_signal(sd_bus *bus, void *userdata) {
1708 _cleanup_free_ char *p = NULL;
1709 Unit *u = ASSERT_PTR(userdata);
1710 int r;
1711
1712 assert(bus);
1713
1714 p = unit_dbus_path(u);
1715 if (!p)
1716 return -ENOMEM;
1717
1718 /* Send a properties changed signal. First for the specific
1719 * type, then for the generic unit. The clients may rely on
1720 * this order to get atomic behavior if needed. */
1721
1722 r = sd_bus_emit_properties_changed_strv(
1723 bus, p,
1724 unit_dbus_interface_from_type(u->type),
1725 NULL);
1726 if (r < 0)
1727 return r;
1728
1729 return sd_bus_emit_properties_changed_strv(
1730 bus, p,
1731 "org.freedesktop.systemd1.Unit",
1732 NULL);
1733}
1734
1735void bus_unit_send_change_signal(Unit *u) {
1736 int r;
1737 assert(u);
1738
1739 if (u->in_dbus_queue) {
1740 LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u);
1741 u->in_dbus_queue = false;
1742
1743 /* The unit might be good to be GC once its pending signals have been sent */
1744 unit_add_to_gc_queue(u);
1745 }
1746
1747 if (!u->id)
1748 return;
1749
1750 r = bus_foreach_bus(u->manager, u->bus_track, u->sent_dbus_new_signal ? send_changed_signal : send_new_signal, u);
1751 if (r < 0)
1752 log_unit_debug_errno(u, r, "Failed to send unit change signal for %s: %m", u->id);
1753
1754 u->sent_dbus_new_signal = true;
1755}
1756
1757void bus_unit_send_pending_change_signal(Unit *u, bool including_new) {
1758
1759 /* Sends out any pending change signals, but only if they really are pending. This call is used when we are
1760 * about to change state in order to force out a PropertiesChanged signal beforehand if there was one pending
1761 * so that clients can follow the full state transition */
1762
1763 if (!u->in_dbus_queue) /* If not enqueued, don't bother */
1764 return;
1765
1766 if (!u->sent_dbus_new_signal && !including_new) /* If the unit was never announced, don't bother, it's fine if
1767 * the unit appears in the new state right-away (except if the
1768 * caller explicitly asked us to send it anyway) */
1769 return;
1770
1771 if (MANAGER_IS_RELOADING(u->manager)) /* Don't generate unnecessary PropertiesChanged signals for the same unit
1772 * when we are reloading. */
1773 return;
1774
1775 bus_unit_send_change_signal(u);
1776}
1777
1778int bus_unit_send_pending_freezer_message(Unit *u, bool canceled) {
1779 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1780 int r;
1781
1782 assert(u);
1783
1784 if (!u->pending_freezer_invocation)
1785 return 0;
1786
1787 if (canceled)
1788 r = sd_bus_message_new_method_error(
1789 u->pending_freezer_invocation,
1790 &reply,
1791 &SD_BUS_ERROR_MAKE_CONST(
1792 BUS_ERROR_FREEZE_CANCELLED, "Freeze operation aborted"));
1793 else
1794 r = sd_bus_message_new_method_return(u->pending_freezer_invocation, &reply);
1795 if (r < 0)
1796 return r;
1797
1798 r = sd_bus_message_send(reply);
1799 if (r < 0)
1800 log_warning_errno(r, "Failed to send queued message, ignoring: %m");
1801
1802 u->pending_freezer_invocation = sd_bus_message_unref(u->pending_freezer_invocation);
1803
1804 return 0;
1805}
1806
1807static int send_removed_signal(sd_bus *bus, void *userdata) {
1808 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1809 _cleanup_free_ char *p = NULL;
1810 Unit *u = ASSERT_PTR(userdata);
1811 int r;
1812
1813 assert(bus);
1814
1815 p = unit_dbus_path(u);
1816 if (!p)
1817 return -ENOMEM;
1818
1819 r = sd_bus_message_new_signal(
1820 bus,
1821 &m,
1822 "/org/freedesktop/systemd1",
1823 "org.freedesktop.systemd1.Manager",
1824 "UnitRemoved");
1825 if (r < 0)
1826 return r;
1827
1828 r = sd_bus_message_append(m, "so", u->id, p);
1829 if (r < 0)
1830 return r;
1831
1832 return sd_bus_send(bus, m, NULL);
1833}
1834
1835void bus_unit_send_removed_signal(Unit *u) {
1836 int r;
1837 assert(u);
1838
1839 if (!u->sent_dbus_new_signal || u->in_dbus_queue)
1840 bus_unit_send_change_signal(u);
1841
1842 if (!u->id)
1843 return;
1844
1845 r = bus_foreach_bus(u->manager, u->bus_track, send_removed_signal, u);
1846 if (r < 0)
1847 log_unit_debug_errno(u, r, "Failed to send unit remove signal for %s: %m", u->id);
1848}
1849
1850int bus_unit_queue_job_one(
1851 sd_bus_message *message,
1852 Unit *u,
1853 JobType type,
1854 JobMode mode,
1855 BusUnitQueueFlags flags,
1856 sd_bus_message *reply,
1857 sd_bus_error *error) {
1858
1859 _cleanup_set_free_ Set *affected = NULL;
1860 _cleanup_free_ char *job_path = NULL, *unit_path = NULL;
1861 Job *j, *a;
1862 int r;
1863
1864 if (FLAGS_SET(flags, BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE) && unit_can_reload(u)) {
1865 if (type == JOB_RESTART)
1866 type = JOB_RELOAD_OR_START;
1867 else if (type == JOB_TRY_RESTART)
1868 type = JOB_TRY_RELOAD;
1869 }
1870
1871 if (type == JOB_STOP && UNIT_IS_LOAD_ERROR(u->load_state) && unit_active_state(u) == UNIT_INACTIVE)
1872 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id);
1873
1874 if ((type == JOB_START && u->refuse_manual_start) ||
1875 (type == JOB_STOP && u->refuse_manual_stop) ||
1876 (IN_SET(type, JOB_RESTART, JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop)) ||
1877 (type == JOB_RELOAD_OR_START && job_type_collapse(type, u) == JOB_START && u->refuse_manual_start))
1878 return sd_bus_error_setf(error,
1879 BUS_ERROR_ONLY_BY_DEPENDENCY,
1880 "Operation refused, unit %s may be requested by dependency only (it is configured to refuse manual start/stop).",
1881 u->id);
1882
1883 /* dbus-broker issues StartUnit for activation requests, and Type=dbus services automatically
1884 * gain dependency on dbus.socket. Therefore, if dbus has a pending stop job, the new start
1885 * job that pulls in dbus again would cause job type conflict. Let's avoid that by rejecting
1886 * job enqueuing early.
1887 *
1888 * Note that unlike signal_activation_request(), we can't use unit_inactive_or_pending()
1889 * here. StartUnit is a more generic interface, and thus users are allowed to use e.g. systemctl
1890 * to start Type=dbus services even when dbus is inactive. */
1891 if (type == JOB_START && u->type == UNIT_SERVICE && SERVICE(u)->type == SERVICE_DBUS)
1892 FOREACH_STRING(dbus_unit, SPECIAL_DBUS_SOCKET, SPECIAL_DBUS_SERVICE) {
1893 Unit *dbus;
1894
1895 dbus = manager_get_unit(u->manager, dbus_unit);
1896 if (dbus && unit_stop_pending(dbus))
1897 return sd_bus_error_setf(error,
1898 BUS_ERROR_SHUTTING_DOWN,
1899 "Operation for unit %s refused, D-Bus is shutting down.",
1900 u->id);
1901 }
1902
1903 if (FLAGS_SET(flags, BUS_UNIT_QUEUE_VERBOSE_REPLY)) {
1904 affected = set_new(NULL);
1905 if (!affected)
1906 return -ENOMEM;
1907 }
1908
1909 r = manager_add_job_full(u->manager, type, u, mode, /* extra_flags = */ 0, affected, error, &j);
1910 if (r < 0)
1911 return r;
1912
1913 r = bus_job_track_sender(j, message);
1914 if (r < 0)
1915 return r;
1916
1917 /* Before we send the method reply, force out the announcement JobNew for this job */
1918 bus_job_send_pending_change_signal(j, true);
1919
1920 job_path = job_dbus_path(j);
1921 if (!job_path)
1922 return -ENOMEM;
1923
1924 /* The classic response is just a job object path */
1925 if (!FLAGS_SET(flags, BUS_UNIT_QUEUE_VERBOSE_REPLY))
1926 return sd_bus_message_append(reply, "o", job_path);
1927
1928 /* In verbose mode respond with the anchor job plus everything that has been affected */
1929
1930 unit_path = unit_dbus_path(j->unit);
1931 if (!unit_path)
1932 return -ENOMEM;
1933
1934 r = sd_bus_message_append(reply, "uosos",
1935 j->id, job_path,
1936 j->unit->id, unit_path,
1937 job_type_to_string(j->type));
1938 if (r < 0)
1939 return r;
1940
1941 r = sd_bus_message_open_container(reply, 'a', "(uosos)");
1942 if (r < 0)
1943 return r;
1944
1945 SET_FOREACH(a, affected) {
1946 if (a->id == j->id)
1947 continue;
1948
1949 /* Free paths from previous iteration */
1950 job_path = mfree(job_path);
1951 unit_path = mfree(unit_path);
1952
1953 job_path = job_dbus_path(a);
1954 if (!job_path)
1955 return -ENOMEM;
1956
1957 unit_path = unit_dbus_path(a->unit);
1958 if (!unit_path)
1959 return -ENOMEM;
1960
1961 r = sd_bus_message_append(reply, "(uosos)",
1962 a->id, job_path,
1963 a->unit->id, unit_path,
1964 job_type_to_string(a->type));
1965 if (r < 0)
1966 return r;
1967 }
1968
1969 return sd_bus_message_close_container(reply);
1970}
1971
1972int bus_unit_queue_job(
1973 sd_bus_message *message,
1974 Unit *u,
1975 JobType type,
1976 JobMode mode,
1977 BusUnitQueueFlags flags,
1978 sd_bus_error *error) {
1979
1980 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1981 int r;
1982
1983 assert(message);
1984 assert(u);
1985 assert(type >= 0 && type < _JOB_TYPE_MAX);
1986 assert(mode >= 0 && mode < _JOB_MODE_MAX);
1987
1988 r = mac_selinux_unit_access_check(
1989 u, message,
1990 job_type_to_access_method(type),
1991 error);
1992 if (r < 0)
1993 return r;
1994
1995 r = sd_bus_message_new_method_return(message, &reply);
1996 if (r < 0)
1997 return r;
1998
1999 r = bus_unit_queue_job_one(message, u, type, mode, flags, reply, error);
2000 if (r < 0)
2001 return r;
2002
2003 return sd_bus_message_send(reply);
2004}
2005
2006static int bus_unit_set_live_property(
2007 Unit *u,
2008 const char *name,
2009 sd_bus_message *message,
2010 UnitWriteFlags flags,
2011 sd_bus_error *error) {
2012
2013 int r;
2014
2015 assert(u);
2016 assert(name);
2017 assert(message);
2018
2019 /* Handles setting properties both "live" (i.e. at any time during runtime), and during creation (for
2020 * transient units that are being created). */
2021
2022 if (streq(name, "Description")) {
2023 const char *d;
2024
2025 r = sd_bus_message_read(message, "s", &d);
2026 if (r < 0)
2027 return r;
2028
2029 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2030 r = unit_set_description(u, d);
2031 if (r < 0)
2032 return r;
2033
2034 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "Description=%s", d);
2035 }
2036
2037 return 1;
2038 }
2039
2040 /* A setting that only applies to active units. We don't actually write this to /run, this state is
2041 * managed internally. "+foo" sets flag foo, "-foo" unsets flag foo, just "foo" resets flags to
2042 * foo. The last type cannot be mixed with "+" or "-". */
2043
2044 if (streq(name, "Markers")) {
2045 unsigned settings = 0, mask = 0;
2046 bool some_plus_minus = false, some_absolute = false;
2047
2048 r = sd_bus_message_enter_container(message, 'a', "s");
2049 if (r < 0)
2050 return r;
2051
2052 for (;;) {
2053 const char *word;
2054 bool b;
2055
2056 r = sd_bus_message_read(message, "s", &word);
2057 if (r < 0)
2058 return r;
2059 if (r == 0)
2060 break;
2061
2062 if (IN_SET(word[0], '+', '-')) {
2063 b = word[0] == '+';
2064 word++;
2065 some_plus_minus = true;
2066 } else {
2067 b = true;
2068 some_absolute = true;
2069 }
2070
2071 UnitMarker m = unit_marker_from_string(word);
2072 if (m < 0)
2073 return sd_bus_error_setf(error, BUS_ERROR_BAD_UNIT_SETTING,
2074 "Unknown marker \"%s\".", word);
2075
2076 SET_FLAG(settings, 1u << m, b);
2077 SET_FLAG(mask, 1u << m, true);
2078 }
2079
2080 r = sd_bus_message_exit_container(message);
2081 if (r < 0)
2082 return r;
2083
2084 if (some_plus_minus && some_absolute)
2085 return sd_bus_error_set(error, BUS_ERROR_BAD_UNIT_SETTING, "Bad marker syntax.");
2086
2087 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2088 if (some_absolute)
2089 u->markers = settings;
2090 else
2091 u->markers = settings | (u->markers & ~mask);
2092 }
2093
2094 return 1;
2095 }
2096
2097 return 0;
2098}
2099
2100static int bus_set_transient_emergency_action(
2101 Unit *u,
2102 const char *name,
2103 EmergencyAction *p,
2104 sd_bus_message *message,
2105 UnitWriteFlags flags,
2106 sd_bus_error *error) {
2107
2108 const char *s;
2109 EmergencyAction v;
2110 int r;
2111
2112 assert(p);
2113
2114 r = sd_bus_message_read(message, "s", &s);
2115 if (r < 0)
2116 return r;
2117
2118 r = parse_emergency_action(s, u->manager->runtime_scope, &v);
2119 if (r < 0)
2120 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
2121 r == -EOPNOTSUPP ? "%s setting invalid for manager type: %s"
2122 : "Invalid %s setting: %s",
2123 name, s);
2124
2125 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2126 *p = v;
2127 unit_write_settingf(u, flags, name,
2128 "%s=%s", name, s);
2129 }
2130
2131 return 1;
2132}
2133
2134static int bus_set_transient_exit_status(
2135 Unit *u,
2136 const char *name,
2137 int *p,
2138 sd_bus_message *message,
2139 UnitWriteFlags flags,
2140 sd_bus_error *error) {
2141
2142 int32_t k;
2143 int r;
2144
2145 assert(p);
2146
2147 r = sd_bus_message_read(message, "i", &k);
2148 if (r < 0)
2149 return r;
2150
2151 if (k > 255)
2152 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Exit status must be in range 0…255 or negative.");
2153
2154 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2155 *p = k < 0 ? -1 : k;
2156
2157 if (k < 0)
2158 unit_write_settingf(u, flags, name, "%s=", name);
2159 else
2160 unit_write_settingf(u, flags, name, "%s=%i", name, k);
2161 }
2162
2163 return 1;
2164}
2165
2166static BUS_DEFINE_SET_TRANSIENT_PARSE(collect_mode, CollectMode, collect_mode_from_string);
2167static BUS_DEFINE_SET_TRANSIENT_PARSE(job_mode, JobMode, job_mode_from_string);
2168
2169static int bus_set_transient_conditions(
2170 Unit *u,
2171 const char *name,
2172 Condition **list,
2173 bool is_condition,
2174 sd_bus_message *message,
2175 UnitWriteFlags flags,
2176 sd_bus_error *error) {
2177
2178 const char *type_name, *param;
2179 int trigger, negate, r;
2180 bool empty = true;
2181
2182 assert(list);
2183
2184 r = sd_bus_message_enter_container(message, 'a', "(sbbs)");
2185 if (r < 0)
2186 return r;
2187
2188 while ((r = sd_bus_message_read(message, "(sbbs)", &type_name, &trigger, &negate, &param)) > 0) {
2189 ConditionType t;
2190
2191 t = is_condition ? condition_type_from_string(type_name) : assert_type_from_string(type_name);
2192 if (t < 0)
2193 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid condition type: %s", type_name);
2194
2195 if (isempty(param))
2196 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Condition parameter in %s is empty", type_name);
2197
2198 if (condition_takes_path(t) && !path_is_absolute(param))
2199 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path in condition %s is not absolute: %s", type_name, param);
2200
2201 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2202 Condition *c;
2203
2204 c = condition_new(t, param, trigger, negate);
2205 if (!c)
2206 return -ENOMEM;
2207
2208 LIST_PREPEND(conditions, *list, c);
2209
2210 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name,
2211 "%s=%s%s%s", type_name,
2212 trigger ? "|" : "", negate ? "!" : "", param);
2213 }
2214
2215 empty = false;
2216 }
2217 if (r < 0)
2218 return r;
2219
2220 r = sd_bus_message_exit_container(message);
2221 if (r < 0)
2222 return r;
2223
2224 if (!UNIT_WRITE_FLAGS_NOOP(flags) && empty) {
2225 *list = condition_free_list(*list);
2226 unit_write_settingf(u, flags, name, "%sNull=", is_condition ? "Condition" : "Assert");
2227 }
2228
2229 return 1;
2230}
2231
2232static int bus_unit_set_transient_property(
2233 Unit *u,
2234 const char *name,
2235 sd_bus_message *message,
2236 UnitWriteFlags flags,
2237 sd_bus_error *error) {
2238
2239 UnitDependency d;
2240 int r;
2241
2242 assert(u);
2243 assert(name);
2244 assert(message);
2245
2246 /* Handles settings when transient units are created. This settings cannot be altered anymore after
2247 * the unit has been created. */
2248
2249 if (streq(name, "SourcePath"))
2250 return bus_set_transient_path(u, name, &u->source_path, message, flags, error);
2251
2252 if (streq(name, "StopWhenUnneeded"))
2253 return bus_set_transient_bool(u, name, &u->stop_when_unneeded, message, flags, error);
2254
2255 if (streq(name, "RefuseManualStart"))
2256 return bus_set_transient_bool(u, name, &u->refuse_manual_start, message, flags, error);
2257
2258 if (streq(name, "RefuseManualStop"))
2259 return bus_set_transient_bool(u, name, &u->refuse_manual_stop, message, flags, error);
2260
2261 if (streq(name, "AllowIsolate"))
2262 return bus_set_transient_bool(u, name, &u->allow_isolate, message, flags, error);
2263
2264 if (streq(name, "DefaultDependencies"))
2265 return bus_set_transient_bool(u, name, &u->default_dependencies, message, flags, error);
2266
2267 if (streq(name, "SurviveFinalKillSignal"))
2268 return bus_set_transient_bool(u, name, &u->survive_final_kill_signal, message, flags, error);
2269
2270 if (streq(name, "OnSuccessJobMode"))
2271 return bus_set_transient_job_mode(u, name, &u->on_success_job_mode, message, flags, error);
2272
2273 if (streq(name, "OnFailureJobMode"))
2274 return bus_set_transient_job_mode(u, name, &u->on_failure_job_mode, message, flags, error);
2275
2276 if (streq(name, "IgnoreOnIsolate"))
2277 return bus_set_transient_bool(u, name, &u->ignore_on_isolate, message, flags, error);
2278
2279 if (streq(name, "JobTimeoutUSec")) {
2280 r = bus_set_transient_usec_fix_0(u, name, &u->job_timeout, message, flags, error);
2281 if (r >= 0 && !UNIT_WRITE_FLAGS_NOOP(flags) && !u->job_running_timeout_set)
2282 u->job_running_timeout = u->job_timeout;
2283 }
2284
2285 if (streq(name, "JobRunningTimeoutUSec")) {
2286 r = bus_set_transient_usec_fix_0(u, name, &u->job_running_timeout, message, flags, error);
2287 if (r >= 0 && !UNIT_WRITE_FLAGS_NOOP(flags))
2288 u->job_running_timeout_set = true;
2289
2290 return r;
2291 }
2292
2293 if (streq(name, "JobTimeoutAction"))
2294 return bus_set_transient_emergency_action(u, name, &u->job_timeout_action, message, flags, error);
2295
2296 if (streq(name, "JobTimeoutRebootArgument"))
2297 return bus_set_transient_reboot_parameter(u, name, &u->job_timeout_reboot_arg, message, flags, error);
2298
2299 if (streq(name, "StartLimitIntervalUSec"))
2300 return bus_set_transient_usec(u, name, &u->start_ratelimit.interval, message, flags, error);
2301
2302 if (streq(name, "StartLimitBurst"))
2303 return bus_set_transient_unsigned(u, name, &u->start_ratelimit.burst, message, flags, error);
2304
2305 if (streq(name, "StartLimitAction"))
2306 return bus_set_transient_emergency_action(u, name, &u->start_limit_action, message, flags, error);
2307
2308 if (streq(name, "FailureAction"))
2309 return bus_set_transient_emergency_action(u, name, &u->failure_action, message, flags, error);
2310
2311 if (streq(name, "SuccessAction"))
2312 return bus_set_transient_emergency_action(u, name, &u->success_action, message, flags, error);
2313
2314 if (streq(name, "FailureActionExitStatus"))
2315 return bus_set_transient_exit_status(u, name, &u->failure_action_exit_status, message, flags, error);
2316
2317 if (streq(name, "SuccessActionExitStatus"))
2318 return bus_set_transient_exit_status(u, name, &u->success_action_exit_status, message, flags, error);
2319
2320 if (streq(name, "RebootArgument"))
2321 return bus_set_transient_reboot_parameter(u, name, &u->reboot_arg, message, flags, error);
2322
2323 if (streq(name, "CollectMode"))
2324 return bus_set_transient_collect_mode(u, name, &u->collect_mode, message, flags, error);
2325
2326 if (streq(name, "Conditions"))
2327 return bus_set_transient_conditions(u, name, &u->conditions, true, message, flags, error);
2328
2329 if (streq(name, "Asserts"))
2330 return bus_set_transient_conditions(u, name, &u->asserts, false, message, flags, error);
2331
2332 if (streq(name, "Documentation")) {
2333 _cleanup_strv_free_ char **l = NULL;
2334
2335 r = sd_bus_message_read_strv(message, &l);
2336 if (r < 0)
2337 return r;
2338
2339 STRV_FOREACH(p, l)
2340 if (!documentation_url_is_valid(*p))
2341 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid URL in %s: %s", name, *p);
2342
2343 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2344 if (strv_isempty(l)) {
2345 u->documentation = strv_free(u->documentation);
2346 unit_write_settingf(u, flags, name, "%s=", name);
2347 } else {
2348 r = strv_extend_strv(&u->documentation, l, /* filter_duplicates= */ false);
2349 if (r < 0)
2350 return r;
2351
2352 STRV_FOREACH(p, l)
2353 unit_write_settingf(u, flags, name, "%s=%s", name, *p);
2354 }
2355 }
2356
2357 return 1;
2358 }
2359
2360 if (streq(name, "Slice")) {
2361 Unit *slice;
2362 const char *s;
2363
2364 if (!UNIT_HAS_CGROUP_CONTEXT(u))
2365 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "The slice property is only available for units with control groups.");
2366 if (u->type == UNIT_SLICE)
2367 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Slice may not be set for slice units.");
2368 if (unit_has_name(u, SPECIAL_INIT_SCOPE))
2369 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot set slice for init.scope");
2370
2371 r = sd_bus_message_read(message, "s", &s);
2372 if (r < 0)
2373 return r;
2374
2375 if (!unit_name_is_valid(s, UNIT_NAME_PLAIN))
2376 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name '%s'", s);
2377
2378 /* Note that we do not dispatch the load queue here yet, as we don't want our own transient unit to be
2379 * loaded while we are still setting it up. Or in other words, we use manager_load_unit_prepare()
2380 * instead of manager_load_unit() on purpose, here. */
2381 r = manager_load_unit_prepare(u->manager, s, NULL, error, &slice);
2382 if (r < 0)
2383 return r;
2384
2385 if (slice->type != UNIT_SLICE)
2386 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit name '%s' is not a slice", s);
2387
2388 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2389 r = unit_set_slice(u, slice);
2390 if (r < 0)
2391 return r;
2392
2393 unit_write_settingf(u, flags|UNIT_PRIVATE, name, "Slice=%s", s);
2394 }
2395
2396 return 1;
2397 }
2398
2399 if (STR_IN_SET(name, "RequiresMountsFor", "WantsMountsFor")) {
2400 _cleanup_strv_free_ char **l = NULL;
2401
2402 r = sd_bus_message_read_strv(message, &l);
2403 if (r < 0)
2404 return r;
2405
2406 STRV_FOREACH(p, l) {
2407 path_simplify(*p);
2408
2409 if (!path_is_absolute(*p))
2410 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path specified in %s is not absolute: %s", name, *p);
2411
2412 if (!path_is_valid(*p))
2413 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path specified in %s has invalid length: %s", name, *p);
2414
2415 if (!path_is_normalized(*p))
2416 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path specified in %s is not normalized: %s", name, *p);
2417
2418 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2419 r = unit_add_mounts_for(u, *p, UNIT_DEPENDENCY_FILE, unit_mount_dependency_type_from_string(name));
2420 if (r < 0)
2421 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to add requested mount \"%s\": %m", *p);
2422
2423 unit_write_settingf(u, flags, name, "%s=%s", name, *p);
2424 }
2425 }
2426
2427 return 1;
2428 }
2429
2430 if (streq(name, "AddRef")) {
2431 int b;
2432
2433 /* Why is this called "AddRef" rather than just "Ref", or "Reference"? There's already a "Ref()" method
2434 * on the Unit interface, and it's probably not a good idea to expose a property and a method on the
2435 * same interface (well, strictly speaking AddRef isn't exposed as full property, we just read it for
2436 * transient units, but still). And "References" and "ReferencedBy" is already used as unit reference
2437 * dependency type, hence let's not confuse things with that.
2438 *
2439 * Note that we don't actually add the reference to the bus track. We do that only after the setup of
2440 * the transient unit is complete, so that setting this property multiple times in the same transient
2441 * unit creation call doesn't count as individual references. */
2442
2443 r = sd_bus_message_read(message, "b", &b);
2444 if (r < 0)
2445 return r;
2446
2447 if (!UNIT_WRITE_FLAGS_NOOP(flags))
2448 u->bus_track_add = b;
2449
2450 return 1;
2451 }
2452
2453 if (streq(name, "RequiresOverridable"))
2454 d = UNIT_REQUIRES; /* redirect for obsolete unit dependency type */
2455 else if (streq(name, "RequisiteOverridable"))
2456 d = UNIT_REQUISITE; /* same here */
2457 else
2458 d = unit_dependency_from_string(name);
2459 if (d >= 0) {
2460 const char *other;
2461
2462 if (!IN_SET(d,
2463 UNIT_REQUIRES,
2464 UNIT_REQUISITE,
2465 UNIT_WANTS,
2466 UNIT_BINDS_TO,
2467 UNIT_PART_OF,
2468 UNIT_UPHOLDS,
2469 UNIT_CONFLICTS,
2470 UNIT_BEFORE,
2471 UNIT_AFTER,
2472 UNIT_ON_SUCCESS,
2473 UNIT_ON_FAILURE,
2474 UNIT_PROPAGATES_RELOAD_TO,
2475 UNIT_RELOAD_PROPAGATED_FROM,
2476 UNIT_PROPAGATES_STOP_TO,
2477 UNIT_STOP_PROPAGATED_FROM,
2478 UNIT_JOINS_NAMESPACE_OF))
2479 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Dependency type %s may not be created transiently.", unit_dependency_to_string(d));
2480
2481 r = sd_bus_message_enter_container(message, 'a', "s");
2482 if (r < 0)
2483 return r;
2484
2485 while ((r = sd_bus_message_read(message, "s", &other)) > 0) {
2486 if (!unit_name_is_valid(other, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
2487 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name %s", other);
2488
2489 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2490 _cleanup_free_ char *label = NULL;
2491
2492 r = unit_add_dependency_by_name(u, d, other, true, UNIT_DEPENDENCY_FILE);
2493 if (r < 0)
2494 return r;
2495
2496 label = strjoin(name, "-", other);
2497 if (!label)
2498 return -ENOMEM;
2499
2500 unit_write_settingf(u, flags, label, "%s=%s", unit_dependency_to_string(d), other);
2501 }
2502
2503 }
2504 if (r < 0)
2505 return r;
2506
2507 r = sd_bus_message_exit_container(message);
2508 if (r < 0)
2509 return r;
2510
2511 return 1;
2512 }
2513
2514 return 0;
2515}
2516
2517int bus_unit_set_properties(
2518 Unit *u,
2519 sd_bus_message *message,
2520 UnitWriteFlags flags,
2521 bool commit,
2522 sd_bus_error *error) {
2523
2524 bool for_real = false;
2525 unsigned n = 0;
2526 int r;
2527
2528 assert(u);
2529 assert(message);
2530
2531 /* We iterate through the array twice. First run just checks if all passed data is valid, second run
2532 * actually applies it. This implements transaction-like behaviour without actually providing full
2533 * transactions. */
2534
2535 r = sd_bus_message_enter_container(message, 'a', "(sv)");
2536 if (r < 0)
2537 goto error;
2538
2539 for (;;) {
2540 const char *name;
2541 UnitWriteFlags f;
2542
2543 r = sd_bus_message_enter_container(message, 'r', "sv");
2544 if (r < 0)
2545 goto error;
2546 if (r == 0) {
2547 if (for_real || UNIT_WRITE_FLAGS_NOOP(flags))
2548 break;
2549
2550 /* Reached EOF. Let's try again, and this time for realz... */
2551 r = sd_bus_message_rewind(message, false);
2552 if (r < 0)
2553 goto error;
2554
2555 for_real = true;
2556 continue;
2557 }
2558
2559 r = sd_bus_message_read(message, "s", &name);
2560 if (r < 0)
2561 goto error;
2562
2563 r = sd_bus_message_enter_container(message, 'v', NULL);
2564 if (r < 0)
2565 goto error;
2566
2567 /* If not for real, then mask out the two target flags */
2568 f = for_real ? flags : (flags & ~(UNIT_RUNTIME|UNIT_PERSISTENT));
2569
2570 if (UNIT_VTABLE(u)->bus_set_property)
2571 r = UNIT_VTABLE(u)->bus_set_property(u, name, message, f, error);
2572 else
2573 r = 0;
2574 if (r == 0 && u->transient && u->load_state == UNIT_STUB)
2575 r = bus_unit_set_transient_property(u, name, message, f, error);
2576 if (r == 0)
2577 r = bus_unit_set_live_property(u, name, message, f, error);
2578 if (r < 0)
2579 goto error;
2580
2581 if (r == 0)
2582 return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY,
2583 "Cannot set property %s, or unknown property.", name);
2584
2585 r = sd_bus_message_exit_container(message);
2586 if (r < 0)
2587 goto error;
2588
2589 r = sd_bus_message_exit_container(message);
2590 if (r < 0)
2591 goto error;
2592
2593 n += for_real;
2594 }
2595
2596 r = sd_bus_message_exit_container(message);
2597 if (r < 0)
2598 goto error;
2599
2600 if (commit && n > 0 && UNIT_VTABLE(u)->bus_commit_properties)
2601 UNIT_VTABLE(u)->bus_commit_properties(u);
2602
2603 return n;
2604
2605 error:
2606 /* Pretty much any of the calls above can fail if the message is not formed properly
2607 * or if it has unexpected contents. Fill in a more informative error message here. */
2608 if (sd_bus_error_is_set(error))
2609 return r;
2610 return sd_bus_error_set_errnof(error, r,
2611 r == -ENXIO ? "Failed to set unit properties: Unexpected message contents"
2612 : "Failed to set unit properties: %m");
2613}
2614
2615int bus_unit_validate_load_state(Unit *u, sd_bus_error *error) {
2616 assert(u);
2617
2618 /* Generates a pretty error if a unit isn't properly loaded. */
2619
2620 switch (u->load_state) {
2621
2622 case UNIT_LOADED:
2623 return 0;
2624
2625 case UNIT_NOT_FOUND:
2626 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not found.", u->id);
2627
2628 case UNIT_BAD_SETTING:
2629 return sd_bus_error_setf(error, BUS_ERROR_BAD_UNIT_SETTING, "Unit %s has a bad unit file setting.", u->id);
2630
2631 case UNIT_ERROR: /* Only show .load_error in UNIT_ERROR state */
2632 return sd_bus_error_set_errnof(error, u->load_error,
2633 "Unit %s failed to load properly, please adjust/correct and reload service manager: %m", u->id);
2634
2635 case UNIT_MASKED:
2636 return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit %s is masked.", u->id);
2637
2638 case UNIT_STUB:
2639 case UNIT_MERGED:
2640 default:
2641 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unexpected load state of unit %s", u->id);
2642 }
2643}
2644
2645static int bus_unit_track_handler(sd_bus_track *t, void *userdata) {
2646 Unit *u = ASSERT_PTR(userdata);
2647
2648 assert(t);
2649
2650 u->bus_track = sd_bus_track_unref(u->bus_track); /* make sure we aren't called again */
2651
2652 /* Add the unit to the GC queue, after all if the client left it might be time to GC this unit */
2653 unit_add_to_gc_queue(u);
2654
2655 return 0;
2656}
2657
2658static int bus_unit_allocate_bus_track(Unit *u) {
2659 int r;
2660
2661 assert(u);
2662
2663 if (u->bus_track)
2664 return 0;
2665
2666 r = sd_bus_track_new(u->manager->api_bus, &u->bus_track, bus_unit_track_handler, u);
2667 if (r < 0)
2668 return r;
2669
2670 r = sd_bus_track_set_recursive(u->bus_track, true);
2671 if (r < 0) {
2672 u->bus_track = sd_bus_track_unref(u->bus_track);
2673 return r;
2674 }
2675
2676 return 0;
2677}
2678
2679int bus_unit_track_add_name(Unit *u, const char *name) {
2680 int r;
2681
2682 assert(u);
2683
2684 r = bus_unit_allocate_bus_track(u);
2685 if (r < 0)
2686 return r;
2687
2688 return sd_bus_track_add_name(u->bus_track, name);
2689}
2690
2691int bus_unit_track_add_sender(Unit *u, sd_bus_message *m) {
2692 int r;
2693
2694 assert(u);
2695
2696 r = bus_unit_allocate_bus_track(u);
2697 if (r < 0)
2698 return r;
2699
2700 return sd_bus_track_add_sender(u->bus_track, m);
2701}
2702
2703int bus_unit_track_remove_sender(Unit *u, sd_bus_message *m) {
2704 assert(u);
2705
2706 /* If we haven't allocated the bus track object yet, then there's definitely no reference taken yet,
2707 * return an error */
2708 if (!u->bus_track)
2709 return -EUNATCH;
2710
2711 return sd_bus_track_remove_sender(u->bus_track, m);
2712}