1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <sys/mount.h>
4 #include <sys/prctl.h>
5 
6 #if HAVE_SECCOMP
7 #include <seccomp.h>
8 #endif
9 
10 #include "af-list.h"
11 #include "alloc-util.h"
12 #include "bus-get-properties.h"
13 #include "cap-list.h"
14 #include "capability-util.h"
15 #include "cpu-set-util.h"
16 #include "creds-util.h"
17 #include "dbus-execute.h"
18 #include "dbus-util.h"
19 #include "env-util.h"
20 #include "errno-list.h"
21 #include "escape.h"
22 #include "execute.h"
23 #include "fd-util.h"
24 #include "fileio.h"
25 #include "hexdecoct.h"
26 #include "io-util.h"
27 #include "ioprio-util.h"
28 #include "journal-file.h"
29 #include "missing_ioprio.h"
30 #include "mountpoint-util.h"
31 #include "namespace.h"
32 #include "parse-util.h"
33 #include "path-util.h"
34 #include "process-util.h"
35 #include "rlimit-util.h"
36 #if HAVE_SECCOMP
37 #include "seccomp-util.h"
38 #endif
39 #include "securebits-util.h"
40 #include "specifier.h"
41 #include "stat-util.h"
42 #include "strv.h"
43 #include "syslog-util.h"
44 #include "unit-printf.h"
45 #include "user-util.h"
46 #include "utf8.h"
47 
48 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
49 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
50 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode);
51 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_preserve_mode, exec_preserve_mode, ExecPreserveMode);
52 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_keyring_mode, exec_keyring_mode, ExecKeyringMode);
53 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_protect_proc, protect_proc, ProtectProc);
54 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_proc_subset, proc_subset, ProcSubset);
55 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_protect_home, protect_home, ProtectHome);
56 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_protect_system, protect_system, ProtectSystem);
57 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_personality, personality, unsigned long);
58 static BUS_DEFINE_PROPERTY_GET(property_get_ioprio, "i", ExecContext, exec_context_get_effective_ioprio);
59 static BUS_DEFINE_PROPERTY_GET(property_get_mount_apivfs, "b", ExecContext, exec_context_get_effective_mount_apivfs);
60 static BUS_DEFINE_PROPERTY_GET2(property_get_ioprio_class, "i", ExecContext, exec_context_get_effective_ioprio, ioprio_prio_class);
61 static BUS_DEFINE_PROPERTY_GET2(property_get_ioprio_priority, "i", ExecContext, exec_context_get_effective_ioprio, ioprio_prio_data);
62 static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_empty_string, "s", NULL);
63 static BUS_DEFINE_PROPERTY_GET_REF(property_get_syslog_level, "i", int, LOG_PRI);
64 static BUS_DEFINE_PROPERTY_GET_REF(property_get_syslog_facility, "i", int, LOG_FAC);
65 static BUS_DEFINE_PROPERTY_GET(property_get_cpu_affinity_from_numa, "b", ExecContext, exec_context_get_cpu_affinity_from_numa);
66 
property_get_environment_files(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)67 static int property_get_environment_files(
68                 sd_bus *bus,
69                 const char *path,
70                 const char *interface,
71                 const char *property,
72                 sd_bus_message *reply,
73                 void *userdata,
74                 sd_bus_error *error) {
75 
76         ExecContext *c = userdata;
77         int r;
78 
79         assert(bus);
80         assert(reply);
81         assert(c);
82 
83         r = sd_bus_message_open_container(reply, 'a', "(sb)");
84         if (r < 0)
85                 return r;
86 
87         STRV_FOREACH(j, c->environment_files) {
88                 const char *fn = *j;
89 
90                 r = sd_bus_message_append(reply, "(sb)", fn[0] == '-' ? fn + 1 : fn, fn[0] == '-');
91                 if (r < 0)
92                         return r;
93         }
94 
95         return sd_bus_message_close_container(reply);
96 }
97 
property_get_oom_score_adjust(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)98 static int property_get_oom_score_adjust(
99                 sd_bus *bus,
100                 const char *path,
101                 const char *interface,
102                 const char *property,
103                 sd_bus_message *reply,
104                 void *userdata,
105                 sd_bus_error *error) {
106 
107         ExecContext *c = userdata;
108         int r, n;
109 
110         assert(bus);
111         assert(reply);
112         assert(c);
113 
114         if (c->oom_score_adjust_set)
115                 n = c->oom_score_adjust;
116         else {
117                 n = 0;
118                 r = get_oom_score_adjust(&n);
119                 if (r < 0)
120                         log_debug_errno(r, "Failed to read /proc/self/oom_score_adj, ignoring: %m");
121         }
122 
123         return sd_bus_message_append(reply, "i", n);
124 }
125 
property_get_coredump_filter(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)126 static int property_get_coredump_filter(
127                 sd_bus *bus,
128                 const char *path,
129                 const char *interface,
130                 const char *property,
131                 sd_bus_message *reply,
132                 void *userdata,
133                 sd_bus_error *error) {
134 
135         ExecContext *c = userdata;
136         uint64_t n;
137         int r;
138 
139         assert(bus);
140         assert(reply);
141         assert(c);
142 
143         if (c->coredump_filter_set)
144                 n = c->coredump_filter;
145         else {
146                 _cleanup_free_ char *t = NULL;
147 
148                 n = COREDUMP_FILTER_MASK_DEFAULT;
149                 r = read_one_line_file("/proc/self/coredump_filter", &t);
150                 if (r < 0)
151                         log_debug_errno(r, "Failed to read /proc/self/coredump_filter, ignoring: %m");
152                 else {
153                         r = safe_atoux64(t, &n);
154                         if (r < 0)
155                                 log_debug_errno(r, "Failed to parse \"%s\" from /proc/self/coredump_filter, ignoring: %m", t);
156                 }
157         }
158 
159         return sd_bus_message_append(reply, "t", n);
160 }
161 
property_get_nice(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)162 static int property_get_nice(
163                 sd_bus *bus,
164                 const char *path,
165                 const char *interface,
166                 const char *property,
167                 sd_bus_message *reply,
168                 void *userdata,
169                 sd_bus_error *error) {
170 
171         ExecContext *c = userdata;
172         int32_t n;
173 
174         assert(bus);
175         assert(reply);
176         assert(c);
177 
178         if (c->nice_set)
179                 n = c->nice;
180         else {
181                 errno = 0;
182                 n = getpriority(PRIO_PROCESS, 0);
183                 if (errno > 0)
184                         n = 0;
185         }
186 
187         return sd_bus_message_append(reply, "i", n);
188 }
189 
property_get_cpu_sched_policy(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)190 static int property_get_cpu_sched_policy(
191                 sd_bus *bus,
192                 const char *path,
193                 const char *interface,
194                 const char *property,
195                 sd_bus_message *reply,
196                 void *userdata,
197                 sd_bus_error *error) {
198 
199         ExecContext *c = userdata;
200         int32_t n;
201 
202         assert(bus);
203         assert(reply);
204         assert(c);
205 
206         if (c->cpu_sched_set)
207                 n = c->cpu_sched_policy;
208         else {
209                 n = sched_getscheduler(0);
210                 if (n < 0)
211                         n = SCHED_OTHER;
212         }
213 
214         return sd_bus_message_append(reply, "i", n);
215 }
216 
property_get_cpu_sched_priority(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)217 static int property_get_cpu_sched_priority(
218                 sd_bus *bus,
219                 const char *path,
220                 const char *interface,
221                 const char *property,
222                 sd_bus_message *reply,
223                 void *userdata,
224                 sd_bus_error *error) {
225 
226         ExecContext *c = userdata;
227         int32_t n;
228 
229         assert(bus);
230         assert(reply);
231         assert(c);
232 
233         if (c->cpu_sched_set)
234                 n = c->cpu_sched_priority;
235         else {
236                 struct sched_param p = {};
237 
238                 if (sched_getparam(0, &p) >= 0)
239                         n = p.sched_priority;
240                 else
241                         n = 0;
242         }
243 
244         return sd_bus_message_append(reply, "i", n);
245 }
246 
property_get_cpu_affinity(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)247 static int property_get_cpu_affinity(
248                 sd_bus *bus,
249                 const char *path,
250                 const char *interface,
251                 const char *property,
252                 sd_bus_message *reply,
253                 void *userdata,
254                 sd_bus_error *error) {
255 
256         ExecContext *c = userdata;
257         _cleanup_(cpu_set_reset) CPUSet s = {};
258         _cleanup_free_ uint8_t *array = NULL;
259         size_t allocated;
260 
261         assert(bus);
262         assert(reply);
263         assert(c);
264 
265         if (c->cpu_affinity_from_numa) {
266                 int r;
267 
268                 r = numa_to_cpu_set(&c->numa_policy, &s);
269                 if (r < 0)
270                         return r;
271         }
272 
273         (void) cpu_set_to_dbus(c->cpu_affinity_from_numa ? &s : &c->cpu_set,  &array, &allocated);
274 
275         return sd_bus_message_append_array(reply, 'y', array, allocated);
276 }
277 
property_get_numa_mask(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)278 static int property_get_numa_mask(
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         ExecContext *c = userdata;
288         _cleanup_free_ uint8_t *array = NULL;
289         size_t allocated;
290 
291         assert(bus);
292         assert(reply);
293         assert(c);
294 
295         (void) cpu_set_to_dbus(&c->numa_policy.nodes, &array, &allocated);
296 
297         return sd_bus_message_append_array(reply, 'y', array, allocated);
298 }
299 
property_get_numa_policy(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)300 static int property_get_numa_policy(
301                 sd_bus *bus,
302                 const char *path,
303                 const char *interface,
304                 const char *property,
305                 sd_bus_message *reply,
306                 void *userdata,
307                 sd_bus_error *error) {
308         ExecContext *c = userdata;
309         int32_t policy;
310 
311         assert(bus);
312         assert(reply);
313         assert(c);
314 
315         policy = numa_policy_get_type(&c->numa_policy);
316 
317         return sd_bus_message_append_basic(reply, 'i', &policy);
318 }
319 
property_get_timer_slack_nsec(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)320 static int property_get_timer_slack_nsec(
321                 sd_bus *bus,
322                 const char *path,
323                 const char *interface,
324                 const char *property,
325                 sd_bus_message *reply,
326                 void *userdata,
327                 sd_bus_error *error) {
328 
329         ExecContext *c = userdata;
330         uint64_t u;
331 
332         assert(bus);
333         assert(reply);
334         assert(c);
335 
336         if (c->timer_slack_nsec != NSEC_INFINITY)
337                 u = (uint64_t) c->timer_slack_nsec;
338         else
339                 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
340 
341         return sd_bus_message_append(reply, "t", u);
342 }
343 
property_get_syscall_filter(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)344 static int property_get_syscall_filter(
345                 sd_bus *bus,
346                 const char *path,
347                 const char *interface,
348                 const char *property,
349                 sd_bus_message *reply,
350                 void *userdata,
351                 sd_bus_error *error) {
352 
353         ExecContext *c = userdata;
354         _cleanup_strv_free_ char **l = NULL;
355         int r;
356 
357         assert(bus);
358         assert(reply);
359         assert(c);
360 
361         r = sd_bus_message_open_container(reply, 'r', "bas");
362         if (r < 0)
363                 return r;
364 
365         r = sd_bus_message_append(reply, "b", c->syscall_allow_list);
366         if (r < 0)
367                 return r;
368 
369 #if HAVE_SECCOMP
370         void *id, *val;
371         HASHMAP_FOREACH_KEY(val, id, c->syscall_filter) {
372                 _cleanup_free_ char *name = NULL;
373                 const char *e = NULL;
374                 char *s;
375                 int num = PTR_TO_INT(val);
376 
377                 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
378                 if (!name)
379                         continue;
380 
381                 if (num >= 0) {
382                         e = seccomp_errno_or_action_to_string(num);
383                         if (e) {
384                                 s = strjoin(name, ":", e);
385                                 if (!s)
386                                         return -ENOMEM;
387                         } else {
388                                 r = asprintf(&s, "%s:%d", name, num);
389                                 if (r < 0)
390                                         return -ENOMEM;
391                         }
392                 } else
393                         s = TAKE_PTR(name);
394 
395                 r = strv_consume(&l, s);
396                 if (r < 0)
397                         return r;
398         }
399 #endif
400 
401         strv_sort(l);
402 
403         r = sd_bus_message_append_strv(reply, l);
404         if (r < 0)
405                 return r;
406 
407         return sd_bus_message_close_container(reply);
408 }
409 
property_get_syscall_log(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)410 static int property_get_syscall_log(
411                 sd_bus *bus,
412                 const char *path,
413                 const char *interface,
414                 const char *property,
415                 sd_bus_message *reply,
416                 void *userdata,
417                 sd_bus_error *error) {
418 
419         ExecContext *c = userdata;
420         _cleanup_strv_free_ char **l = NULL;
421         int r;
422 
423         assert(bus);
424         assert(reply);
425         assert(c);
426 
427         r = sd_bus_message_open_container(reply, 'r', "bas");
428         if (r < 0)
429                 return r;
430 
431         r = sd_bus_message_append(reply, "b", c->syscall_log_allow_list);
432         if (r < 0)
433                 return r;
434 
435 #if HAVE_SECCOMP
436         void *id, *val;
437         HASHMAP_FOREACH_KEY(val, id, c->syscall_log) {
438                 char *name = NULL;
439 
440                 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
441                 if (!name)
442                         continue;
443 
444                 r = strv_consume(&l, name);
445                 if (r < 0)
446                         return r;
447         }
448 #endif
449 
450         strv_sort(l);
451 
452         r = sd_bus_message_append_strv(reply, l);
453         if (r < 0)
454                 return r;
455 
456         return sd_bus_message_close_container(reply);
457 }
458 
property_get_syscall_archs(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)459 static int property_get_syscall_archs(
460                 sd_bus *bus,
461                 const char *path,
462                 const char *interface,
463                 const char *property,
464                 sd_bus_message *reply,
465                 void *userdata,
466                 sd_bus_error *error) {
467 
468         ExecContext *c = userdata;
469         _cleanup_strv_free_ char **l = NULL;
470         int r;
471 
472         assert(bus);
473         assert(reply);
474         assert(c);
475 
476 #if HAVE_SECCOMP
477         void *id;
478         SET_FOREACH(id, c->syscall_archs) {
479                 const char *name;
480 
481                 name = seccomp_arch_to_string(PTR_TO_UINT32(id) - 1);
482                 if (!name)
483                         continue;
484 
485                 r = strv_extend(&l, name);
486                 if (r < 0)
487                         return -ENOMEM;
488         }
489 #endif
490 
491         strv_sort(l);
492 
493         r = sd_bus_message_append_strv(reply, l);
494         if (r < 0)
495                 return r;
496 
497         return 0;
498 }
499 
property_get_selinux_context(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)500 static int property_get_selinux_context(
501                 sd_bus *bus,
502                 const char *path,
503                 const char *interface,
504                 const char *property,
505                 sd_bus_message *reply,
506                 void *userdata,
507                 sd_bus_error *error) {
508 
509         ExecContext *c = userdata;
510 
511         assert(bus);
512         assert(reply);
513         assert(c);
514 
515         return sd_bus_message_append(reply, "(bs)", c->selinux_context_ignore, c->selinux_context);
516 }
517 
property_get_apparmor_profile(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)518 static int property_get_apparmor_profile(
519                 sd_bus *bus,
520                 const char *path,
521                 const char *interface,
522                 const char *property,
523                 sd_bus_message *reply,
524                 void *userdata,
525                 sd_bus_error *error) {
526 
527         ExecContext *c = userdata;
528 
529         assert(bus);
530         assert(reply);
531         assert(c);
532 
533         return sd_bus_message_append(reply, "(bs)", c->apparmor_profile_ignore, c->apparmor_profile);
534 }
535 
property_get_smack_process_label(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)536 static int property_get_smack_process_label(
537                 sd_bus *bus,
538                 const char *path,
539                 const char *interface,
540                 const char *property,
541                 sd_bus_message *reply,
542                 void *userdata,
543                 sd_bus_error *error) {
544 
545         ExecContext *c = userdata;
546 
547         assert(bus);
548         assert(reply);
549         assert(c);
550 
551         return sd_bus_message_append(reply, "(bs)", c->smack_process_label_ignore, c->smack_process_label);
552 }
553 
property_get_address_families(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)554 static int property_get_address_families(
555                 sd_bus *bus,
556                 const char *path,
557                 const char *interface,
558                 const char *property,
559                 sd_bus_message *reply,
560                 void *userdata,
561                 sd_bus_error *error) {
562 
563         ExecContext *c = userdata;
564         _cleanup_strv_free_ char **l = NULL;
565         void *af;
566         int r;
567 
568         assert(bus);
569         assert(reply);
570         assert(c);
571 
572         r = sd_bus_message_open_container(reply, 'r', "bas");
573         if (r < 0)
574                 return r;
575 
576         r = sd_bus_message_append(reply, "b", c->address_families_allow_list);
577         if (r < 0)
578                 return r;
579 
580         SET_FOREACH(af, c->address_families) {
581                 const char *name;
582 
583                 name = af_to_name(PTR_TO_INT(af));
584                 if (!name)
585                         continue;
586 
587                 r = strv_extend(&l, name);
588                 if (r < 0)
589                         return -ENOMEM;
590         }
591 
592         strv_sort(l);
593 
594         r = sd_bus_message_append_strv(reply, l);
595         if (r < 0)
596                 return r;
597 
598         return sd_bus_message_close_container(reply);
599 }
600 
property_get_working_directory(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)601 static int property_get_working_directory(
602                 sd_bus *bus,
603                 const char *path,
604                 const char *interface,
605                 const char *property,
606                 sd_bus_message *reply,
607                 void *userdata,
608                 sd_bus_error *error) {
609 
610         ExecContext *c = userdata;
611         const char *wd;
612 
613         assert(bus);
614         assert(reply);
615         assert(c);
616 
617         if (c->working_directory_home)
618                 wd = "~";
619         else
620                 wd = c->working_directory;
621 
622         if (c->working_directory_missing_ok)
623                 wd = strjoina("!", wd);
624 
625         return sd_bus_message_append(reply, "s", wd);
626 }
627 
property_get_stdio_fdname(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)628 static int property_get_stdio_fdname(
629                 sd_bus *bus,
630                 const char *path,
631                 const char *interface,
632                 const char *property,
633                 sd_bus_message *reply,
634                 void *userdata,
635                 sd_bus_error *error) {
636 
637         ExecContext *c = userdata;
638         int fileno;
639 
640         assert(bus);
641         assert(c);
642         assert(property);
643         assert(reply);
644 
645         if (streq(property, "StandardInputFileDescriptorName"))
646                 fileno = STDIN_FILENO;
647         else if (streq(property, "StandardOutputFileDescriptorName"))
648                 fileno = STDOUT_FILENO;
649         else {
650                 assert(streq(property, "StandardErrorFileDescriptorName"));
651                 fileno = STDERR_FILENO;
652         }
653 
654         return sd_bus_message_append(reply, "s", exec_context_fdname(c, fileno));
655 }
656 
property_get_input_data(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)657 static int property_get_input_data(
658                 sd_bus *bus,
659                 const char *path,
660                 const char *interface,
661                 const char *property,
662                 sd_bus_message *reply,
663                 void *userdata,
664                 sd_bus_error *error) {
665 
666         ExecContext *c = userdata;
667 
668         assert(bus);
669         assert(c);
670         assert(property);
671         assert(reply);
672 
673         return sd_bus_message_append_array(reply, 'y', c->stdin_data, c->stdin_data_size);
674 }
675 
property_get_restrict_filesystems(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)676 static int property_get_restrict_filesystems(
677                 sd_bus *bus,
678                 const char *path,
679                 const char *interface,
680                 const char *property,
681                 sd_bus_message *reply,
682                 void *userdata,
683                 sd_bus_error *error) {
684 
685         ExecContext *c = userdata;
686         _cleanup_free_ char **l = NULL;
687         int r;
688 
689         assert(bus);
690         assert(reply);
691         assert(c);
692 
693         r = sd_bus_message_open_container(reply, 'r', "bas");
694         if (r < 0)
695                 return r;
696 
697         r = sd_bus_message_append(reply, "b", c->restrict_filesystems_allow_list);
698         if (r < 0)
699                 return r;
700 
701 #if HAVE_LIBBPF
702         l = set_get_strv(c->restrict_filesystems);
703         if (!l)
704                 return -ENOMEM;
705 #endif
706 
707         strv_sort(l);
708 
709         r = sd_bus_message_append_strv(reply, l);
710         if (r < 0)
711                 return r;
712 
713         return sd_bus_message_close_container(reply);
714 }
715 
property_get_bind_paths(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)716 static int property_get_bind_paths(
717                 sd_bus *bus,
718                 const char *path,
719                 const char *interface,
720                 const char *property,
721                 sd_bus_message *reply,
722                 void *userdata,
723                 sd_bus_error *error) {
724 
725         ExecContext *c = userdata;
726         bool ro;
727         int r;
728 
729         assert(bus);
730         assert(c);
731         assert(property);
732         assert(reply);
733 
734         ro = strstr(property, "ReadOnly");
735 
736         r = sd_bus_message_open_container(reply, 'a', "(ssbt)");
737         if (r < 0)
738                 return r;
739 
740         for (size_t i = 0; i < c->n_bind_mounts; i++) {
741 
742                 if (ro != c->bind_mounts[i].read_only)
743                         continue;
744 
745                 r = sd_bus_message_append(
746                                 reply, "(ssbt)",
747                                 c->bind_mounts[i].source,
748                                 c->bind_mounts[i].destination,
749                                 c->bind_mounts[i].ignore_enoent,
750                                 c->bind_mounts[i].recursive ? (uint64_t) MS_REC : (uint64_t) 0);
751                 if (r < 0)
752                         return r;
753         }
754 
755         return sd_bus_message_close_container(reply);
756 }
757 
property_get_temporary_filesystems(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)758 static int property_get_temporary_filesystems(
759                 sd_bus *bus,
760                 const char *path,
761                 const char *interface,
762                 const char *property,
763                 sd_bus_message *reply,
764                 void *userdata,
765                 sd_bus_error *error) {
766 
767         ExecContext *c = userdata;
768         int r;
769 
770         assert(bus);
771         assert(c);
772         assert(property);
773         assert(reply);
774 
775         r = sd_bus_message_open_container(reply, 'a', "(ss)");
776         if (r < 0)
777                 return r;
778 
779         for (unsigned i = 0; i < c->n_temporary_filesystems; i++) {
780                 TemporaryFileSystem *t = c->temporary_filesystems + i;
781 
782                 r = sd_bus_message_append(
783                                 reply, "(ss)",
784                                 t->path,
785                                 t->options);
786                 if (r < 0)
787                         return r;
788         }
789 
790         return sd_bus_message_close_container(reply);
791 }
792 
property_get_log_extra_fields(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)793 static int property_get_log_extra_fields(
794                 sd_bus *bus,
795                 const char *path,
796                 const char *interface,
797                 const char *property,
798                 sd_bus_message *reply,
799                 void *userdata,
800                 sd_bus_error *error) {
801 
802         ExecContext *c = userdata;
803         int r;
804 
805         assert(bus);
806         assert(c);
807         assert(property);
808         assert(reply);
809 
810         r = sd_bus_message_open_container(reply, 'a', "ay");
811         if (r < 0)
812                 return r;
813 
814         for (size_t i = 0; i < c->n_log_extra_fields; i++) {
815                 r = sd_bus_message_append_array(reply, 'y', c->log_extra_fields[i].iov_base, c->log_extra_fields[i].iov_len);
816                 if (r < 0)
817                         return r;
818         }
819 
820         return sd_bus_message_close_container(reply);
821 }
822 
property_get_set_credential(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)823 static int property_get_set_credential(
824                 sd_bus *bus,
825                 const char *path,
826                 const char *interface,
827                 const char *property,
828                 sd_bus_message *reply,
829                 void *userdata,
830                 sd_bus_error *error) {
831 
832         ExecContext *c = userdata;
833         ExecSetCredential *sc;
834         int r;
835 
836         assert(bus);
837         assert(c);
838         assert(property);
839         assert(reply);
840 
841         r = sd_bus_message_open_container(reply, 'a', "(say)");
842         if (r < 0)
843                 return r;
844 
845         HASHMAP_FOREACH(sc, c->set_credentials) {
846 
847                 if (sc->encrypted != streq(property, "SetCredentialEncrypted"))
848                         continue;
849 
850                 r = sd_bus_message_open_container(reply, 'r', "say");
851                 if (r < 0)
852                         return r;
853 
854                 r = sd_bus_message_append(reply, "s", sc->id);
855                 if (r < 0)
856                         return r;
857 
858                 r = sd_bus_message_append_array(reply, 'y', sc->data, sc->size);
859                 if (r < 0)
860                         return r;
861 
862                 r = sd_bus_message_close_container(reply);
863                 if (r < 0)
864                         return r;
865         }
866 
867         return sd_bus_message_close_container(reply);
868 }
869 
property_get_load_credential(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)870 static int property_get_load_credential(
871                 sd_bus *bus,
872                 const char *path,
873                 const char *interface,
874                 const char *property,
875                 sd_bus_message *reply,
876                 void *userdata,
877                 sd_bus_error *error) {
878 
879         ExecContext *c = userdata;
880         ExecLoadCredential *lc;
881         int r;
882 
883         assert(bus);
884         assert(c);
885         assert(property);
886         assert(reply);
887 
888         r = sd_bus_message_open_container(reply, 'a', "(ss)");
889         if (r < 0)
890                 return r;
891 
892         HASHMAP_FOREACH(lc, c->load_credentials) {
893 
894                 if (lc->encrypted != streq(property, "LoadCredentialEncrypted"))
895                         continue;
896 
897                 r = sd_bus_message_append(reply, "(ss)", lc->id, lc->path);
898                 if (r < 0)
899                         return r;
900         }
901 
902         return sd_bus_message_close_container(reply);
903 }
904 
property_get_root_hash(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)905 static int property_get_root_hash(
906                 sd_bus *bus,
907                 const char *path,
908                 const char *interface,
909                 const char *property,
910                 sd_bus_message *reply,
911                 void *userdata,
912                 sd_bus_error *error) {
913 
914         ExecContext *c = userdata;
915 
916         assert(bus);
917         assert(c);
918         assert(property);
919         assert(reply);
920 
921         return sd_bus_message_append_array(reply, 'y', c->root_hash, c->root_hash_size);
922 }
923 
property_get_root_hash_sig(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)924 static int property_get_root_hash_sig(
925                 sd_bus *bus,
926                 const char *path,
927                 const char *interface,
928                 const char *property,
929                 sd_bus_message *reply,
930                 void *userdata,
931                 sd_bus_error *error) {
932 
933         ExecContext *c = userdata;
934 
935         assert(bus);
936         assert(c);
937         assert(property);
938         assert(reply);
939 
940         return sd_bus_message_append_array(reply, 'y', c->root_hash_sig, c->root_hash_sig_size);
941 }
942 
property_get_root_image_options(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)943 static int property_get_root_image_options(
944                 sd_bus *bus,
945                 const char *path,
946                 const char *interface,
947                 const char *property,
948                 sd_bus_message *reply,
949                 void *userdata,
950                 sd_bus_error *error) {
951 
952         ExecContext *c = userdata;
953         int r;
954 
955         assert(bus);
956         assert(c);
957         assert(property);
958         assert(reply);
959 
960         r = sd_bus_message_open_container(reply, 'a', "(ss)");
961         if (r < 0)
962                 return r;
963 
964         LIST_FOREACH(mount_options, m, c->root_image_options) {
965                 r = sd_bus_message_append(reply, "(ss)",
966                                           partition_designator_to_string(m->partition_designator),
967                                           m->options);
968                 if (r < 0)
969                         return r;
970         }
971 
972         return sd_bus_message_close_container(reply);
973 }
974 
property_get_mount_images(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)975 static int property_get_mount_images(
976                 sd_bus *bus,
977                 const char *path,
978                 const char *interface,
979                 const char *property,
980                 sd_bus_message *reply,
981                 void *userdata,
982                 sd_bus_error *error) {
983 
984         ExecContext *c = userdata;
985         int r;
986 
987         assert(bus);
988         assert(c);
989         assert(property);
990         assert(reply);
991 
992         r = sd_bus_message_open_container(reply, 'a', "(ssba(ss))");
993         if (r < 0)
994                 return r;
995 
996         for (size_t i = 0; i < c->n_mount_images; i++) {
997                 r = sd_bus_message_open_container(reply, SD_BUS_TYPE_STRUCT, "ssba(ss)");
998                 if (r < 0)
999                         return r;
1000                 r = sd_bus_message_append(
1001                                 reply, "ssb",
1002                                 c->mount_images[i].source,
1003                                 c->mount_images[i].destination,
1004                                 c->mount_images[i].ignore_enoent);
1005                 if (r < 0)
1006                         return r;
1007                 r = sd_bus_message_open_container(reply, 'a', "(ss)");
1008                 if (r < 0)
1009                         return r;
1010                 LIST_FOREACH(mount_options, m, c->mount_images[i].mount_options) {
1011                         r = sd_bus_message_append(reply, "(ss)",
1012                                                   partition_designator_to_string(m->partition_designator),
1013                                                   m->options);
1014                         if (r < 0)
1015                                 return r;
1016                 }
1017                 r = sd_bus_message_close_container(reply);
1018                 if (r < 0)
1019                         return r;
1020                 r = sd_bus_message_close_container(reply);
1021                 if (r < 0)
1022                         return r;
1023         }
1024 
1025         return sd_bus_message_close_container(reply);
1026 }
1027 
property_get_extension_images(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)1028 static int property_get_extension_images(
1029                 sd_bus *bus,
1030                 const char *path,
1031                 const char *interface,
1032                 const char *property,
1033                 sd_bus_message *reply,
1034                 void *userdata,
1035                 sd_bus_error *error) {
1036 
1037         ExecContext *c = userdata;
1038         int r;
1039 
1040         assert(bus);
1041         assert(c);
1042         assert(property);
1043         assert(reply);
1044 
1045         r = sd_bus_message_open_container(reply, 'a', "(sba(ss))");
1046         if (r < 0)
1047                 return r;
1048 
1049         for (size_t i = 0; i < c->n_extension_images; i++) {
1050                 r = sd_bus_message_open_container(reply, SD_BUS_TYPE_STRUCT, "sba(ss)");
1051                 if (r < 0)
1052                         return r;
1053                 r = sd_bus_message_append(
1054                                 reply, "sb",
1055                                 c->extension_images[i].source,
1056                                 c->extension_images[i].ignore_enoent);
1057                 if (r < 0)
1058                         return r;
1059                 r = sd_bus_message_open_container(reply, 'a', "(ss)");
1060                 if (r < 0)
1061                         return r;
1062                 LIST_FOREACH(mount_options, m, c->extension_images[i].mount_options) {
1063                         r = sd_bus_message_append(reply, "(ss)",
1064                                                   partition_designator_to_string(m->partition_designator),
1065                                                   m->options);
1066                         if (r < 0)
1067                                 return r;
1068                 }
1069                 r = sd_bus_message_close_container(reply);
1070                 if (r < 0)
1071                         return r;
1072                 r = sd_bus_message_close_container(reply);
1073                 if (r < 0)
1074                         return r;
1075         }
1076 
1077         return sd_bus_message_close_container(reply);
1078 }
1079 
bus_property_get_exec_dir(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)1080 static int bus_property_get_exec_dir(
1081                 sd_bus *bus,
1082                 const char *path,
1083                 const char *interface,
1084                 const char *property,
1085                 sd_bus_message *reply,
1086                 void *userdata,
1087                 sd_bus_error *error) {
1088 
1089         ExecDirectory *d = userdata;
1090         int r;
1091 
1092         assert(bus);
1093         assert(d);
1094         assert(property);
1095         assert(reply);
1096 
1097         r = sd_bus_message_open_container(reply, 'a', "s");
1098         if (r < 0)
1099                 return r;
1100 
1101         for (size_t i = 0; i < d->n_items; i++) {
1102                 r = sd_bus_message_append_basic(reply, 's', d->items[i].path);
1103                 if (r < 0)
1104                         return r;
1105         }
1106 
1107         return sd_bus_message_close_container(reply);
1108 }
1109 
bus_property_get_exec_dir_symlink(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)1110 static int bus_property_get_exec_dir_symlink(
1111                 sd_bus *bus,
1112                 const char *path,
1113                 const char *interface,
1114                 const char *property,
1115                 sd_bus_message *reply,
1116                 void *userdata,
1117                 sd_bus_error *error) {
1118 
1119         ExecDirectory *d = userdata;
1120         int r;
1121 
1122         assert(bus);
1123         assert(d);
1124         assert(property);
1125         assert(reply);
1126 
1127         r = sd_bus_message_open_container(reply, 'a', "(sst)");
1128         if (r < 0)
1129                 return r;
1130 
1131         for (size_t i = 0; i < d->n_items; i++)
1132                 STRV_FOREACH(dst, d->items[i].symlinks) {
1133                         r = sd_bus_message_append(reply, "(sst)", d->items[i].path, *dst, 0 /* flags, unused for now */);
1134                         if (r < 0)
1135                                 return r;
1136                 }
1137 
1138         return sd_bus_message_close_container(reply);
1139 }
1140 
1141 const sd_bus_vtable bus_exec_vtable[] = {
1142         SD_BUS_VTABLE_START(0),
1143         SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
1144         SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1145         SD_BUS_PROPERTY("PassEnvironment", "as", NULL, offsetof(ExecContext, pass_environment), SD_BUS_VTABLE_PROPERTY_CONST),
1146         SD_BUS_PROPERTY("UnsetEnvironment", "as", NULL, offsetof(ExecContext, unset_environment), SD_BUS_VTABLE_PROPERTY_CONST),
1147         SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
1148         SD_BUS_PROPERTY("LimitCPU", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
1149         SD_BUS_PROPERTY("LimitCPUSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
1150         SD_BUS_PROPERTY("LimitFSIZE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
1151         SD_BUS_PROPERTY("LimitFSIZESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
1152         SD_BUS_PROPERTY("LimitDATA", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
1153         SD_BUS_PROPERTY("LimitDATASoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
1154         SD_BUS_PROPERTY("LimitSTACK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
1155         SD_BUS_PROPERTY("LimitSTACKSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
1156         SD_BUS_PROPERTY("LimitCORE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
1157         SD_BUS_PROPERTY("LimitCORESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
1158         SD_BUS_PROPERTY("LimitRSS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
1159         SD_BUS_PROPERTY("LimitRSSSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
1160         SD_BUS_PROPERTY("LimitNOFILE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
1161         SD_BUS_PROPERTY("LimitNOFILESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
1162         SD_BUS_PROPERTY("LimitAS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
1163         SD_BUS_PROPERTY("LimitASSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
1164         SD_BUS_PROPERTY("LimitNPROC", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
1165         SD_BUS_PROPERTY("LimitNPROCSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
1166         SD_BUS_PROPERTY("LimitMEMLOCK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
1167         SD_BUS_PROPERTY("LimitMEMLOCKSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
1168         SD_BUS_PROPERTY("LimitLOCKS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
1169         SD_BUS_PROPERTY("LimitLOCKSSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
1170         SD_BUS_PROPERTY("LimitSIGPENDING", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
1171         SD_BUS_PROPERTY("LimitSIGPENDINGSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
1172         SD_BUS_PROPERTY("LimitMSGQUEUE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
1173         SD_BUS_PROPERTY("LimitMSGQUEUESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
1174         SD_BUS_PROPERTY("LimitNICE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
1175         SD_BUS_PROPERTY("LimitNICESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
1176         SD_BUS_PROPERTY("LimitRTPRIO", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
1177         SD_BUS_PROPERTY("LimitRTPRIOSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
1178         SD_BUS_PROPERTY("LimitRTTIME", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
1179         SD_BUS_PROPERTY("LimitRTTIMESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
1180         SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1181         SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
1182         SD_BUS_PROPERTY("RootImage", "s", NULL, offsetof(ExecContext, root_image), SD_BUS_VTABLE_PROPERTY_CONST),
1183         SD_BUS_PROPERTY("RootImageOptions", "a(ss)", property_get_root_image_options, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1184         SD_BUS_PROPERTY("RootHash", "ay", property_get_root_hash, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1185         SD_BUS_PROPERTY("RootHashPath", "s", NULL, offsetof(ExecContext, root_hash_path), SD_BUS_VTABLE_PROPERTY_CONST),
1186         SD_BUS_PROPERTY("RootHashSignature", "ay", property_get_root_hash_sig, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1187         SD_BUS_PROPERTY("RootHashSignaturePath", "s", NULL, offsetof(ExecContext, root_hash_sig_path), SD_BUS_VTABLE_PROPERTY_CONST),
1188         SD_BUS_PROPERTY("RootVerity", "s", NULL, offsetof(ExecContext, root_verity), SD_BUS_VTABLE_PROPERTY_CONST),
1189         SD_BUS_PROPERTY("ExtensionDirectories", "as", NULL, offsetof(ExecContext, extension_directories), SD_BUS_VTABLE_PROPERTY_CONST),
1190         SD_BUS_PROPERTY("ExtensionImages", "a(sba(ss))", property_get_extension_images, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1191         SD_BUS_PROPERTY("MountImages", "a(ssba(ss))", property_get_mount_images, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1192         SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1193         SD_BUS_PROPERTY("CoredumpFilter", "t", property_get_coredump_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1194         SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1195         SD_BUS_PROPERTY("IOSchedulingClass", "i", property_get_ioprio_class, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1196         SD_BUS_PROPERTY("IOSchedulingPriority", "i", property_get_ioprio_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1197         SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1198         SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1199         SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1200         SD_BUS_PROPERTY("CPUAffinityFromNUMA", "b", property_get_cpu_affinity_from_numa, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1201         SD_BUS_PROPERTY("NUMAPolicy", "i", property_get_numa_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1202         SD_BUS_PROPERTY("NUMAMask", "ay", property_get_numa_mask, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1203         SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1204         SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST),
1205         SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST),
1206         SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST),
1207         SD_BUS_PROPERTY("StandardInputFileDescriptorName", "s", property_get_stdio_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1208         SD_BUS_PROPERTY("StandardInputData", "ay", property_get_input_data, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1209         SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST),
1210         SD_BUS_PROPERTY("StandardOutputFileDescriptorName", "s", property_get_stdio_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1211         SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST),
1212         SD_BUS_PROPERTY("StandardErrorFileDescriptorName", "s", property_get_stdio_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1213         SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST),
1214         SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
1215         SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
1216         SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST),
1217         SD_BUS_PROPERTY("TTYRows", "q", bus_property_get_unsigned, offsetof(ExecContext, tty_rows), SD_BUS_VTABLE_PROPERTY_CONST),
1218         SD_BUS_PROPERTY("TTYColumns", "q", bus_property_get_unsigned, offsetof(ExecContext, tty_cols), SD_BUS_VTABLE_PROPERTY_CONST),
1219         SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
1220         SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
1221         SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
1222         SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
1223         SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
1224         SD_BUS_PROPERTY("LogLevelMax", "i", bus_property_get_int, offsetof(ExecContext, log_level_max), SD_BUS_VTABLE_PROPERTY_CONST),
1225         SD_BUS_PROPERTY("LogRateLimitIntervalUSec", "t", bus_property_get_usec, offsetof(ExecContext, log_ratelimit_interval_usec), SD_BUS_VTABLE_PROPERTY_CONST),
1226         SD_BUS_PROPERTY("LogRateLimitBurst", "u", bus_property_get_unsigned, offsetof(ExecContext, log_ratelimit_burst), SD_BUS_VTABLE_PROPERTY_CONST),
1227         SD_BUS_PROPERTY("LogExtraFields", "aay", property_get_log_extra_fields, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1228         SD_BUS_PROPERTY("LogNamespace", "s", NULL, offsetof(ExecContext, log_namespace), SD_BUS_VTABLE_PROPERTY_CONST),
1229         SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
1230         SD_BUS_PROPERTY("CapabilityBoundingSet", "t", NULL, offsetof(ExecContext, capability_bounding_set), SD_BUS_VTABLE_PROPERTY_CONST),
1231         SD_BUS_PROPERTY("AmbientCapabilities", "t", NULL, offsetof(ExecContext, capability_ambient_set), SD_BUS_VTABLE_PROPERTY_CONST),
1232         SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
1233         SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
1234         SD_BUS_PROPERTY("DynamicUser", "b", bus_property_get_bool, offsetof(ExecContext, dynamic_user), SD_BUS_VTABLE_PROPERTY_CONST),
1235         SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(ExecContext, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
1236         SD_BUS_PROPERTY("SetCredential", "a(say)", property_get_set_credential, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1237         SD_BUS_PROPERTY("SetCredentialEncrypted", "a(say)", property_get_set_credential, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1238         SD_BUS_PROPERTY("LoadCredential", "a(ss)", property_get_load_credential, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1239         SD_BUS_PROPERTY("LoadCredentialEncrypted", "a(ss)", property_get_load_credential, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1240         SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
1241         SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST),
1242         SD_BUS_PROPERTY("ReadWritePaths", "as", NULL, offsetof(ExecContext, read_write_paths), SD_BUS_VTABLE_PROPERTY_CONST),
1243         SD_BUS_PROPERTY("ReadOnlyPaths", "as", NULL, offsetof(ExecContext, read_only_paths), SD_BUS_VTABLE_PROPERTY_CONST),
1244         SD_BUS_PROPERTY("InaccessiblePaths", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST),
1245         SD_BUS_PROPERTY("ExecPaths", "as", NULL, offsetof(ExecContext, exec_paths), SD_BUS_VTABLE_PROPERTY_CONST),
1246         SD_BUS_PROPERTY("NoExecPaths", "as", NULL, offsetof(ExecContext, no_exec_paths), SD_BUS_VTABLE_PROPERTY_CONST),
1247         SD_BUS_PROPERTY("ExecSearchPath", "as", NULL, offsetof(ExecContext, exec_search_path), SD_BUS_VTABLE_PROPERTY_CONST),
1248         SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
1249         SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
1250         SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
1251         SD_BUS_PROPERTY("ProtectClock", "b", bus_property_get_bool, offsetof(ExecContext, protect_clock), SD_BUS_VTABLE_PROPERTY_CONST),
1252         SD_BUS_PROPERTY("ProtectKernelTunables", "b", bus_property_get_bool, offsetof(ExecContext, protect_kernel_tunables), SD_BUS_VTABLE_PROPERTY_CONST),
1253         SD_BUS_PROPERTY("ProtectKernelModules", "b", bus_property_get_bool, offsetof(ExecContext, protect_kernel_modules), SD_BUS_VTABLE_PROPERTY_CONST),
1254         SD_BUS_PROPERTY("ProtectKernelLogs", "b", bus_property_get_bool, offsetof(ExecContext, protect_kernel_logs), SD_BUS_VTABLE_PROPERTY_CONST),
1255         SD_BUS_PROPERTY("ProtectControlGroups", "b", bus_property_get_bool, offsetof(ExecContext, protect_control_groups), SD_BUS_VTABLE_PROPERTY_CONST),
1256         SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
1257         SD_BUS_PROPERTY("PrivateUsers", "b", bus_property_get_bool, offsetof(ExecContext, private_users), SD_BUS_VTABLE_PROPERTY_CONST),
1258         SD_BUS_PROPERTY("PrivateMounts", "b", bus_property_get_bool, offsetof(ExecContext, private_mounts), SD_BUS_VTABLE_PROPERTY_CONST),
1259         SD_BUS_PROPERTY("PrivateIPC", "b", bus_property_get_bool, offsetof(ExecContext, private_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
1260         SD_BUS_PROPERTY("ProtectHome", "s", property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST),
1261         SD_BUS_PROPERTY("ProtectSystem", "s", property_get_protect_system, offsetof(ExecContext, protect_system), SD_BUS_VTABLE_PROPERTY_CONST),
1262         SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
1263         SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
1264         SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode, offsetof(ExecContext, utmp_mode), SD_BUS_VTABLE_PROPERTY_CONST),
1265         SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1266         SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1267         SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1268         SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
1269         SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
1270         SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1271         SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1272         SD_BUS_PROPERTY("SystemCallErrorNumber", "i", bus_property_get_int, offsetof(ExecContext, syscall_errno), SD_BUS_VTABLE_PROPERTY_CONST),
1273         SD_BUS_PROPERTY("SystemCallLog", "(bas)", property_get_syscall_log, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1274         SD_BUS_PROPERTY("Personality", "s", property_get_personality, offsetof(ExecContext, personality), SD_BUS_VTABLE_PROPERTY_CONST),
1275         SD_BUS_PROPERTY("LockPersonality", "b", bus_property_get_bool, offsetof(ExecContext, lock_personality), SD_BUS_VTABLE_PROPERTY_CONST),
1276         SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1277         SD_BUS_PROPERTY("RuntimeDirectorySymlink", "a(sst)", bus_property_get_exec_dir_symlink, offsetof(ExecContext, directories[EXEC_DIRECTORY_RUNTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
1278         SD_BUS_PROPERTY("RuntimeDirectoryPreserve", "s", property_get_exec_preserve_mode, offsetof(ExecContext, runtime_directory_preserve_mode), SD_BUS_VTABLE_PROPERTY_CONST),
1279         SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_RUNTIME].mode), SD_BUS_VTABLE_PROPERTY_CONST),
1280         SD_BUS_PROPERTY("RuntimeDirectory", "as", bus_property_get_exec_dir, offsetof(ExecContext, directories[EXEC_DIRECTORY_RUNTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
1281         SD_BUS_PROPERTY("StateDirectorySymlink", "a(sst)", bus_property_get_exec_dir_symlink, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE]), SD_BUS_VTABLE_PROPERTY_CONST),
1282         SD_BUS_PROPERTY("StateDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE].mode), SD_BUS_VTABLE_PROPERTY_CONST),
1283         SD_BUS_PROPERTY("StateDirectory", "as", bus_property_get_exec_dir, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE]), SD_BUS_VTABLE_PROPERTY_CONST),
1284         SD_BUS_PROPERTY("CacheDirectorySymlink", "a(sst)", bus_property_get_exec_dir_symlink, offsetof(ExecContext, directories[EXEC_DIRECTORY_CACHE]), SD_BUS_VTABLE_PROPERTY_CONST),
1285         SD_BUS_PROPERTY("CacheDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_CACHE].mode), SD_BUS_VTABLE_PROPERTY_CONST),
1286         SD_BUS_PROPERTY("CacheDirectory", "as", bus_property_get_exec_dir, offsetof(ExecContext, directories[EXEC_DIRECTORY_CACHE]), SD_BUS_VTABLE_PROPERTY_CONST),
1287         SD_BUS_PROPERTY("LogsDirectorySymlink", "a(sst)", bus_property_get_exec_dir_symlink, offsetof(ExecContext, directories[EXEC_DIRECTORY_LOGS]), SD_BUS_VTABLE_PROPERTY_CONST),
1288         SD_BUS_PROPERTY("LogsDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_LOGS].mode), SD_BUS_VTABLE_PROPERTY_CONST),
1289         SD_BUS_PROPERTY("LogsDirectory", "as", bus_property_get_exec_dir, offsetof(ExecContext, directories[EXEC_DIRECTORY_LOGS]), SD_BUS_VTABLE_PROPERTY_CONST),
1290         SD_BUS_PROPERTY("ConfigurationDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_CONFIGURATION].mode), SD_BUS_VTABLE_PROPERTY_CONST),
1291         SD_BUS_PROPERTY("ConfigurationDirectory", "as", bus_property_get_exec_dir, offsetof(ExecContext, directories[EXEC_DIRECTORY_CONFIGURATION]), SD_BUS_VTABLE_PROPERTY_CONST),
1292         SD_BUS_PROPERTY("TimeoutCleanUSec", "t", bus_property_get_usec, offsetof(ExecContext, timeout_clean_usec), SD_BUS_VTABLE_PROPERTY_CONST),
1293         SD_BUS_PROPERTY("MemoryDenyWriteExecute", "b", bus_property_get_bool, offsetof(ExecContext, memory_deny_write_execute), SD_BUS_VTABLE_PROPERTY_CONST),
1294         SD_BUS_PROPERTY("RestrictRealtime", "b", bus_property_get_bool, offsetof(ExecContext, restrict_realtime), SD_BUS_VTABLE_PROPERTY_CONST),
1295         SD_BUS_PROPERTY("RestrictSUIDSGID", "b", bus_property_get_bool, offsetof(ExecContext, restrict_suid_sgid), SD_BUS_VTABLE_PROPERTY_CONST),
1296         SD_BUS_PROPERTY("RestrictNamespaces", "t", bus_property_get_ulong, offsetof(ExecContext, restrict_namespaces), SD_BUS_VTABLE_PROPERTY_CONST),
1297         SD_BUS_PROPERTY("RestrictFileSystems", "(bas)", property_get_restrict_filesystems, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1298         SD_BUS_PROPERTY("BindPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1299         SD_BUS_PROPERTY("BindReadOnlyPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1300         SD_BUS_PROPERTY("TemporaryFileSystem", "a(ss)", property_get_temporary_filesystems, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1301         SD_BUS_PROPERTY("MountAPIVFS", "b", property_get_mount_apivfs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1302         SD_BUS_PROPERTY("KeyringMode", "s", property_get_exec_keyring_mode, offsetof(ExecContext, keyring_mode), SD_BUS_VTABLE_PROPERTY_CONST),
1303         SD_BUS_PROPERTY("ProtectProc", "s", property_get_protect_proc, offsetof(ExecContext, protect_proc), SD_BUS_VTABLE_PROPERTY_CONST),
1304         SD_BUS_PROPERTY("ProcSubset", "s", property_get_proc_subset, offsetof(ExecContext, proc_subset), SD_BUS_VTABLE_PROPERTY_CONST),
1305         SD_BUS_PROPERTY("ProtectHostname", "b", bus_property_get_bool, offsetof(ExecContext, protect_hostname), SD_BUS_VTABLE_PROPERTY_CONST),
1306         SD_BUS_PROPERTY("NetworkNamespacePath", "s", NULL, offsetof(ExecContext, network_namespace_path), SD_BUS_VTABLE_PROPERTY_CONST),
1307         SD_BUS_PROPERTY("IPCNamespacePath", "s", NULL, offsetof(ExecContext, ipc_namespace_path), SD_BUS_VTABLE_PROPERTY_CONST),
1308 
1309         /* Obsolete/redundant properties: */
1310         SD_BUS_PROPERTY("Capabilities", "s", property_get_empty_string, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
1311         SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
1312         SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
1313         SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
1314         SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
1315 
1316         SD_BUS_VTABLE_END
1317 };
1318 
append_exec_command(sd_bus_message * reply,ExecCommand * c)1319 static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
1320         int r;
1321 
1322         assert(reply);
1323         assert(c);
1324 
1325         if (!c->path)
1326                 return 0;
1327 
1328         r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
1329         if (r < 0)
1330                 return r;
1331 
1332         r = sd_bus_message_append(reply, "s", c->path);
1333         if (r < 0)
1334                 return r;
1335 
1336         r = sd_bus_message_append_strv(reply, c->argv);
1337         if (r < 0)
1338                 return r;
1339 
1340         r = sd_bus_message_append(reply, "bttttuii",
1341                                   !!(c->flags & EXEC_COMMAND_IGNORE_FAILURE),
1342                                   c->exec_status.start_timestamp.realtime,
1343                                   c->exec_status.start_timestamp.monotonic,
1344                                   c->exec_status.exit_timestamp.realtime,
1345                                   c->exec_status.exit_timestamp.monotonic,
1346                                   (uint32_t) c->exec_status.pid,
1347                                   (int32_t) c->exec_status.code,
1348                                   (int32_t) c->exec_status.status);
1349         if (r < 0)
1350                 return r;
1351 
1352         return sd_bus_message_close_container(reply);
1353 }
1354 
append_exec_ex_command(sd_bus_message * reply,ExecCommand * c)1355 static int append_exec_ex_command(sd_bus_message *reply, ExecCommand *c) {
1356         _cleanup_strv_free_ char **ex_opts = NULL;
1357         int r;
1358 
1359         assert(reply);
1360         assert(c);
1361 
1362         if (!c->path)
1363                 return 0;
1364 
1365         r = sd_bus_message_open_container(reply, 'r', "sasasttttuii");
1366         if (r < 0)
1367                 return r;
1368 
1369         r = sd_bus_message_append(reply, "s", c->path);
1370         if (r < 0)
1371                 return r;
1372 
1373         r = sd_bus_message_append_strv(reply, c->argv);
1374         if (r < 0)
1375                 return r;
1376 
1377         r = exec_command_flags_to_strv(c->flags, &ex_opts);
1378         if (r < 0)
1379                 return r;
1380 
1381         r = sd_bus_message_append_strv(reply, ex_opts);
1382         if (r < 0)
1383                 return r;
1384 
1385         r = sd_bus_message_append(reply, "ttttuii",
1386                                   c->exec_status.start_timestamp.realtime,
1387                                   c->exec_status.start_timestamp.monotonic,
1388                                   c->exec_status.exit_timestamp.realtime,
1389                                   c->exec_status.exit_timestamp.monotonic,
1390                                   (uint32_t) c->exec_status.pid,
1391                                   (int32_t) c->exec_status.code,
1392                                   (int32_t) c->exec_status.status);
1393         if (r < 0)
1394                 return r;
1395 
1396         return sd_bus_message_close_container(reply);
1397 }
1398 
bus_property_get_exec_command(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * ret_error)1399 int bus_property_get_exec_command(
1400                 sd_bus *bus,
1401                 const char *path,
1402                 const char *interface,
1403                 const char *property,
1404                 sd_bus_message *reply,
1405                 void *userdata,
1406                 sd_bus_error *ret_error) {
1407 
1408         ExecCommand *c = (ExecCommand*) userdata;
1409         int r;
1410 
1411         assert(bus);
1412         assert(reply);
1413 
1414         r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
1415         if (r < 0)
1416                 return r;
1417 
1418         r = append_exec_command(reply, c);
1419         if (r < 0)
1420                 return r;
1421 
1422         return sd_bus_message_close_container(reply);
1423 }
1424 
bus_property_get_exec_command_list(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * ret_error)1425 int bus_property_get_exec_command_list(
1426                 sd_bus *bus,
1427                 const char *path,
1428                 const char *interface,
1429                 const char *property,
1430                 sd_bus_message *reply,
1431                 void *userdata,
1432                 sd_bus_error *ret_error) {
1433 
1434         ExecCommand *exec_command = *(ExecCommand**) userdata;
1435         int r;
1436 
1437         assert(bus);
1438         assert(reply);
1439 
1440         r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
1441         if (r < 0)
1442                 return r;
1443 
1444         LIST_FOREACH(command, c, exec_command) {
1445                 r = append_exec_command(reply, c);
1446                 if (r < 0)
1447                         return r;
1448         }
1449 
1450         return sd_bus_message_close_container(reply);
1451 }
1452 
bus_property_get_exec_ex_command_list(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * ret_error)1453 int bus_property_get_exec_ex_command_list(
1454                 sd_bus *bus,
1455                 const char *path,
1456                 const char *interface,
1457                 const char *property,
1458                 sd_bus_message *reply,
1459                 void *userdata,
1460                 sd_bus_error *ret_error) {
1461 
1462         ExecCommand *exec_command = *(ExecCommand**) userdata;
1463         int r;
1464 
1465         assert(bus);
1466         assert(reply);
1467 
1468         r = sd_bus_message_open_container(reply, 'a', "(sasasttttuii)");
1469         if (r < 0)
1470                 return r;
1471 
1472         LIST_FOREACH(command, c, exec_command) {
1473                 r = append_exec_ex_command(reply, c);
1474                 if (r < 0)
1475                         return r;
1476         }
1477 
1478         return sd_bus_message_close_container(reply);
1479 }
1480 
exec_command_flags_to_exec_chars(ExecCommandFlags flags)1481 static char *exec_command_flags_to_exec_chars(ExecCommandFlags flags) {
1482         return strjoin(FLAGS_SET(flags, EXEC_COMMAND_IGNORE_FAILURE)   ? "-" : "",
1483                        FLAGS_SET(flags, EXEC_COMMAND_NO_ENV_EXPAND)    ? ":" : "",
1484                        FLAGS_SET(flags, EXEC_COMMAND_FULLY_PRIVILEGED) ? "+" : "",
1485                        FLAGS_SET(flags, EXEC_COMMAND_NO_SETUID)        ? "!" : "",
1486                        FLAGS_SET(flags, EXEC_COMMAND_AMBIENT_MAGIC)    ? "!!" : "");
1487 }
1488 
bus_set_transient_exec_command(Unit * u,const char * name,ExecCommand ** exec_command,sd_bus_message * message,UnitWriteFlags flags,sd_bus_error * error)1489 int bus_set_transient_exec_command(
1490                 Unit *u,
1491                 const char *name,
1492                 ExecCommand **exec_command,
1493                 sd_bus_message *message,
1494                 UnitWriteFlags flags,
1495                 sd_bus_error *error) {
1496         bool is_ex_prop = endswith(name, "Ex");
1497         unsigned n = 0;
1498         int r;
1499 
1500         r = sd_bus_message_enter_container(message, 'a', is_ex_prop ? "(sasas)" : "(sasb)");
1501         if (r < 0)
1502                 return r;
1503 
1504         while ((r = sd_bus_message_enter_container(message, 'r', is_ex_prop ? "sasas" : "sasb")) > 0) {
1505                 _cleanup_strv_free_ char **argv = NULL, **ex_opts = NULL;
1506                 const char *path;
1507                 int b;
1508 
1509                 r = sd_bus_message_read(message, "s", &path);
1510                 if (r < 0)
1511                         return r;
1512 
1513                 if (!path_is_absolute(path) && !filename_is_valid(path))
1514                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
1515                                                  "\"%s\" is neither a valid executable name nor an absolute path",
1516                                                  path);
1517 
1518                 r = sd_bus_message_read_strv(message, &argv);
1519                 if (r < 0)
1520                         return r;
1521 
1522                 if (strv_isempty(argv))
1523                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
1524                                                  "\"%s\" argv cannot be empty", name);
1525 
1526                 r = is_ex_prop ? sd_bus_message_read_strv(message, &ex_opts) : sd_bus_message_read(message, "b", &b);
1527                 if (r < 0)
1528                         return r;
1529 
1530                 r = sd_bus_message_exit_container(message);
1531                 if (r < 0)
1532                         return r;
1533 
1534                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1535                         ExecCommand *c;
1536 
1537                         c = new0(ExecCommand, 1);
1538                         if (!c)
1539                                 return -ENOMEM;
1540 
1541                         c->path = strdup(path);
1542                         if (!c->path) {
1543                                 free(c);
1544                                 return -ENOMEM;
1545                         }
1546 
1547                         c->argv = TAKE_PTR(argv);
1548 
1549                         if (is_ex_prop) {
1550                                 r = exec_command_flags_from_strv(ex_opts, &c->flags);
1551                                 if (r < 0)
1552                                         return r;
1553                         } else
1554                                 c->flags = b ? EXEC_COMMAND_IGNORE_FAILURE : 0;
1555 
1556                         path_simplify(c->path);
1557                         exec_command_append_list(exec_command, c);
1558                 }
1559 
1560                 n++;
1561         }
1562         if (r < 0)
1563                 return r;
1564 
1565         r = sd_bus_message_exit_container(message);
1566         if (r < 0)
1567                 return r;
1568 
1569         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1570                 _cleanup_free_ char *buf = NULL;
1571                 _cleanup_fclose_ FILE *f = NULL;
1572                 size_t size = 0;
1573 
1574                 if (n == 0)
1575                         *exec_command = exec_command_free_list(*exec_command);
1576 
1577                 f = open_memstream_unlocked(&buf, &size);
1578                 if (!f)
1579                         return -ENOMEM;
1580 
1581                 fprintf(f, "%s=\n", name);
1582 
1583                 LIST_FOREACH(command, c, *exec_command) {
1584                         _cleanup_free_ char *a = NULL, *exec_chars = NULL;
1585 
1586                         exec_chars = exec_command_flags_to_exec_chars(c->flags);
1587                         if (!exec_chars)
1588                                 return -ENOMEM;
1589 
1590                         a = unit_concat_strv(c->argv, UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS);
1591                         if (!a)
1592                                 return -ENOMEM;
1593 
1594                         if (streq_ptr(c->path, c->argv ? c->argv[0] : NULL))
1595                                 fprintf(f, "%s=%s%s\n", name, exec_chars, a);
1596                         else {
1597                                 _cleanup_free_ char *t = NULL;
1598                                 const char *p;
1599 
1600                                 p = unit_escape_setting(c->path, UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS, &t);
1601                                 if (!p)
1602                                         return -ENOMEM;
1603 
1604                                 fprintf(f, "%s=%s@%s %s\n", name, exec_chars, p, a);
1605                         }
1606                 }
1607 
1608                 r = fflush_and_check(f);
1609                 if (r < 0)
1610                         return r;
1611 
1612                 unit_write_setting(u, flags, name, buf);
1613         }
1614 
1615         return 1;
1616 }
1617 
parse_personality(const char * s,unsigned long * p)1618 static int parse_personality(const char *s, unsigned long *p) {
1619         unsigned long v;
1620 
1621         assert(p);
1622 
1623         v = personality_from_string(s);
1624         if (v == PERSONALITY_INVALID)
1625                 return -EINVAL;
1626 
1627         *p = v;
1628         return 0;
1629 }
1630 
mount_propagation_flags_to_string_with_check(unsigned long n)1631 static const char* mount_propagation_flags_to_string_with_check(unsigned long n) {
1632         if (!IN_SET(n, 0, MS_SHARED, MS_PRIVATE, MS_SLAVE))
1633                 return NULL;
1634 
1635         return mount_propagation_flags_to_string(n);
1636 }
1637 
1638 static BUS_DEFINE_SET_TRANSIENT(nsec, "t", uint64_t, nsec_t, NSEC_FMT);
1639 static BUS_DEFINE_SET_TRANSIENT_IS_VALID(log_level, "i", int32_t, int, "%" PRIi32, log_level_is_valid);
1640 #if HAVE_SECCOMP
1641 static BUS_DEFINE_SET_TRANSIENT_IS_VALID(errno, "i", int32_t, int, "%" PRIi32, seccomp_errno_or_action_is_valid);
1642 #endif
1643 static BUS_DEFINE_SET_TRANSIENT_PARSE(std_input, ExecInput, exec_input_from_string);
1644 static BUS_DEFINE_SET_TRANSIENT_PARSE(std_output, ExecOutput, exec_output_from_string);
1645 static BUS_DEFINE_SET_TRANSIENT_PARSE(utmp_mode, ExecUtmpMode, exec_utmp_mode_from_string);
1646 static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_system, ProtectSystem, protect_system_from_string);
1647 static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_home, ProtectHome, protect_home_from_string);
1648 static BUS_DEFINE_SET_TRANSIENT_PARSE(keyring_mode, ExecKeyringMode, exec_keyring_mode_from_string);
1649 static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_proc, ProtectProc, protect_proc_from_string);
1650 static BUS_DEFINE_SET_TRANSIENT_PARSE(proc_subset, ProcSubset, proc_subset_from_string);
1651 static BUS_DEFINE_SET_TRANSIENT_PARSE(preserve_mode, ExecPreserveMode, exec_preserve_mode_from_string);
1652 static BUS_DEFINE_SET_TRANSIENT_PARSE_PTR(personality, unsigned long, parse_personality);
1653 static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(secure_bits, "i", int32_t, int, "%" PRIi32, secure_bits_to_string_alloc_with_check);
1654 static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(capability, "t", uint64_t, uint64_t, "%" PRIu64, capability_set_to_string_alloc);
1655 static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(namespace_flag, "t", uint64_t, unsigned long, "%" PRIu64, namespace_flags_to_string);
1656 static BUS_DEFINE_SET_TRANSIENT_TO_STRING(mount_flags, "t", uint64_t, unsigned long, "%" PRIu64, mount_propagation_flags_to_string_with_check);
1657 
bus_exec_context_set_transient_property(Unit * u,ExecContext * c,const char * name,sd_bus_message * message,UnitWriteFlags flags,sd_bus_error * error)1658 int bus_exec_context_set_transient_property(
1659                 Unit *u,
1660                 ExecContext *c,
1661                 const char *name,
1662                 sd_bus_message *message,
1663                 UnitWriteFlags flags,
1664                 sd_bus_error *error) {
1665 
1666         const char *suffix;
1667         int r;
1668 
1669         assert(u);
1670         assert(c);
1671         assert(name);
1672         assert(message);
1673 
1674         flags |= UNIT_PRIVATE;
1675 
1676         if (streq(name, "User"))
1677                 return bus_set_transient_user_relaxed(u, name, &c->user, message, flags, error);
1678 
1679         if (streq(name, "Group"))
1680                 return bus_set_transient_user_relaxed(u, name, &c->group, message, flags, error);
1681 
1682         if (streq(name, "TTYPath"))
1683                 return bus_set_transient_path(u, name, &c->tty_path, message, flags, error);
1684 
1685         if (streq(name, "RootImage"))
1686                 return bus_set_transient_path(u, name, &c->root_image, message, flags, error);
1687 
1688         if (streq(name, "RootImageOptions")) {
1689                 _cleanup_(mount_options_free_allp) MountOptions *options = NULL;
1690                 _cleanup_free_ char *format_str = NULL;
1691 
1692                 r = bus_read_mount_options(message, error, &options, &format_str, " ");
1693                 if (r < 0)
1694                         return r;
1695 
1696                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1697                         if (LIST_IS_EMPTY(options)) {
1698                                 c->root_image_options = mount_options_free_all(c->root_image_options);
1699                                 unit_write_settingf(u, flags, name, "%s=", name);
1700                         } else {
1701                                 LIST_JOIN(mount_options, c->root_image_options, options);
1702                                 unit_write_settingf(
1703                                                 u, flags|UNIT_ESCAPE_SPECIFIERS, name,
1704                                                 "%s=%s",
1705                                                 name,
1706                                                 format_str);
1707                         }
1708                 }
1709 
1710                 return 1;
1711         }
1712 
1713         if (streq(name, "RootHash")) {
1714                 const void *roothash_decoded;
1715                 size_t roothash_decoded_size;
1716 
1717                 r = sd_bus_message_read_array(message, 'y', &roothash_decoded, &roothash_decoded_size);
1718                 if (r < 0)
1719                         return r;
1720 
1721                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1722                         _cleanup_free_ char *encoded = NULL;
1723 
1724                         if (roothash_decoded_size == 0) {
1725                                 c->root_hash_path = mfree(c->root_hash_path);
1726                                 c->root_hash = mfree(c->root_hash);
1727                                 c->root_hash_size = 0;
1728 
1729                                 unit_write_settingf(u, flags, name, "RootHash=");
1730                         } else {
1731                                 _cleanup_free_ void *p = NULL;
1732 
1733                                 encoded = hexmem(roothash_decoded, roothash_decoded_size);
1734                                 if (!encoded)
1735                                         return -ENOMEM;
1736 
1737                                 p = memdup(roothash_decoded, roothash_decoded_size);
1738                                 if (!p)
1739                                         return -ENOMEM;
1740 
1741                                 free_and_replace(c->root_hash, p);
1742                                 c->root_hash_size = roothash_decoded_size;
1743                                 c->root_hash_path = mfree(c->root_hash_path);
1744 
1745                                 unit_write_settingf(u, flags, name, "RootHash=%s", encoded);
1746                         }
1747                 }
1748 
1749                 return 1;
1750         }
1751 
1752         if (streq(name, "RootHashPath")) {
1753                 c->root_hash_size = 0;
1754                 c->root_hash = mfree(c->root_hash);
1755 
1756                 return bus_set_transient_path(u, "RootHash", &c->root_hash_path, message, flags, error);
1757         }
1758 
1759         if (streq(name, "RootHashSignature")) {
1760                 const void *roothash_sig_decoded;
1761                 size_t roothash_sig_decoded_size;
1762 
1763                 r = sd_bus_message_read_array(message, 'y', &roothash_sig_decoded, &roothash_sig_decoded_size);
1764                 if (r < 0)
1765                         return r;
1766 
1767                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1768                         _cleanup_free_ char *encoded = NULL;
1769 
1770                         if (roothash_sig_decoded_size == 0) {
1771                                 c->root_hash_sig_path = mfree(c->root_hash_sig_path);
1772                                 c->root_hash_sig = mfree(c->root_hash_sig);
1773                                 c->root_hash_sig_size = 0;
1774 
1775                                 unit_write_settingf(u, flags, name, "RootHashSignature=");
1776                         } else {
1777                                 _cleanup_free_ void *p = NULL;
1778                                 ssize_t len;
1779 
1780                                 len = base64mem(roothash_sig_decoded, roothash_sig_decoded_size, &encoded);
1781                                 if (len < 0)
1782                                         return -ENOMEM;
1783 
1784                                 p = memdup(roothash_sig_decoded, roothash_sig_decoded_size);
1785                                 if (!p)
1786                                         return -ENOMEM;
1787 
1788                                 free_and_replace(c->root_hash_sig, p);
1789                                 c->root_hash_sig_size = roothash_sig_decoded_size;
1790                                 c->root_hash_sig_path = mfree(c->root_hash_sig_path);
1791 
1792                                 unit_write_settingf(u, flags, name, "RootHashSignature=base64:%s", encoded);
1793                         }
1794                 }
1795 
1796                 return 1;
1797         }
1798 
1799         if (streq(name, "RootHashSignaturePath")) {
1800                 c->root_hash_sig_size = 0;
1801                 c->root_hash_sig = mfree(c->root_hash_sig);
1802 
1803                 return bus_set_transient_path(u, "RootHashSignature", &c->root_hash_sig_path, message, flags, error);
1804         }
1805 
1806         if (streq(name, "RootVerity"))
1807                 return bus_set_transient_path(u, name, &c->root_verity, message, flags, error);
1808 
1809         if (streq(name, "RootDirectory"))
1810                 return bus_set_transient_path(u, name, &c->root_directory, message, flags, error);
1811 
1812         if (streq(name, "SyslogIdentifier"))
1813                 return bus_set_transient_string(u, name, &c->syslog_identifier, message, flags, error);
1814 
1815         if (streq(name, "LogLevelMax"))
1816                 return bus_set_transient_log_level(u, name, &c->log_level_max, message, flags, error);
1817 
1818         if (streq(name, "LogRateLimitIntervalUSec"))
1819                 return bus_set_transient_usec(u, name, &c->log_ratelimit_interval_usec, message, flags, error);
1820 
1821         if (streq(name, "LogRateLimitBurst"))
1822                 return bus_set_transient_unsigned(u, name, &c->log_ratelimit_burst, message, flags, error);
1823 
1824         if (streq(name, "Personality"))
1825                 return bus_set_transient_personality(u, name, &c->personality, message, flags, error);
1826 
1827         if (streq(name, "StandardInput"))
1828                 return bus_set_transient_std_input(u, name, &c->std_input, message, flags, error);
1829 
1830         if (streq(name, "StandardOutput"))
1831                 return bus_set_transient_std_output(u, name, &c->std_output, message, flags, error);
1832 
1833         if (streq(name, "StandardError"))
1834                 return bus_set_transient_std_output(u, name, &c->std_error, message, flags, error);
1835 
1836         if (streq(name, "IgnoreSIGPIPE"))
1837                 return bus_set_transient_bool(u, name, &c->ignore_sigpipe, message, flags, error);
1838 
1839         if (streq(name, "TTYVHangup"))
1840                 return bus_set_transient_bool(u, name, &c->tty_vhangup, message, flags, error);
1841 
1842         if (streq(name, "TTYReset"))
1843                 return bus_set_transient_bool(u, name, &c->tty_reset, message, flags, error);
1844 
1845         if (streq(name, "TTYVTDisallocate"))
1846                 return bus_set_transient_bool(u, name, &c->tty_vt_disallocate, message, flags, error);
1847 
1848         if (streq(name, "TTYRows"))
1849                 return bus_set_transient_unsigned(u, name, &c->tty_rows, message, flags, error);
1850 
1851         if (streq(name, "TTYColumns"))
1852                 return bus_set_transient_unsigned(u, name, &c->tty_cols, message, flags, error);
1853 
1854         if (streq(name, "PrivateTmp"))
1855                 return bus_set_transient_bool(u, name, &c->private_tmp, message, flags, error);
1856 
1857         if (streq(name, "PrivateDevices"))
1858                 return bus_set_transient_bool(u, name, &c->private_devices, message, flags, error);
1859 
1860         if (streq(name, "PrivateMounts"))
1861                 return bus_set_transient_bool(u, name, &c->private_mounts, message, flags, error);
1862 
1863         if (streq(name, "PrivateNetwork"))
1864                 return bus_set_transient_bool(u, name, &c->private_network, message, flags, error);
1865 
1866         if (streq(name, "PrivateIPC"))
1867                 return bus_set_transient_bool(u, name, &c->private_ipc, message, flags, error);
1868 
1869         if (streq(name, "PrivateUsers"))
1870                 return bus_set_transient_bool(u, name, &c->private_users, message, flags, error);
1871 
1872         if (streq(name, "NoNewPrivileges"))
1873                 return bus_set_transient_bool(u, name, &c->no_new_privileges, message, flags, error);
1874 
1875         if (streq(name, "SyslogLevelPrefix"))
1876                 return bus_set_transient_bool(u, name, &c->syslog_level_prefix, message, flags, error);
1877 
1878         if (streq(name, "MemoryDenyWriteExecute"))
1879                 return bus_set_transient_bool(u, name, &c->memory_deny_write_execute, message, flags, error);
1880 
1881         if (streq(name, "RestrictRealtime"))
1882                 return bus_set_transient_bool(u, name, &c->restrict_realtime, message, flags, error);
1883 
1884         if (streq(name, "RestrictSUIDSGID"))
1885                 return bus_set_transient_bool(u, name, &c->restrict_suid_sgid, message, flags, error);
1886 
1887         if (streq(name, "DynamicUser"))
1888                 return bus_set_transient_bool(u, name, &c->dynamic_user, message, flags, error);
1889 
1890         if (streq(name, "RemoveIPC"))
1891                 return bus_set_transient_bool(u, name, &c->remove_ipc, message, flags, error);
1892 
1893         if (streq(name, "ProtectKernelTunables"))
1894                 return bus_set_transient_bool(u, name, &c->protect_kernel_tunables, message, flags, error);
1895 
1896         if (streq(name, "ProtectKernelModules"))
1897                 return bus_set_transient_bool(u, name, &c->protect_kernel_modules, message, flags, error);
1898 
1899         if (streq(name, "ProtectKernelLogs"))
1900                 return bus_set_transient_bool(u, name, &c->protect_kernel_logs, message, flags, error);
1901 
1902         if (streq(name, "ProtectClock"))
1903                 return bus_set_transient_bool(u, name, &c->protect_clock, message, flags, error);
1904 
1905         if (streq(name, "ProtectControlGroups"))
1906                 return bus_set_transient_bool(u, name, &c->protect_control_groups, message, flags, error);
1907 
1908         if (streq(name, "CPUSchedulingResetOnFork"))
1909                 return bus_set_transient_bool(u, name, &c->cpu_sched_reset_on_fork, message, flags, error);
1910 
1911         if (streq(name, "NonBlocking"))
1912                 return bus_set_transient_bool(u, name, &c->non_blocking, message, flags, error);
1913 
1914         if (streq(name, "LockPersonality"))
1915                 return bus_set_transient_bool(u, name, &c->lock_personality, message, flags, error);
1916 
1917         if (streq(name, "ProtectHostname"))
1918                 return bus_set_transient_bool(u, name, &c->protect_hostname, message, flags, error);
1919 
1920         if (streq(name, "UtmpIdentifier"))
1921                 return bus_set_transient_string(u, name, &c->utmp_id, message, flags, error);
1922 
1923         if (streq(name, "UtmpMode"))
1924                 return bus_set_transient_utmp_mode(u, name, &c->utmp_mode, message, flags, error);
1925 
1926         if (streq(name, "PAMName"))
1927                 return bus_set_transient_string(u, name, &c->pam_name, message, flags, error);
1928 
1929         if (streq(name, "TimerSlackNSec"))
1930                 return bus_set_transient_nsec(u, name, &c->timer_slack_nsec, message, flags, error);
1931 
1932         if (streq(name, "ProtectSystem"))
1933                 return bus_set_transient_protect_system(u, name, &c->protect_system, message, flags, error);
1934 
1935         if (streq(name, "ProtectHome"))
1936                 return bus_set_transient_protect_home(u, name, &c->protect_home, message, flags, error);
1937 
1938         if (streq(name, "KeyringMode"))
1939                 return bus_set_transient_keyring_mode(u, name, &c->keyring_mode, message, flags, error);
1940 
1941         if (streq(name, "ProtectProc"))
1942                 return bus_set_transient_protect_proc(u, name, &c->protect_proc, message, flags, error);
1943 
1944         if (streq(name, "ProcSubset"))
1945                 return bus_set_transient_proc_subset(u, name, &c->proc_subset, message, flags, error);
1946 
1947         if (streq(name, "RuntimeDirectoryPreserve"))
1948                 return bus_set_transient_preserve_mode(u, name, &c->runtime_directory_preserve_mode, message, flags, error);
1949 
1950         if (streq(name, "UMask"))
1951                 return bus_set_transient_mode_t(u, name, &c->umask, message, flags, error);
1952 
1953         if (streq(name, "RuntimeDirectoryMode"))
1954                 return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_RUNTIME].mode, message, flags, error);
1955 
1956         if (streq(name, "StateDirectoryMode"))
1957                 return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_STATE].mode, message, flags, error);
1958 
1959         if (streq(name, "CacheDirectoryMode"))
1960                 return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_CACHE].mode, message, flags, error);
1961 
1962         if (streq(name, "LogsDirectoryMode"))
1963                 return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_LOGS].mode, message, flags, error);
1964 
1965         if (streq(name, "ConfigurationDirectoryMode"))
1966                 return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_CONFIGURATION].mode, message, flags, error);
1967 
1968         if (streq(name, "SELinuxContext"))
1969                 return bus_set_transient_string(u, name, &c->selinux_context, message, flags, error);
1970 
1971         if (streq(name, "SecureBits"))
1972                 return bus_set_transient_secure_bits(u, name, &c->secure_bits, message, flags, error);
1973 
1974         if (streq(name, "CapabilityBoundingSet"))
1975                 return bus_set_transient_capability(u, name, &c->capability_bounding_set, message, flags, error);
1976 
1977         if (streq(name, "AmbientCapabilities"))
1978                 return bus_set_transient_capability(u, name, &c->capability_ambient_set, message, flags, error);
1979 
1980         if (streq(name, "RestrictNamespaces"))
1981                 return bus_set_transient_namespace_flag(u, name, &c->restrict_namespaces, message, flags, error);
1982 
1983         if (streq(name, "RestrictFileSystems")) {
1984                 int allow_list;
1985                 _cleanup_strv_free_ char **l = NULL;
1986 
1987                 r = sd_bus_message_enter_container(message, 'r', "bas");
1988                 if (r < 0)
1989                         return r;
1990 
1991                 r = sd_bus_message_read(message, "b", &allow_list);
1992                 if (r < 0)
1993                         return r;
1994 
1995                 r = sd_bus_message_read_strv(message, &l);
1996                 if (r < 0)
1997                         return r;
1998 
1999                 r = sd_bus_message_exit_container(message);
2000                 if (r < 0)
2001                         return r;
2002 
2003                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2004                         _cleanup_free_ char *joined = NULL;
2005                         FilesystemParseFlags invert_flag = allow_list ? 0 : FILESYSTEM_PARSE_INVERT;
2006 
2007                         if (strv_isempty(l)) {
2008                                 c->restrict_filesystems_allow_list = false;
2009                                 c->restrict_filesystems = set_free(c->restrict_filesystems);
2010 
2011                                 unit_write_setting(u, flags, name, "RestrictFileSystems=");
2012                                 return 1;
2013                         }
2014 
2015                         if (!c->restrict_filesystems)
2016                                 c->restrict_filesystems_allow_list = allow_list;
2017 
2018                         STRV_FOREACH(s, l) {
2019                                 r = lsm_bpf_parse_filesystem(
2020                                               *s,
2021                                               &c->restrict_filesystems,
2022                                               FILESYSTEM_PARSE_LOG|
2023                                               (invert_flag ? FILESYSTEM_PARSE_INVERT : 0)|
2024                                               (c->restrict_filesystems_allow_list ? FILESYSTEM_PARSE_ALLOW_LIST : 0),
2025                                               u->id, NULL, 0);
2026                                 if (r < 0)
2027                                         return r;
2028                         }
2029 
2030                         joined = strv_join(l, " ");
2031                         if (!joined)
2032                                 return -ENOMEM;
2033 
2034                         unit_write_settingf(u, flags, name, "%s=%s%s", name, allow_list ? "" : "~", joined);
2035                 }
2036 
2037                 return 1;
2038         }
2039 
2040         if (streq(name, "MountFlags"))
2041                 return bus_set_transient_mount_flags(u, name, &c->mount_flags, message, flags, error);
2042 
2043         if (streq(name, "NetworkNamespacePath"))
2044                 return bus_set_transient_path(u, name, &c->network_namespace_path, message, flags, error);
2045 
2046         if (streq(name, "IPCNamespacePath"))
2047                 return bus_set_transient_path(u, name, &c->ipc_namespace_path, message, flags, error);
2048 
2049         if (streq(name, "SupplementaryGroups")) {
2050                 _cleanup_strv_free_ char **l = NULL;
2051 
2052                 r = sd_bus_message_read_strv(message, &l);
2053                 if (r < 0)
2054                         return r;
2055 
2056                 STRV_FOREACH(p, l)
2057                         if (!isempty(*p) && !valid_user_group_name(*p, VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX|VALID_USER_WARN))
2058                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
2059                                                          "Invalid supplementary group names");
2060 
2061                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2062                         if (strv_isempty(l)) {
2063                                 c->supplementary_groups = strv_free(c->supplementary_groups);
2064                                 unit_write_settingf(u, flags, name, "%s=", name);
2065                         } else {
2066                                 _cleanup_free_ char *joined = NULL;
2067 
2068                                 r = strv_extend_strv(&c->supplementary_groups, l, true);
2069                                 if (r < 0)
2070                                         return -ENOMEM;
2071 
2072                                 joined = strv_join(c->supplementary_groups, " ");
2073                                 if (!joined)
2074                                         return -ENOMEM;
2075 
2076                                 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, joined);
2077                         }
2078                 }
2079 
2080                 return 1;
2081 
2082         } else if (STR_IN_SET(name, "SetCredential", "SetCredentialEncrypted")) {
2083                 bool isempty = true;
2084 
2085                 r = sd_bus_message_enter_container(message, 'a', "(say)");
2086                 if (r < 0)
2087                         return r;
2088 
2089                 for (;;) {
2090                         const char *id;
2091                         const void *p;
2092                         size_t sz;
2093 
2094                         r = sd_bus_message_enter_container(message, 'r', "say");
2095                         if (r < 0)
2096                                 return r;
2097                         if (r == 0)
2098                                 break;
2099 
2100                         r = sd_bus_message_read(message, "s", &id);
2101                         if (r < 0)
2102                                 return r;
2103 
2104                         r = sd_bus_message_read_array(message, 'y', &p, &sz);
2105                         if (r < 0)
2106                                 return r;
2107 
2108                         r = sd_bus_message_exit_container(message);
2109                         if (r < 0)
2110                                 return r;
2111 
2112                         if (!credential_name_valid(id))
2113                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Credential ID is invalid: %s", id);
2114 
2115                         isempty = false;
2116 
2117                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2118                                 _cleanup_free_ char *a = NULL, *b = NULL;
2119                                 _cleanup_free_ void *copy = NULL;
2120                                 ExecSetCredential *old;
2121 
2122                                 copy = memdup(p, sz);
2123                                 if (!copy)
2124                                         return -ENOMEM;
2125 
2126                                 old = hashmap_get(c->set_credentials, id);
2127                                 if (old) {
2128                                         free_and_replace(old->data, copy);
2129                                         old->size = sz;
2130                                         old->encrypted = streq(name, "SetCredentialEncrypted");
2131                                 } else {
2132                                         _cleanup_(exec_set_credential_freep) ExecSetCredential *sc = NULL;
2133 
2134                                         sc = new(ExecSetCredential, 1);
2135                                         if (!sc)
2136                                                 return -ENOMEM;
2137 
2138                                         *sc = (ExecSetCredential) {
2139                                                 .id = strdup(id),
2140                                                 .data = TAKE_PTR(copy),
2141                                                 .size = sz,
2142                                                 .encrypted = streq(name, "SetCredentialEncrypted"),
2143                                         };
2144 
2145                                         if (!sc->id)
2146                                                 return -ENOMEM;
2147 
2148                                         r = hashmap_ensure_put(&c->set_credentials, &exec_set_credential_hash_ops, sc->id, sc);
2149                                         if (r < 0)
2150                                                 return r;
2151 
2152                                         TAKE_PTR(sc);
2153                                 }
2154 
2155                                 a = specifier_escape(id);
2156                                 if (!a)
2157                                         return -ENOMEM;
2158 
2159                                 b = cescape_length(p, sz);
2160                                 if (!b)
2161                                         return -ENOMEM;
2162 
2163                                 (void) unit_write_settingf(u, flags, name, "%s=%s:%s", name, a, b);
2164                         }
2165                 }
2166 
2167                 r = sd_bus_message_exit_container(message);
2168                 if (r < 0)
2169                         return r;
2170 
2171                 if (!UNIT_WRITE_FLAGS_NOOP(flags) && isempty) {
2172                         c->set_credentials = hashmap_free(c->set_credentials);
2173                         (void) unit_write_settingf(u, flags, name, "%s=", name);
2174                 }
2175 
2176                 return 1;
2177 
2178         } else if (STR_IN_SET(name, "LoadCredential", "LoadCredentialEncrypted")) {
2179                 bool isempty = true;
2180 
2181                 r = sd_bus_message_enter_container(message, 'a', "(ss)");
2182                 if (r < 0)
2183                         return r;
2184 
2185                 for (;;) {
2186                         const char *id, *source;
2187 
2188                         r = sd_bus_message_read(message, "(ss)", &id, &source);
2189                         if (r < 0)
2190                                 return r;
2191                         if (r == 0)
2192                                 break;
2193 
2194                         if (!credential_name_valid(id))
2195                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Credential ID is invalid: %s", id);
2196 
2197                         if (!(path_is_absolute(source) ? path_is_normalized(source) : credential_name_valid(source)))
2198                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Credential source is invalid: %s", source);
2199 
2200                         isempty = false;
2201 
2202                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2203                                 _cleanup_free_ char *copy = NULL;
2204                                 ExecLoadCredential *old;
2205 
2206                                 copy = strdup(source);
2207                                 if (!copy)
2208                                         return -ENOMEM;
2209 
2210                                 old = hashmap_get(c->load_credentials, id);
2211                                 if (old) {
2212                                         free_and_replace(old->path, copy);
2213                                         old->encrypted = streq(name, "LoadCredentialEncrypted");
2214                                 } else {
2215                                         _cleanup_(exec_load_credential_freep) ExecLoadCredential *lc = NULL;
2216 
2217                                         lc = new(ExecLoadCredential, 1);
2218                                         if (!lc)
2219                                                 return -ENOMEM;
2220 
2221                                         *lc = (ExecLoadCredential) {
2222                                                 .id = strdup(id),
2223                                                 .path = TAKE_PTR(copy),
2224                                                 .encrypted = streq(name, "LoadCredentialEncrypted"),
2225                                         };
2226 
2227                                         if (!lc->id)
2228                                                 return -ENOMEM;
2229 
2230                                         r = hashmap_ensure_put(&c->load_credentials, &exec_load_credential_hash_ops, lc->id, lc);
2231                                         if (r < 0)
2232                                                 return r;
2233 
2234                                         TAKE_PTR(lc);
2235                                 }
2236 
2237                                 (void) unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s:%s", name, id, source);
2238                         }
2239                 }
2240 
2241                 r = sd_bus_message_exit_container(message);
2242                 if (r < 0)
2243                         return r;
2244 
2245                 if (!UNIT_WRITE_FLAGS_NOOP(flags) && isempty) {
2246                         c->load_credentials = hashmap_free(c->load_credentials);
2247                         (void) unit_write_settingf(u, flags, name, "%s=", name);
2248                 }
2249 
2250                 return 1;
2251 
2252         } else if (streq(name, "SyslogLevel")) {
2253                 int32_t level;
2254 
2255                 r = sd_bus_message_read(message, "i", &level);
2256                 if (r < 0)
2257                         return r;
2258 
2259                 if (!log_level_is_valid(level))
2260                         return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Log level value out of range");
2261 
2262                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2263                         c->syslog_priority = (c->syslog_priority & LOG_FACMASK) | level;
2264                         unit_write_settingf(u, flags, name, "SyslogLevel=%i", level);
2265                 }
2266 
2267                 return 1;
2268 
2269         } else if (streq(name, "SyslogFacility")) {
2270                 int32_t facility;
2271 
2272                 r = sd_bus_message_read(message, "i", &facility);
2273                 if (r < 0)
2274                         return r;
2275 
2276                 if (!log_facility_unshifted_is_valid(facility))
2277                         return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Log facility value out of range");
2278 
2279                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2280                         c->syslog_priority = (facility << 3) | LOG_PRI(c->syslog_priority);
2281                         unit_write_settingf(u, flags, name, "SyslogFacility=%i", facility);
2282                 }
2283 
2284                 return 1;
2285 
2286         } else if (streq(name, "LogNamespace")) {
2287                 const char *n;
2288 
2289                 r = sd_bus_message_read(message, "s", &n);
2290                 if (r < 0)
2291                         return r;
2292 
2293                 if (!isempty(n) && !log_namespace_name_valid(n))
2294                         return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Log namespace name not valid");
2295 
2296                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2297 
2298                         if (isempty(n)) {
2299                                 c->log_namespace = mfree(c->log_namespace);
2300                                 unit_write_settingf(u, flags, name, "%s=", name);
2301                         } else {
2302                                 r = free_and_strdup(&c->log_namespace, n);
2303                                 if (r < 0)
2304                                         return r;
2305 
2306                                 unit_write_settingf(u, flags, name, "%s=%s", name, n);
2307                         }
2308                 }
2309 
2310                 return 1;
2311 
2312         } else if (streq(name, "LogExtraFields")) {
2313                 size_t n = 0;
2314 
2315                 r = sd_bus_message_enter_container(message, 'a', "ay");
2316                 if (r < 0)
2317                         return r;
2318 
2319                 for (;;) {
2320                         _cleanup_free_ void *copy = NULL;
2321                         struct iovec *t;
2322                         const char *eq;
2323                         const void *p;
2324                         size_t sz;
2325 
2326                         /* Note that we expect a byte array for each field, instead of a string. That's because on the
2327                          * lower-level journal fields can actually contain binary data and are not restricted to text,
2328                          * and we should not "lose precision" in our types on the way. That said, I am pretty sure
2329                          * actually encoding binary data as unit metadata is not a good idea. Hence we actually refuse
2330                          * any actual binary data, and only accept UTF-8. This allows us to eventually lift this
2331                          * limitation, should a good, valid usecase arise. */
2332 
2333                         r = sd_bus_message_read_array(message, 'y', &p, &sz);
2334                         if (r < 0)
2335                                 return r;
2336                         if (r == 0)
2337                                 break;
2338 
2339                         if (memchr(p, 0, sz))
2340                                 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field contains zero byte");
2341 
2342                         eq = memchr(p, '=', sz);
2343                         if (!eq)
2344                                 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field contains no '=' character");
2345                         if (!journal_field_valid(p, eq - (const char*) p, false))
2346                                 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field invalid");
2347 
2348                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2349                                 t = reallocarray(c->log_extra_fields, c->n_log_extra_fields+1, sizeof(struct iovec));
2350                                 if (!t)
2351                                         return -ENOMEM;
2352                                 c->log_extra_fields = t;
2353                         }
2354 
2355                         copy = malloc(sz + 1);
2356                         if (!copy)
2357                                 return -ENOMEM;
2358 
2359                         memcpy(copy, p, sz);
2360                         ((uint8_t*) copy)[sz] = 0;
2361 
2362                         if (!utf8_is_valid(copy))
2363                                 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field is not valid UTF-8");
2364 
2365                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2366                                 c->log_extra_fields[c->n_log_extra_fields++] = IOVEC_MAKE(copy, sz);
2367                                 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS|UNIT_ESCAPE_C, name, "LogExtraFields=%s", (char*) copy);
2368 
2369                                 copy = NULL;
2370                         }
2371 
2372                         n++;
2373                 }
2374 
2375                 r = sd_bus_message_exit_container(message);
2376                 if (r < 0)
2377                         return r;
2378 
2379                 if (!UNIT_WRITE_FLAGS_NOOP(flags) && n == 0) {
2380                         exec_context_free_log_extra_fields(c);
2381                         unit_write_setting(u, flags, name, "LogExtraFields=");
2382                 }
2383 
2384                 return 1;
2385         }
2386 
2387 #if HAVE_SECCOMP
2388 
2389         if (streq(name, "SystemCallErrorNumber"))
2390                 return bus_set_transient_errno(u, name, &c->syscall_errno, message, flags, error);
2391 
2392         if (streq(name, "SystemCallFilter")) {
2393                 int allow_list;
2394                 _cleanup_strv_free_ char **l = NULL;
2395 
2396                 r = sd_bus_message_enter_container(message, 'r', "bas");
2397                 if (r < 0)
2398                         return r;
2399 
2400                 r = sd_bus_message_read(message, "b", &allow_list);
2401                 if (r < 0)
2402                         return r;
2403 
2404                 r = sd_bus_message_read_strv(message, &l);
2405                 if (r < 0)
2406                         return r;
2407 
2408                 r = sd_bus_message_exit_container(message);
2409                 if (r < 0)
2410                         return r;
2411 
2412                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2413                         _cleanup_free_ char *joined = NULL;
2414                         SeccompParseFlags invert_flag = allow_list ? 0 : SECCOMP_PARSE_INVERT;
2415 
2416                         if (strv_isempty(l)) {
2417                                 c->syscall_allow_list = false;
2418                                 c->syscall_filter = hashmap_free(c->syscall_filter);
2419 
2420                                 unit_write_settingf(u, flags, name, "SystemCallFilter=");
2421                                 return 1;
2422                         }
2423 
2424                         if (!c->syscall_filter) {
2425                                 c->syscall_filter = hashmap_new(NULL);
2426                                 if (!c->syscall_filter)
2427                                         return log_oom();
2428 
2429                                 c->syscall_allow_list = allow_list;
2430 
2431                                 if (c->syscall_allow_list) {
2432                                         r = seccomp_parse_syscall_filter("@default",
2433                                                                          -1,
2434                                                                          c->syscall_filter,
2435                                                                          SECCOMP_PARSE_PERMISSIVE |
2436                                                                          SECCOMP_PARSE_ALLOW_LIST | invert_flag,
2437                                                                          u->id,
2438                                                                          NULL, 0);
2439                                         if (r < 0)
2440                                                 return r;
2441                                 }
2442                         }
2443 
2444                         STRV_FOREACH(s, l) {
2445                                 _cleanup_free_ char *n = NULL;
2446                                 int e;
2447 
2448                                 r = parse_syscall_and_errno(*s, &n, &e);
2449                                 if (r < 0)
2450                                         return r;
2451 
2452                                 if (allow_list && e >= 0)
2453                                         return -EINVAL;
2454 
2455                                 r = seccomp_parse_syscall_filter(n,
2456                                                                  e,
2457                                                                  c->syscall_filter,
2458                                                                  SECCOMP_PARSE_LOG | SECCOMP_PARSE_PERMISSIVE |
2459                                                                  invert_flag |
2460                                                                  (c->syscall_allow_list ? SECCOMP_PARSE_ALLOW_LIST : 0),
2461                                                                  u->id,
2462                                                                  NULL, 0);
2463                                 if (r < 0)
2464                                         return r;
2465                         }
2466 
2467                         joined = strv_join(l, " ");
2468                         if (!joined)
2469                                 return -ENOMEM;
2470 
2471                         unit_write_settingf(u, flags, name, "SystemCallFilter=%s%s", allow_list ? "" : "~", joined);
2472                 }
2473 
2474                 return 1;
2475 
2476         } else if (streq(name, "SystemCallLog")) {
2477                 int allow_list;
2478                 _cleanup_strv_free_ char **l = NULL;
2479 
2480                 r = sd_bus_message_enter_container(message, 'r', "bas");
2481                 if (r < 0)
2482                         return r;
2483 
2484                 r = sd_bus_message_read(message, "b", &allow_list);
2485                 if (r < 0)
2486                         return r;
2487 
2488                 r = sd_bus_message_read_strv(message, &l);
2489                 if (r < 0)
2490                         return r;
2491 
2492                 r = sd_bus_message_exit_container(message);
2493                 if (r < 0)
2494                         return r;
2495 
2496                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2497                         _cleanup_free_ char *joined = NULL;
2498                         SeccompParseFlags invert_flag = allow_list ? 0 : SECCOMP_PARSE_INVERT;
2499 
2500                         if (strv_isempty(l)) {
2501                                 c->syscall_log_allow_list = false;
2502                                 c->syscall_log = hashmap_free(c->syscall_log);
2503 
2504                                 unit_write_settingf(u, flags, name, "SystemCallLog=");
2505                                 return 1;
2506                         }
2507 
2508                         if (!c->syscall_log) {
2509                                 c->syscall_log = hashmap_new(NULL);
2510                                 if (!c->syscall_log)
2511                                         return log_oom();
2512 
2513                                 c->syscall_log_allow_list = allow_list;
2514                         }
2515 
2516                         STRV_FOREACH(s, l) {
2517                                 r = seccomp_parse_syscall_filter(*s,
2518                                                                  -1, /* errno not used */
2519                                                                  c->syscall_log,
2520                                                                  SECCOMP_PARSE_LOG | SECCOMP_PARSE_PERMISSIVE |
2521                                                                  invert_flag |
2522                                                                  (c->syscall_log_allow_list ? SECCOMP_PARSE_ALLOW_LIST : 0),
2523                                                                  u->id,
2524                                                                  NULL, 0);
2525                                 if (r < 0)
2526                                         return r;
2527                         }
2528 
2529                         joined = strv_join(l, " ");
2530                         if (!joined)
2531                                 return -ENOMEM;
2532 
2533                         unit_write_settingf(u, flags, name, "SystemCallLog=%s%s", allow_list ? "" : "~", joined);
2534                 }
2535 
2536                 return 1;
2537 
2538         } else if (streq(name, "SystemCallArchitectures")) {
2539                 _cleanup_strv_free_ char **l = NULL;
2540 
2541                 r = sd_bus_message_read_strv(message, &l);
2542                 if (r < 0)
2543                         return r;
2544 
2545                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2546                         _cleanup_free_ char *joined = NULL;
2547 
2548                         if (strv_isempty(l))
2549                                 c->syscall_archs = set_free(c->syscall_archs);
2550                         else
2551                                 STRV_FOREACH(s, l) {
2552                                         uint32_t a;
2553 
2554                                         r = seccomp_arch_from_string(*s, &a);
2555                                         if (r < 0)
2556                                                 return r;
2557 
2558                                         r = set_ensure_put(&c->syscall_archs, NULL, UINT32_TO_PTR(a + 1));
2559                                         if (r < 0)
2560                                                 return r;
2561                                 }
2562 
2563                         joined = strv_join(l, " ");
2564                         if (!joined)
2565                                 return -ENOMEM;
2566 
2567                         unit_write_settingf(u, flags, name, "%s=%s", name, joined);
2568                 }
2569 
2570                 return 1;
2571 
2572         } else if (streq(name, "RestrictAddressFamilies")) {
2573                 _cleanup_strv_free_ char **l = NULL;
2574                 int allow_list;
2575 
2576                 r = sd_bus_message_enter_container(message, 'r', "bas");
2577                 if (r < 0)
2578                         return r;
2579 
2580                 r = sd_bus_message_read(message, "b", &allow_list);
2581                 if (r < 0)
2582                         return r;
2583 
2584                 r = sd_bus_message_read_strv(message, &l);
2585                 if (r < 0)
2586                         return r;
2587 
2588                 r = sd_bus_message_exit_container(message);
2589                 if (r < 0)
2590                         return r;
2591 
2592                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2593                         _cleanup_free_ char *joined = NULL;
2594 
2595                         if (strv_isempty(l)) {
2596                                 c->address_families_allow_list = allow_list;
2597                                 c->address_families = set_free(c->address_families);
2598 
2599                                 unit_write_settingf(u, flags, name, "RestrictAddressFamilies=%s",
2600                                                     allow_list ? "none" : "");
2601                                 return 1;
2602                         }
2603 
2604                         if (!c->address_families) {
2605                                 c->address_families = set_new(NULL);
2606                                 if (!c->address_families)
2607                                         return log_oom();
2608 
2609                                 c->address_families_allow_list = allow_list;
2610                         }
2611 
2612                         STRV_FOREACH(s, l) {
2613                                 int af;
2614 
2615                                 af = af_from_name(*s);
2616                                 if (af < 0)
2617                                         return af;
2618 
2619                                 if (allow_list == c->address_families_allow_list) {
2620                                         r = set_put(c->address_families, INT_TO_PTR(af));
2621                                         if (r < 0)
2622                                                 return r;
2623                                 } else
2624                                         set_remove(c->address_families, INT_TO_PTR(af));
2625                         }
2626 
2627                         joined = strv_join(l, " ");
2628                         if (!joined)
2629                                 return -ENOMEM;
2630 
2631                         unit_write_settingf(u, flags, name, "RestrictAddressFamilies=%s%s", allow_list ? "" : "~", joined);
2632                 }
2633 
2634                 return 1;
2635         }
2636 #endif
2637         if (STR_IN_SET(name, "CPUAffinity", "NUMAMask")) {
2638                 const void *a;
2639                 size_t n;
2640                 bool affinity = streq(name, "CPUAffinity");
2641                 _cleanup_(cpu_set_reset) CPUSet set = {};
2642 
2643                 r = sd_bus_message_read_array(message, 'y', &a, &n);
2644                 if (r < 0)
2645                         return r;
2646 
2647                 r = cpu_set_from_dbus(a, n, &set);
2648                 if (r < 0)
2649                         return r;
2650 
2651                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2652                         if (n == 0) {
2653                                 cpu_set_reset(affinity ? &c->cpu_set : &c->numa_policy.nodes);
2654                                 unit_write_settingf(u, flags, name, "%s=", name);
2655                         } else {
2656                                 _cleanup_free_ char *str = NULL;
2657 
2658                                 str = cpu_set_to_string(&set);
2659                                 if (!str)
2660                                         return -ENOMEM;
2661 
2662                                 /* We forego any optimizations here, and always create the structure using
2663                                  * cpu_set_add_all(), because we don't want to care if the existing size we
2664                                  * got over dbus is appropriate. */
2665                                 r = cpu_set_add_all(affinity ? &c->cpu_set : &c->numa_policy.nodes, &set);
2666                                 if (r < 0)
2667                                         return r;
2668 
2669                                 unit_write_settingf(u, flags, name, "%s=%s", name, str);
2670                         }
2671                 }
2672 
2673                 return 1;
2674 
2675         } else if (streq(name, "CPUAffinityFromNUMA")) {
2676                 int q;
2677 
2678                 r = sd_bus_message_read_basic(message, 'b', &q);
2679                 if (r < 0)
2680                         return r;
2681 
2682                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2683                         c->cpu_affinity_from_numa = q;
2684                         unit_write_settingf(u, flags, name, "%s=%s", "CPUAffinity", "numa");
2685                 }
2686 
2687                 return 1;
2688 
2689         } else if (streq(name, "NUMAPolicy")) {
2690                 int32_t type;
2691 
2692                 r = sd_bus_message_read(message, "i", &type);
2693                 if (r < 0)
2694                         return r;
2695 
2696                 if (!mpol_is_valid(type))
2697                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid NUMAPolicy value: %i", type);
2698 
2699                 if (!UNIT_WRITE_FLAGS_NOOP(flags))
2700                         c->numa_policy.type = type;
2701 
2702                 return 1;
2703 
2704         } else if (streq(name, "Nice")) {
2705                 int32_t q;
2706 
2707                 r = sd_bus_message_read(message, "i", &q);
2708                 if (r < 0)
2709                         return r;
2710 
2711                 if (!nice_is_valid(q))
2712                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid Nice value: %i", q);
2713 
2714                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2715                         c->nice = q;
2716                         c->nice_set = true;
2717 
2718                         unit_write_settingf(u, flags, name, "Nice=%i", q);
2719                 }
2720 
2721                 return 1;
2722 
2723         } else if (streq(name, "CPUSchedulingPolicy")) {
2724                 int32_t q;
2725 
2726                 r = sd_bus_message_read(message, "i", &q);
2727                 if (r < 0)
2728                         return r;
2729 
2730                 if (!sched_policy_is_valid(q))
2731                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid CPU scheduling policy: %i", q);
2732 
2733                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2734                         _cleanup_free_ char *s = NULL;
2735 
2736                         r = sched_policy_to_string_alloc(q, &s);
2737                         if (r < 0)
2738                                 return r;
2739 
2740                         c->cpu_sched_policy = q;
2741                         c->cpu_sched_priority = CLAMP(c->cpu_sched_priority, sched_get_priority_min(q), sched_get_priority_max(q));
2742                         c->cpu_sched_set = true;
2743 
2744                         unit_write_settingf(u, flags, name, "CPUSchedulingPolicy=%s", s);
2745                 }
2746 
2747                 return 1;
2748 
2749         } else if (streq(name, "CPUSchedulingPriority")) {
2750                 int32_t p, min, max;
2751 
2752                 r = sd_bus_message_read(message, "i", &p);
2753                 if (r < 0)
2754                         return r;
2755 
2756                 min = sched_get_priority_min(c->cpu_sched_policy);
2757                 max = sched_get_priority_max(c->cpu_sched_policy);
2758                 if (p < min || p > max)
2759                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid CPU scheduling priority: %i", p);
2760 
2761                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2762                         c->cpu_sched_priority = p;
2763                         c->cpu_sched_set = true;
2764 
2765                         unit_write_settingf(u, flags, name, "CPUSchedulingPriority=%i", p);
2766                 }
2767 
2768                 return 1;
2769 
2770         } else if (streq(name, "IOSchedulingClass")) {
2771                 int32_t q;
2772 
2773                 r = sd_bus_message_read(message, "i", &q);
2774                 if (r < 0)
2775                         return r;
2776 
2777                 if (!ioprio_class_is_valid(q))
2778                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IO scheduling class: %i", q);
2779 
2780                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2781                         _cleanup_free_ char *s = NULL;
2782 
2783                         r = ioprio_class_to_string_alloc(q, &s);
2784                         if (r < 0)
2785                                 return r;
2786 
2787                         c->ioprio = ioprio_normalize(ioprio_prio_value(q, ioprio_prio_data(c->ioprio)));
2788                         c->ioprio_set = true;
2789 
2790                         unit_write_settingf(u, flags, name, "IOSchedulingClass=%s", s);
2791                 }
2792 
2793                 return 1;
2794 
2795         } else if (streq(name, "IOSchedulingPriority")) {
2796                 int32_t p;
2797 
2798                 r = sd_bus_message_read(message, "i", &p);
2799                 if (r < 0)
2800                         return r;
2801 
2802                 if (!ioprio_priority_is_valid(p))
2803                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IO scheduling priority: %i", p);
2804 
2805                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2806                         c->ioprio = ioprio_normalize(ioprio_prio_value(ioprio_prio_class(c->ioprio), p));
2807                         c->ioprio_set = true;
2808 
2809                         unit_write_settingf(u, flags, name, "IOSchedulingPriority=%i", p);
2810                 }
2811 
2812                 return 1;
2813 
2814         } else if (streq(name, "MountAPIVFS")) {
2815                 bool b;
2816 
2817                 r = bus_set_transient_bool(u, name, &b, message, flags, error);
2818                 if (r < 0)
2819                         return r;
2820 
2821                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2822                         c->mount_apivfs = b;
2823                         c->mount_apivfs_set = true;
2824                 }
2825 
2826                 return 1;
2827 
2828         } else if (streq(name, "WorkingDirectory")) {
2829                 const char *s;
2830                 bool missing_ok;
2831 
2832                 r = sd_bus_message_read(message, "s", &s);
2833                 if (r < 0)
2834                         return r;
2835 
2836                 if (s[0] == '-') {
2837                         missing_ok = true;
2838                         s++;
2839                 } else
2840                         missing_ok = false;
2841 
2842                 if (!isempty(s) && !streq(s, "~") && !path_is_absolute(s))
2843                         return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "WorkingDirectory= expects an absolute path or '~'");
2844 
2845                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2846                         if (streq(s, "~")) {
2847                                 c->working_directory = mfree(c->working_directory);
2848                                 c->working_directory_home = true;
2849                         } else {
2850                                 r = free_and_strdup(&c->working_directory, empty_to_null(s));
2851                                 if (r < 0)
2852                                         return r;
2853 
2854                                 c->working_directory_home = false;
2855                         }
2856 
2857                         c->working_directory_missing_ok = missing_ok;
2858                         unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "WorkingDirectory=%s%s", missing_ok ? "-" : "", s);
2859                 }
2860 
2861                 return 1;
2862 
2863         } else if (STR_IN_SET(name,
2864                               "StandardInputFileDescriptorName", "StandardOutputFileDescriptorName", "StandardErrorFileDescriptorName")) {
2865                 const char *s;
2866 
2867                 r = sd_bus_message_read(message, "s", &s);
2868                 if (r < 0)
2869                         return r;
2870 
2871                 if (!isempty(s) && !fdname_is_valid(s))
2872                         return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid file descriptor name");
2873 
2874                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2875 
2876                         if (streq(name, "StandardInputFileDescriptorName")) {
2877                                 r = free_and_strdup(c->stdio_fdname + STDIN_FILENO, empty_to_null(s));
2878                                 if (r < 0)
2879                                         return r;
2880 
2881                                 c->std_input = EXEC_INPUT_NAMED_FD;
2882                                 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardInput=fd:%s", exec_context_fdname(c, STDIN_FILENO));
2883 
2884                         } else if (streq(name, "StandardOutputFileDescriptorName")) {
2885                                 r = free_and_strdup(c->stdio_fdname + STDOUT_FILENO, empty_to_null(s));
2886                                 if (r < 0)
2887                                         return r;
2888 
2889                                 c->std_output = EXEC_OUTPUT_NAMED_FD;
2890                                 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=fd:%s", exec_context_fdname(c, STDOUT_FILENO));
2891 
2892                         } else {
2893                                 assert(streq(name, "StandardErrorFileDescriptorName"));
2894 
2895                                 r = free_and_strdup(&c->stdio_fdname[STDERR_FILENO], empty_to_null(s));
2896                                 if (r < 0)
2897                                         return r;
2898 
2899                                 c->std_error = EXEC_OUTPUT_NAMED_FD;
2900                                 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=fd:%s", exec_context_fdname(c, STDERR_FILENO));
2901                         }
2902                 }
2903 
2904                 return 1;
2905 
2906         } else if (STR_IN_SET(name,
2907                               "StandardInputFile",
2908                               "StandardOutputFile", "StandardOutputFileToAppend", "StandardOutputFileToTruncate",
2909                               "StandardErrorFile", "StandardErrorFileToAppend", "StandardErrorFileToTruncate")) {
2910                 const char *s;
2911 
2912                 r = sd_bus_message_read(message, "s", &s);
2913                 if (r < 0)
2914                         return r;
2915 
2916                 if (!isempty(s)) {
2917                         if (!path_is_absolute(s))
2918                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute", s);
2919                         if (!path_is_normalized(s))
2920                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not normalized", s);
2921                 }
2922 
2923                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2924 
2925                         if (streq(name, "StandardInputFile")) {
2926                                 r = free_and_strdup(&c->stdio_file[STDIN_FILENO], empty_to_null(s));
2927                                 if (r < 0)
2928                                         return r;
2929 
2930                                 c->std_input = EXEC_INPUT_FILE;
2931                                 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardInput=file:%s", s);
2932 
2933                         } else if (STR_IN_SET(name, "StandardOutputFile", "StandardOutputFileToAppend", "StandardOutputFileToTruncate")) {
2934                                 r = free_and_strdup(&c->stdio_file[STDOUT_FILENO], empty_to_null(s));
2935                                 if (r < 0)
2936                                         return r;
2937 
2938                                 if (streq(name, "StandardOutputFile")) {
2939                                         c->std_output = EXEC_OUTPUT_FILE;
2940                                         unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=file:%s", s);
2941                                 } else if (streq(name, "StandardOutputFileToAppend")) {
2942                                         c->std_output = EXEC_OUTPUT_FILE_APPEND;
2943                                         unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=append:%s", s);
2944                                 } else {
2945                                         assert(streq(name, "StandardOutputFileToTruncate"));
2946                                         c->std_output = EXEC_OUTPUT_FILE_TRUNCATE;
2947                                         unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=truncate:%s", s);
2948                                 }
2949                         } else {
2950                                 assert(STR_IN_SET(name, "StandardErrorFile", "StandardErrorFileToAppend", "StandardErrorFileToTruncate"));
2951 
2952                                 r = free_and_strdup(&c->stdio_file[STDERR_FILENO], empty_to_null(s));
2953                                 if (r < 0)
2954                                         return r;
2955 
2956                                 if (streq(name, "StandardErrorFile")) {
2957                                         c->std_error = EXEC_OUTPUT_FILE;
2958                                         unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=file:%s", s);
2959                                 } else if (streq(name, "StandardErrorFileToAppend")) {
2960                                         c->std_error = EXEC_OUTPUT_FILE_APPEND;
2961                                         unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=append:%s", s);
2962                                 } else {
2963                                         assert(streq(name, "StandardErrorFileToTruncate"));
2964                                         c->std_error = EXEC_OUTPUT_FILE_TRUNCATE;
2965                                         unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=truncate:%s", s);
2966                                 }
2967                         }
2968                 }
2969 
2970                 return 1;
2971 
2972         } else if (streq(name, "StandardInputData")) {
2973                 const void *p;
2974                 size_t sz;
2975 
2976                 r = sd_bus_message_read_array(message, 'y', &p, &sz);
2977                 if (r < 0)
2978                         return r;
2979 
2980                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2981                         _cleanup_free_ char *encoded = NULL;
2982 
2983                         if (sz == 0) {
2984                                 c->stdin_data = mfree(c->stdin_data);
2985                                 c->stdin_data_size = 0;
2986 
2987                                 unit_write_settingf(u, flags, name, "StandardInputData=");
2988                         } else {
2989                                 void *q;
2990                                 ssize_t n;
2991 
2992                                 if (c->stdin_data_size + sz < c->stdin_data_size || /* check for overflow */
2993                                     c->stdin_data_size + sz > EXEC_STDIN_DATA_MAX)
2994                                         return -E2BIG;
2995 
2996                                 n = base64mem(p, sz, &encoded);
2997                                 if (n < 0)
2998                                         return (int) n;
2999 
3000                                 q = realloc(c->stdin_data, c->stdin_data_size + sz);
3001                                 if (!q)
3002                                         return -ENOMEM;
3003 
3004                                 memcpy((uint8_t*) q + c->stdin_data_size, p, sz);
3005 
3006                                 c->stdin_data = q;
3007                                 c->stdin_data_size += sz;
3008 
3009                                 unit_write_settingf(u, flags, name, "StandardInputData=%s", encoded);
3010                         }
3011                 }
3012 
3013                 return 1;
3014 
3015         } else if (streq(name, "Environment")) {
3016 
3017                 _cleanup_strv_free_ char **l = NULL;
3018 
3019                 r = sd_bus_message_read_strv(message, &l);
3020                 if (r < 0)
3021                         return r;
3022 
3023                 if (!strv_env_is_valid(l))
3024                         return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
3025 
3026                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3027                         if (strv_isempty(l)) {
3028                                 c->environment = strv_free(c->environment);
3029                                 unit_write_setting(u, flags, name, "Environment=");
3030                         } else {
3031                                 _cleanup_free_ char *joined = NULL;
3032                                 char **e;
3033 
3034                                 joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS|UNIT_ESCAPE_C);
3035                                 if (!joined)
3036                                         return -ENOMEM;
3037 
3038                                 e = strv_env_merge(c->environment, l);
3039                                 if (!e)
3040                                         return -ENOMEM;
3041 
3042                                 strv_free_and_replace(c->environment, e);
3043                                 unit_write_settingf(u, flags, name, "Environment=%s", joined);
3044                         }
3045                 }
3046 
3047                 return 1;
3048 
3049         } else if (streq(name, "UnsetEnvironment")) {
3050 
3051                 _cleanup_strv_free_ char **l = NULL;
3052 
3053                 r = sd_bus_message_read_strv(message, &l);
3054                 if (r < 0)
3055                         return r;
3056 
3057                 if (!strv_env_name_or_assignment_is_valid(l))
3058                         return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UnsetEnvironment= list.");
3059 
3060                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3061                         if (strv_isempty(l)) {
3062                                 c->unset_environment = strv_free(c->unset_environment);
3063                                 unit_write_setting(u, flags, name, "UnsetEnvironment=");
3064                         } else {
3065                                 _cleanup_free_ char *joined = NULL;
3066                                 char **e;
3067 
3068                                 joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS|UNIT_ESCAPE_C);
3069                                 if (!joined)
3070                                         return -ENOMEM;
3071 
3072                                 e = strv_env_merge(c->unset_environment, l);
3073                                 if (!e)
3074                                         return -ENOMEM;
3075 
3076                                 strv_free_and_replace(c->unset_environment, e);
3077                                 unit_write_settingf(u, flags, name, "UnsetEnvironment=%s", joined);
3078                         }
3079                 }
3080 
3081                 return 1;
3082 
3083         } else if (streq(name, "OOMScoreAdjust")) {
3084                 int oa;
3085 
3086                 r = sd_bus_message_read(message, "i", &oa);
3087                 if (r < 0)
3088                         return r;
3089 
3090                 if (!oom_score_adjust_is_valid(oa))
3091                         return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "OOM score adjust value out of range");
3092 
3093                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3094                         c->oom_score_adjust = oa;
3095                         c->oom_score_adjust_set = true;
3096                         unit_write_settingf(u, flags, name, "OOMScoreAdjust=%i", oa);
3097                 }
3098 
3099                 return 1;
3100 
3101         } else if (streq(name, "CoredumpFilter")) {
3102                 uint64_t f;
3103 
3104                 r = sd_bus_message_read(message, "t", &f);
3105                 if (r < 0)
3106                         return r;
3107 
3108                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3109                         c->coredump_filter = f;
3110                         c->coredump_filter_set = true;
3111                         unit_write_settingf(u, flags, name, "CoredumpFilter=0x%"PRIx64, f);
3112                 }
3113 
3114                 return 1;
3115 
3116         } else if (streq(name, "EnvironmentFiles")) {
3117 
3118                 _cleanup_free_ char *joined = NULL;
3119                 _cleanup_fclose_ FILE *f = NULL;
3120                 _cleanup_strv_free_ char **l = NULL;
3121                 size_t size = 0;
3122 
3123                 r = sd_bus_message_enter_container(message, 'a', "(sb)");
3124                 if (r < 0)
3125                         return r;
3126 
3127                 f = open_memstream_unlocked(&joined, &size);
3128                 if (!f)
3129                         return -ENOMEM;
3130 
3131                 fputs("EnvironmentFile=\n", f);
3132 
3133                 STRV_FOREACH(i, c->environment_files) {
3134                         _cleanup_free_ char *q = NULL;
3135 
3136                         q = specifier_escape(*i);
3137                         if (!q)
3138                                 return -ENOMEM;
3139 
3140                         fprintf(f, "EnvironmentFile=%s\n", q);
3141                 }
3142 
3143                 while ((r = sd_bus_message_enter_container(message, 'r', "sb")) > 0) {
3144                         const char *path;
3145                         int b;
3146 
3147                         r = sd_bus_message_read(message, "sb", &path, &b);
3148                         if (r < 0)
3149                                 return r;
3150 
3151                         r = sd_bus_message_exit_container(message);
3152                         if (r < 0)
3153                                 return r;
3154 
3155                         if (!path_is_absolute(path))
3156                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
3157 
3158                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3159                                 _cleanup_free_ char *q = NULL, *buf = NULL;
3160 
3161                                 buf = strjoin(b ? "-" : "", path);
3162                                 if (!buf)
3163                                         return -ENOMEM;
3164 
3165                                 q = specifier_escape(buf);
3166                                 if (!q)
3167                                         return -ENOMEM;
3168 
3169                                 fprintf(f, "EnvironmentFile=%s\n", q);
3170 
3171                                 r = strv_consume(&l, TAKE_PTR(buf));
3172                                 if (r < 0)
3173                                         return r;
3174                         }
3175                 }
3176                 if (r < 0)
3177                         return r;
3178 
3179                 r = sd_bus_message_exit_container(message);
3180                 if (r < 0)
3181                         return r;
3182 
3183                 r = fflush_and_check(f);
3184                 if (r < 0)
3185                         return r;
3186 
3187                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3188                         if (strv_isempty(l)) {
3189                                 c->environment_files = strv_free(c->environment_files);
3190                                 unit_write_setting(u, flags, name, "EnvironmentFile=");
3191                         } else {
3192                                 r = strv_extend_strv(&c->environment_files, l, true);
3193                                 if (r < 0)
3194                                         return r;
3195 
3196                                 unit_write_setting(u, flags, name, joined);
3197                         }
3198                 }
3199 
3200                 return 1;
3201 
3202         } else if (streq(name, "PassEnvironment")) {
3203 
3204                 _cleanup_strv_free_ char **l = NULL;
3205 
3206                 r = sd_bus_message_read_strv(message, &l);
3207                 if (r < 0)
3208                         return r;
3209 
3210                 if (!strv_env_name_is_valid(l))
3211                         return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PassEnvironment= block.");
3212 
3213                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3214                         if (strv_isempty(l)) {
3215                                 c->pass_environment = strv_free(c->pass_environment);
3216                                 unit_write_setting(u, flags, name, "PassEnvironment=");
3217                         } else {
3218                                 _cleanup_free_ char *joined = NULL;
3219 
3220                                 r = strv_extend_strv(&c->pass_environment, l, true);
3221                                 if (r < 0)
3222                                         return r;
3223 
3224                                 /* We write just the new settings out to file, with unresolved specifiers. */
3225                                 joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS);
3226                                 if (!joined)
3227                                         return -ENOMEM;
3228 
3229                                 unit_write_settingf(u, flags, name, "PassEnvironment=%s", joined);
3230                         }
3231                 }
3232 
3233                 return 1;
3234 
3235         } else if (STR_IN_SET(name, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories",
3236                               "ReadWritePaths", "ReadOnlyPaths", "InaccessiblePaths", "ExecPaths", "NoExecPaths",
3237                               "ExtensionDirectories")) {
3238                 _cleanup_strv_free_ char **l = NULL;
3239                 char ***dirs;
3240 
3241                 r = sd_bus_message_read_strv(message, &l);
3242                 if (r < 0)
3243                         return r;
3244 
3245                 STRV_FOREACH(p, l) {
3246                         char *i = *p;
3247                         size_t offset;
3248 
3249                         offset = i[0] == '-';
3250                         offset += i[offset] == '+';
3251                         if (!path_is_absolute(i + offset))
3252                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
3253 
3254                         path_simplify(i + offset);
3255                 }
3256 
3257                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3258                         if (STR_IN_SET(name, "ReadWriteDirectories", "ReadWritePaths"))
3259                                 dirs = &c->read_write_paths;
3260                         else if (STR_IN_SET(name, "ReadOnlyDirectories", "ReadOnlyPaths"))
3261                                 dirs = &c->read_only_paths;
3262                         else if (streq(name, "ExecPaths"))
3263                                 dirs = &c->exec_paths;
3264                         else if (streq(name, "NoExecPaths"))
3265                                 dirs = &c->no_exec_paths;
3266                         else if (streq(name, "ExtensionDirectories"))
3267                                 dirs = &c->extension_directories;
3268                         else /* "InaccessiblePaths" */
3269                                 dirs = &c->inaccessible_paths;
3270 
3271                         if (strv_isempty(l)) {
3272                                 *dirs = strv_free(*dirs);
3273                                 unit_write_settingf(u, flags, name, "%s=", name);
3274                         } else {
3275                                 _cleanup_free_ char *joined = NULL;
3276 
3277                                 joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS);
3278                                 if (!joined)
3279                                         return -ENOMEM;
3280 
3281                                 r = strv_extend_strv(dirs, l, true);
3282                                 if (r < 0)
3283                                         return -ENOMEM;
3284 
3285                                 unit_write_settingf(u, flags, name, "%s=%s", name, joined);
3286                         }
3287                 }
3288 
3289                 return 1;
3290 
3291         } else if (streq(name, "ExecSearchPath")) {
3292                 _cleanup_strv_free_ char **l = NULL;
3293 
3294                 r = sd_bus_message_read_strv(message, &l);
3295                 if (r < 0)
3296                         return r;
3297 
3298                 STRV_FOREACH(p, l)
3299                         if (!path_is_absolute(*p) || !path_is_normalized(*p) || strchr(*p, ':'))
3300                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
3301 
3302                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3303                         if (strv_isempty(l)) {
3304                                 c->exec_search_path = strv_free(c->exec_search_path);
3305                                 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "ExecSearchPath=");
3306                         } else {
3307                                 _cleanup_free_ char *joined = NULL;
3308                                 r = strv_extend_strv(&c->exec_search_path, l, true);
3309                                 if (r < 0)
3310                                         return -ENOMEM;
3311                                 joined = strv_join(c->exec_search_path, ":");
3312                                 if (!joined)
3313                                         return log_oom();
3314                                 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "ExecSearchPath=%s", joined);
3315                         }
3316                 }
3317 
3318                 return 1;
3319 
3320         } else if (STR_IN_SET(name, "RuntimeDirectory", "StateDirectory", "CacheDirectory", "LogsDirectory", "ConfigurationDirectory")) {
3321                 _cleanup_strv_free_ char **l = NULL;
3322 
3323                 r = sd_bus_message_read_strv(message, &l);
3324                 if (r < 0)
3325                         return r;
3326 
3327                 STRV_FOREACH(p, l) {
3328                         if (!path_is_normalized(*p))
3329                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= path is not normalized: %s", name, *p);
3330 
3331                         if (path_is_absolute(*p))
3332                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= path is absolute: %s", name, *p);
3333 
3334                         if (path_startswith(*p, "private"))
3335                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= path can't be 'private': %s", name, *p);
3336                 }
3337 
3338                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3339                         ExecDirectoryType i;
3340                         ExecDirectory *d;
3341 
3342                         assert_se((i = exec_directory_type_from_string(name)) >= 0);
3343                         d = c->directories + i;
3344 
3345                         if (strv_isempty(l)) {
3346                                 exec_directory_done(d);
3347                                 unit_write_settingf(u, flags, name, "%s=", name);
3348                         } else {
3349                                 _cleanup_free_ char *joined = NULL;
3350 
3351                                 STRV_FOREACH(source, l) {
3352                                         r = exec_directory_add(&d->items, &d->n_items, *source, NULL);
3353                                         if (r < 0)
3354                                                 return log_oom();
3355                                 }
3356 
3357                                 joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS);
3358                                 if (!joined)
3359                                         return -ENOMEM;
3360 
3361                                 unit_write_settingf(u, flags, name, "%s=%s", name, joined);
3362                         }
3363                 }
3364 
3365                 return 1;
3366 
3367         } else if (STR_IN_SET(name, "AppArmorProfile", "SmackProcessLabel")) {
3368                 int ignore;
3369                 const char *s;
3370 
3371                 r = sd_bus_message_read(message, "(bs)", &ignore, &s);
3372                 if (r < 0)
3373                         return r;
3374 
3375                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3376                         char **p;
3377                         bool *b;
3378 
3379                         if (streq(name, "AppArmorProfile")) {
3380                                 p = &c->apparmor_profile;
3381                                 b = &c->apparmor_profile_ignore;
3382                         } else { /* "SmackProcessLabel" */
3383                                 p = &c->smack_process_label;
3384                                 b = &c->smack_process_label_ignore;
3385                         }
3386 
3387                         if (isempty(s)) {
3388                                 *p = mfree(*p);
3389                                 *b = false;
3390                         } else {
3391                                 if (free_and_strdup(p, s) < 0)
3392                                         return -ENOMEM;
3393                                 *b = ignore;
3394                         }
3395 
3396                         unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s%s", name, ignore ? "-" : "", strempty(s));
3397                 }
3398 
3399                 return 1;
3400 
3401         } else if (STR_IN_SET(name, "BindPaths", "BindReadOnlyPaths")) {
3402                 char *source, *destination;
3403                 int ignore_enoent;
3404                 uint64_t mount_flags;
3405                 bool empty = true;
3406 
3407                 r = sd_bus_message_enter_container(message, 'a', "(ssbt)");
3408                 if (r < 0)
3409                         return r;
3410 
3411                 while ((r = sd_bus_message_read(message, "(ssbt)", &source, &destination, &ignore_enoent, &mount_flags)) > 0) {
3412 
3413                         if (!path_is_absolute(source))
3414                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path %s is not absolute.", source);
3415                         if (!path_is_absolute(destination))
3416                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path %s is not absolute.", destination);
3417                         if (!IN_SET(mount_flags, 0, MS_REC))
3418                                 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown mount flags.");
3419 
3420                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3421                                 r = bind_mount_add(&c->bind_mounts, &c->n_bind_mounts,
3422                                                    &(BindMount) {
3423                                                            .source = source,
3424                                                            .destination = destination,
3425                                                            .read_only = !!strstr(name, "ReadOnly"),
3426                                                            .recursive = !!(mount_flags & MS_REC),
3427                                                            .ignore_enoent = ignore_enoent,
3428                                                    });
3429                                 if (r < 0)
3430                                         return r;
3431 
3432                                 unit_write_settingf(
3433                                                 u, flags|UNIT_ESCAPE_SPECIFIERS, name,
3434                                                 "%s=%s%s:%s:%s",
3435                                                 name,
3436                                                 ignore_enoent ? "-" : "",
3437                                                 source,
3438                                                 destination,
3439                                                 (mount_flags & MS_REC) ? "rbind" : "norbind");
3440                         }
3441 
3442                         empty = false;
3443                 }
3444                 if (r < 0)
3445                         return r;
3446 
3447                 r = sd_bus_message_exit_container(message);
3448                 if (r < 0)
3449                         return r;
3450 
3451                 if (empty) {
3452                         bind_mount_free_many(c->bind_mounts, c->n_bind_mounts);
3453                         c->bind_mounts = NULL;
3454                         c->n_bind_mounts = 0;
3455 
3456                         unit_write_settingf(u, flags, name, "%s=", name);
3457                 }
3458 
3459                 return 1;
3460 
3461         } else if (streq(name, "TemporaryFileSystem")) {
3462                 const char *path, *options;
3463                 bool empty = true;
3464 
3465                 r = sd_bus_message_enter_container(message, 'a', "(ss)");
3466                 if (r < 0)
3467                         return r;
3468 
3469                 while ((r = sd_bus_message_read(message, "(ss)", &path, &options)) > 0) {
3470 
3471                         if (!path_is_absolute(path))
3472                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Mount point %s is not absolute.", path);
3473 
3474                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3475                                 r = temporary_filesystem_add(&c->temporary_filesystems, &c->n_temporary_filesystems, path, options);
3476                                 if (r < 0)
3477                                         return r;
3478 
3479                                 unit_write_settingf(
3480                                                 u, flags|UNIT_ESCAPE_SPECIFIERS, name,
3481                                                 "%s=%s:%s",
3482                                                 name,
3483                                                 path,
3484                                                 options);
3485                         }
3486 
3487                         empty = false;
3488                 }
3489                 if (r < 0)
3490                         return r;
3491 
3492                 r = sd_bus_message_exit_container(message);
3493                 if (r < 0)
3494                         return r;
3495 
3496                 if (empty) {
3497                         temporary_filesystem_free_many(c->temporary_filesystems, c->n_temporary_filesystems);
3498                         c->temporary_filesystems = NULL;
3499                         c->n_temporary_filesystems = 0;
3500 
3501                         unit_write_settingf(u, flags, name, "%s=", name);
3502                 }
3503 
3504                 return 1;
3505 
3506         } else if ((suffix = startswith(name, "Limit"))) {
3507                 const char *soft = NULL;
3508                 int ri;
3509 
3510                 ri = rlimit_from_string(suffix);
3511                 if (ri < 0) {
3512                         soft = endswith(suffix, "Soft");
3513                         if (soft) {
3514                                 const char *n;
3515 
3516                                 n = strndupa_safe(suffix, soft - suffix);
3517                                 ri = rlimit_from_string(n);
3518                                 if (ri >= 0)
3519                                         name = strjoina("Limit", n);
3520                         }
3521                 }
3522 
3523                 if (ri >= 0) {
3524                         uint64_t rl;
3525                         rlim_t x;
3526 
3527                         r = sd_bus_message_read(message, "t", &rl);
3528                         if (r < 0)
3529                                 return r;
3530 
3531                         if (rl == UINT64_MAX)
3532                                 x = RLIM_INFINITY;
3533                         else {
3534                                 x = (rlim_t) rl;
3535 
3536                                 if ((uint64_t) x != rl)
3537                                         return -ERANGE;
3538                         }
3539 
3540                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3541                                 _cleanup_free_ char *f = NULL;
3542                                 struct rlimit nl;
3543 
3544                                 if (c->rlimit[ri]) {
3545                                         nl = *c->rlimit[ri];
3546 
3547                                         if (soft)
3548                                                 nl.rlim_cur = x;
3549                                         else
3550                                                 nl.rlim_max = x;
3551                                 } else
3552                                         /* When the resource limit is not initialized yet, then assign the value to both fields */
3553                                         nl = (struct rlimit) {
3554                                                 .rlim_cur = x,
3555                                                 .rlim_max = x,
3556                                         };
3557 
3558                                 r = rlimit_format(&nl, &f);
3559                                 if (r < 0)
3560                                         return r;
3561 
3562                                 if (c->rlimit[ri])
3563                                         *c->rlimit[ri] = nl;
3564                                 else {
3565                                         c->rlimit[ri] = newdup(struct rlimit, &nl, 1);
3566                                         if (!c->rlimit[ri])
3567                                                 return -ENOMEM;
3568                                 }
3569 
3570                                 unit_write_settingf(u, flags, name, "%s=%s", name, f);
3571                         }
3572 
3573                         return 1;
3574                 }
3575 
3576         } else if (streq(name, "MountImages")) {
3577                 _cleanup_free_ char *format_str = NULL;
3578                 MountImage *mount_images = NULL;
3579                 size_t n_mount_images = 0;
3580                 char *source, *destination;
3581                 int permissive;
3582 
3583                 r = sd_bus_message_enter_container(message, 'a', "(ssba(ss))");
3584                 if (r < 0)
3585                         return r;
3586 
3587                 for (;;) {
3588                         _cleanup_(mount_options_free_allp) MountOptions *options = NULL;
3589                         _cleanup_free_ char *source_escaped = NULL, *destination_escaped = NULL;
3590                         char *tuple;
3591 
3592                         r = sd_bus_message_enter_container(message, 'r', "ssba(ss)");
3593                         if (r < 0)
3594                                 return r;
3595 
3596                         r = sd_bus_message_read(message, "ssb", &source, &destination, &permissive);
3597                         if (r <= 0)
3598                                 break;
3599 
3600                         if (!path_is_absolute(source))
3601                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path %s is not absolute.", source);
3602                         if (!path_is_normalized(source))
3603                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path %s is not normalized.", source);
3604                         if (!path_is_absolute(destination))
3605                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path %s is not absolute.", destination);
3606                         if (!path_is_normalized(destination))
3607                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path %s is not normalized.", destination);
3608 
3609                         /* Need to store them in the unit with the escapes, so that they can be parsed again */
3610                         source_escaped = shell_escape(source, ":");
3611                         if (!source_escaped)
3612                                 return -ENOMEM;
3613                         destination_escaped = shell_escape(destination, ":");
3614                         if (!destination_escaped)
3615                                 return -ENOMEM;
3616 
3617                         tuple = strjoin(format_str,
3618                                         format_str ? " " : "",
3619                                         permissive ? "-" : "",
3620                                         source_escaped,
3621                                         ":",
3622                                         destination_escaped);
3623                         if (!tuple)
3624                                 return -ENOMEM;
3625                         free_and_replace(format_str, tuple);
3626 
3627                         r = bus_read_mount_options(message, error, &options, &format_str, ":");
3628                         if (r < 0)
3629                                 return r;
3630 
3631                         r = sd_bus_message_exit_container(message);
3632                         if (r < 0)
3633                                 return r;
3634 
3635                         r = mount_image_add(&mount_images, &n_mount_images,
3636                                             &(MountImage) {
3637                                                     .source = source,
3638                                                     .destination = destination,
3639                                                     .mount_options = options,
3640                                                     .ignore_enoent = permissive,
3641                                                     .type = MOUNT_IMAGE_DISCRETE,
3642                                             });
3643                         if (r < 0)
3644                                 return r;
3645                 }
3646                 if (r < 0)
3647                         return r;
3648 
3649                 r = sd_bus_message_exit_container(message);
3650                 if (r < 0)
3651                         return r;
3652 
3653                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3654                         if (n_mount_images == 0) {
3655                                 c->mount_images = mount_image_free_many(c->mount_images, &c->n_mount_images);
3656 
3657                                 unit_write_settingf(u, flags, name, "%s=", name);
3658                         } else {
3659                                 for (size_t i = 0; i < n_mount_images; ++i) {
3660                                         r = mount_image_add(&c->mount_images, &c->n_mount_images, &mount_images[i]);
3661                                         if (r < 0)
3662                                                 return r;
3663                                 }
3664 
3665                                 unit_write_settingf(u, flags|UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS,
3666                                                     name,
3667                                                     "%s=%s",
3668                                                     name,
3669                                                     format_str);
3670                         }
3671                 }
3672 
3673                 mount_images = mount_image_free_many(mount_images, &n_mount_images);
3674 
3675                 return 1;
3676         } else if (streq(name, "ExtensionImages")) {
3677                 _cleanup_free_ char *format_str = NULL;
3678                 MountImage *extension_images = NULL;
3679                 size_t n_extension_images = 0;
3680 
3681                 r = sd_bus_message_enter_container(message, 'a', "(sba(ss))");
3682                 if (r < 0)
3683                         return r;
3684 
3685                 for (;;) {
3686                         _cleanup_(mount_options_free_allp) MountOptions *options = NULL;
3687                         _cleanup_free_ char *source_escaped = NULL;
3688                         char *source, *tuple;
3689                         int permissive;
3690 
3691                         r = sd_bus_message_enter_container(message, 'r', "sba(ss)");
3692                         if (r < 0)
3693                                 return r;
3694 
3695                         r = sd_bus_message_read(message, "sb", &source, &permissive);
3696                         if (r <= 0)
3697                                 break;
3698 
3699                         if (!path_is_absolute(source))
3700                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path %s is not absolute.", source);
3701                         if (!path_is_normalized(source))
3702                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path %s is not normalized.", source);
3703 
3704                         /* Need to store them in the unit with the escapes, so that they can be parsed again */
3705                         source_escaped = shell_escape(source, ":");
3706                         if (!source_escaped)
3707                                 return -ENOMEM;
3708 
3709                         tuple = strjoin(format_str,
3710                                         format_str ? " " : "",
3711                                         permissive ? "-" : "",
3712                                         source_escaped);
3713                         if (!tuple)
3714                                 return -ENOMEM;
3715                         free_and_replace(format_str, tuple);
3716 
3717                         r = bus_read_mount_options(message, error, &options, &format_str, ":");
3718                         if (r < 0)
3719                                 return r;
3720 
3721                         r = sd_bus_message_exit_container(message);
3722                         if (r < 0)
3723                                 return r;
3724 
3725                         r = mount_image_add(&extension_images, &n_extension_images,
3726                                             &(MountImage) {
3727                                                     .source = source,
3728                                                     .mount_options = options,
3729                                                     .ignore_enoent = permissive,
3730                                                     .type = MOUNT_IMAGE_EXTENSION,
3731                                             });
3732                         if (r < 0)
3733                                 return r;
3734                 }
3735                 if (r < 0)
3736                         return r;
3737 
3738                 r = sd_bus_message_exit_container(message);
3739                 if (r < 0)
3740                         return r;
3741 
3742                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3743                         if (n_extension_images == 0) {
3744                                 c->extension_images = mount_image_free_many(c->extension_images, &c->n_extension_images);
3745 
3746                                 unit_write_settingf(u, flags, name, "%s=", name);
3747                         } else {
3748                                 for (size_t i = 0; i < n_extension_images; ++i) {
3749                                         r = mount_image_add(&c->extension_images, &c->n_extension_images, &extension_images[i]);
3750                                         if (r < 0)
3751                                                 return r;
3752                                 }
3753 
3754                                 unit_write_settingf(u, flags|UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS,
3755                                                     name,
3756                                                     "%s=%s",
3757                                                     name,
3758                                                     format_str);
3759                         }
3760                 }
3761 
3762                 extension_images = mount_image_free_many(extension_images, &n_extension_images);
3763 
3764                 return 1;
3765 
3766         } else if (STR_IN_SET(name, "StateDirectorySymlink", "RuntimeDirectorySymlink", "CacheDirectorySymlink", "LogsDirectorySymlink")) {
3767                 char *source, *destination;
3768                 ExecDirectory *directory;
3769                 uint64_t symlink_flags; /* No flags for now, reserved for future uses. */
3770                 ExecDirectoryType i;
3771 
3772                 assert_se((i = exec_directory_type_symlink_from_string(name)) >= 0);
3773                 directory = c->directories + i;
3774 
3775                 r = sd_bus_message_enter_container(message, 'a', "(sst)");
3776                 if (r < 0)
3777                         return r;
3778 
3779                 while ((r = sd_bus_message_read(message, "(sst)", &source, &destination, &symlink_flags)) > 0) {
3780                         if (!path_is_valid(source))
3781                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path %s is not valid.", source);
3782                         if (path_is_absolute(source))
3783                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path %s is absolute.", source);
3784                         if (!path_is_normalized(source))
3785                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path %s is not normalized.", source);
3786                         if (!path_is_valid(destination))
3787                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path %s is not valid.", destination);
3788                         if (path_is_absolute(destination))
3789                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path %s is absolute.", destination);
3790                         if (!path_is_normalized(destination))
3791                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path %s is not normalized.", destination);
3792                         if (symlink_flags != 0)
3793                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Flags must be zero.");
3794 
3795                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3796                                 _cleanup_free_ char *destination_escaped = NULL, *source_escaped = NULL;
3797                                 ExecDirectoryItem *item = NULL;
3798 
3799                                 /* Adding new directories is supported from both *DirectorySymlink methods and the
3800                                  * older ones, so try to find an existing configuration first and create it if it's
3801                                  * not there yet. */
3802                                 for (size_t j = 0; j < directory->n_items; ++j)
3803                                         if (path_equal(source, directory->items[j].path)) {
3804                                                 item = &directory->items[j];
3805                                                 break;
3806                                         }
3807 
3808                                 if (item)
3809                                         r = strv_extend(&item->symlinks, destination);
3810                                 else
3811                                         r = exec_directory_add(&directory->items, &directory->n_items, source, STRV_MAKE(destination));
3812                                 if (r < 0)
3813                                         return r;
3814 
3815                                 /* Need to store them in the unit with the escapes, so that they can be parsed again */
3816                                 source_escaped = xescape(source, ":");
3817                                 destination_escaped = xescape(destination, ":");
3818                                 if (!source_escaped || !destination_escaped)
3819                                         return -ENOMEM;
3820 
3821                                 unit_write_settingf(
3822                                                 u, flags|UNIT_ESCAPE_SPECIFIERS, exec_directory_type_to_string(i),
3823                                                 "%s=%s:%s",
3824                                                 exec_directory_type_to_string(i),
3825                                                 source_escaped,
3826                                                 destination_escaped);
3827                         }
3828                 }
3829                 if (r < 0)
3830                         return r;
3831 
3832                 r = sd_bus_message_exit_container(message);
3833                 if (r < 0)
3834                         return r;
3835 
3836                 return 1;
3837 
3838         }
3839 
3840         return 0;
3841 }
3842