]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-execute.c
core: rework syscall filter
[thirdparty/systemd.git] / src / core / dbus-execute.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <sys/prctl.h>
23
24 #include "bus-util.h"
25 #include "missing.h"
26 #include "ioprio.h"
27 #include "strv.h"
28 #include "fileio.h"
29 #include "execute.h"
30 #include "dbus-execute.h"
31 #include "capability.h"
32 #include "env-util.h"
33
34 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
35
36 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
37
38 static int property_get_environment_files(
39 sd_bus *bus,
40 const char *path,
41 const char *interface,
42 const char *property,
43 sd_bus_message *reply,
44 void *userdata,
45 sd_bus_error *error) {
46
47 ExecContext *c = userdata;
48 char **j;
49 int r;
50
51 assert(bus);
52 assert(reply);
53 assert(c);
54
55 r = sd_bus_message_open_container(reply, 'a', "(sb)");
56 if (r < 0)
57 return r;
58
59 STRV_FOREACH(j, c->environment_files) {
60 const char *fn = *j;
61
62 r = sd_bus_message_append(reply, "(sb)", fn[0] == '-' ? fn + 1 : fn, fn[0] == '-');
63 if (r < 0)
64 return r;
65 }
66
67 return sd_bus_message_close_container(reply);
68 }
69
70 static int property_get_rlimit(
71 sd_bus *bus,
72 const char *path,
73 const char *interface,
74 const char *property,
75 sd_bus_message *reply,
76 void *userdata,
77 sd_bus_error *error) {
78
79 struct rlimit *rl;
80 uint64_t u;
81
82 assert(bus);
83 assert(reply);
84 assert(userdata);
85
86 rl = *(struct rlimit**) userdata;
87 if (rl)
88 u = (uint64_t) rl->rlim_max;
89 else {
90 struct rlimit buf = {};
91 int z;
92
93 z = rlimit_from_string(property);
94 assert(z >= 0);
95
96 getrlimit(z, &buf);
97
98 u = (uint64_t) buf.rlim_max;
99 }
100
101 return sd_bus_message_append(reply, "t", u);
102 }
103
104 static int property_get_oom_score_adjust(
105 sd_bus *bus,
106 const char *path,
107 const char *interface,
108 const char *property,
109 sd_bus_message *reply,
110 void *userdata,
111 sd_bus_error *error) {
112
113
114 ExecContext *c = userdata;
115 int32_t n;
116
117 assert(bus);
118 assert(reply);
119 assert(c);
120
121 if (c->oom_score_adjust_set)
122 n = c->oom_score_adjust;
123 else {
124 _cleanup_free_ char *t = NULL;
125
126 n = 0;
127 if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0)
128 safe_atoi(t, &n);
129 }
130
131 return sd_bus_message_append(reply, "i", n);
132 }
133
134 static int property_get_nice(
135 sd_bus *bus,
136 const char *path,
137 const char *interface,
138 const char *property,
139 sd_bus_message *reply,
140 void *userdata,
141 sd_bus_error *error) {
142
143
144 ExecContext *c = userdata;
145 int32_t n;
146
147 assert(bus);
148 assert(reply);
149 assert(c);
150
151 if (c->nice_set)
152 n = c->nice;
153 else {
154 errno = 0;
155 n = getpriority(PRIO_PROCESS, 0);
156 if (errno != 0)
157 n = 0;
158 }
159
160 return sd_bus_message_append(reply, "i", n);
161 }
162
163 static int property_get_ioprio(
164 sd_bus *bus,
165 const char *path,
166 const char *interface,
167 const char *property,
168 sd_bus_message *reply,
169 void *userdata,
170 sd_bus_error *error) {
171
172
173 ExecContext *c = userdata;
174 int32_t n;
175
176 assert(bus);
177 assert(reply);
178 assert(c);
179
180 if (c->ioprio_set)
181 n = c->ioprio;
182 else {
183 n = ioprio_get(IOPRIO_WHO_PROCESS, 0);
184 if (n < 0)
185 n = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4);
186 }
187
188 return sd_bus_message_append(reply, "i", n);
189 }
190
191 static int property_get_cpu_sched_policy(
192 sd_bus *bus,
193 const char *path,
194 const char *interface,
195 const char *property,
196 sd_bus_message *reply,
197 void *userdata,
198 sd_bus_error *error) {
199
200 ExecContext *c = userdata;
201 int32_t n;
202
203 assert(bus);
204 assert(reply);
205 assert(c);
206
207 if (c->cpu_sched_set)
208 n = c->cpu_sched_policy;
209 else {
210 n = sched_getscheduler(0);
211 if (n < 0)
212 n = SCHED_OTHER;
213 }
214
215 return sd_bus_message_append(reply, "i", n);
216 }
217
218 static int property_get_cpu_sched_priority(
219 sd_bus *bus,
220 const char *path,
221 const char *interface,
222 const char *property,
223 sd_bus_message *reply,
224 void *userdata,
225 sd_bus_error *error) {
226
227 ExecContext *c = userdata;
228 int32_t n;
229
230 assert(bus);
231 assert(reply);
232 assert(c);
233
234 if (c->cpu_sched_set)
235 n = c->cpu_sched_priority;
236 else {
237 struct sched_param p = {};
238
239 if (sched_getparam(0, &p) >= 0)
240 n = p.sched_priority;
241 else
242 n = 0;
243 }
244
245 return sd_bus_message_append(reply, "i", n);
246 }
247
248 static int property_get_cpu_affinity(
249 sd_bus *bus,
250 const char *path,
251 const char *interface,
252 const char *property,
253 sd_bus_message *reply,
254 void *userdata,
255 sd_bus_error *error) {
256
257 ExecContext *c = userdata;
258
259 assert(bus);
260 assert(reply);
261 assert(c);
262
263 if (c->cpuset)
264 return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
265 else
266 return sd_bus_message_append_array(reply, 'y', NULL, 0);
267 }
268
269 static int property_get_timer_slack_nsec(
270 sd_bus *bus,
271 const char *path,
272 const char *interface,
273 const char *property,
274 sd_bus_message *reply,
275 void *userdata,
276 sd_bus_error *error) {
277
278 ExecContext *c = userdata;
279 uint64_t u;
280
281 assert(bus);
282 assert(reply);
283 assert(c);
284
285 if (c->timer_slack_nsec != (nsec_t) -1)
286 u = (uint64_t) c->timer_slack_nsec;
287 else
288 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
289
290 return sd_bus_message_append(reply, "t", u);
291 }
292
293 static int property_get_capability_bounding_set(
294 sd_bus *bus,
295 const char *path,
296 const char *interface,
297 const char *property,
298 sd_bus_message *reply,
299 void *userdata,
300 sd_bus_error *error) {
301
302 ExecContext *c = userdata;
303
304 assert(bus);
305 assert(reply);
306 assert(c);
307
308 /* We store this negated internally, to match the kernel, but
309 * we expose it normalized. */
310 return sd_bus_message_append(reply, "t", ~c->capability_bounding_set_drop);
311 }
312
313 static int property_get_capabilities(
314 sd_bus *bus,
315 const char *path,
316 const char *interface,
317 const char *property,
318 sd_bus_message *reply,
319 void *userdata,
320 sd_bus_error *error) {
321
322 ExecContext *c = userdata;
323 _cleanup_cap_free_charp_ char *t = NULL;
324 const char *s;
325
326 assert(bus);
327 assert(reply);
328 assert(c);
329
330 if (c->capabilities)
331 s = t = cap_to_text(c->capabilities, NULL);
332 else
333 s = "";
334
335 if (!s)
336 return -ENOMEM;
337
338 return sd_bus_message_append(reply, "s", s);
339 }
340
341 static int property_get_syscall_filter(
342 sd_bus *bus,
343 const char *path,
344 const char *interface,
345 const char *property,
346 sd_bus_message *reply,
347 void *userdata,
348 sd_bus_error *error) {
349
350 ExecContext *c = userdata;
351 _cleanup_strv_free_ char **l = NULL;
352 _cleanup_free_ char *t = NULL;
353 Iterator i;
354 void *id;
355 int r;
356
357 assert(bus);
358 assert(reply);
359 assert(c);
360
361 SET_FOREACH(id, c->syscall_filter, i) {
362 char *name;
363
364 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
365 if (!name)
366 continue;
367
368 r = strv_push(&l, name);
369 if (r < 0) {
370 free(name);
371 return -ENOMEM;
372 }
373 }
374
375 strv_sort(l);
376
377 t = strv_join(l, " ");
378 if (!t)
379 return -ENOMEM;
380
381 if (!c->syscall_whitelist) {
382 char *d;
383
384 d = strappend("~", t);
385 if (!d)
386 return -ENOMEM;
387
388 free(t);
389 t = d;
390 }
391
392 return sd_bus_message_append(reply, "s", t);
393 }
394
395 static int property_get_syscall_errno(
396 sd_bus *bus,
397 const char *path,
398 const char *interface,
399 const char *property,
400 sd_bus_message *reply,
401 void *userdata,
402 sd_bus_error *error) {
403
404 ExecContext *c = userdata;
405
406 assert(bus);
407 assert(reply);
408 assert(c);
409
410 return sd_bus_message_append(reply, "i", (int32_t) c->syscall_errno);
411 }
412
413 const sd_bus_vtable bus_exec_vtable[] = {
414 SD_BUS_VTABLE_START(0),
415 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
416 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
417 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
418 SD_BUS_PROPERTY("LimitCPU", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
419 SD_BUS_PROPERTY("LimitFSIZE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
420 SD_BUS_PROPERTY("LimitDATA", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
421 SD_BUS_PROPERTY("LimitSTACK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
422 SD_BUS_PROPERTY("LimitCORE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
423 SD_BUS_PROPERTY("LimitRSS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
424 SD_BUS_PROPERTY("LimitNOFILE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
425 SD_BUS_PROPERTY("LimitAS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
426 SD_BUS_PROPERTY("LimitNPROC", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
427 SD_BUS_PROPERTY("LimitMEMLOCK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
428 SD_BUS_PROPERTY("LimitLOCKS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
429 SD_BUS_PROPERTY("LimitSIGPENDING", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
430 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
431 SD_BUS_PROPERTY("LimitNICE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
432 SD_BUS_PROPERTY("LimitRTPRIO", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
433 SD_BUS_PROPERTY("LimitRTTIME", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
434 SD_BUS_PROPERTY("WorkingDirectory", "s", NULL, offsetof(ExecContext, working_directory), SD_BUS_VTABLE_PROPERTY_CONST),
435 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
436 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
437 SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
438 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST),
439 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
440 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
441 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
442 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
443 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST),
444 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST),
445 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST),
446 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST),
447 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST),
448 SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST),
449 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
450 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
451 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST),
452 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
453 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
454 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
455 SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
456 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
457 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
458 SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
459 SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
460 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
461 SD_BUS_PROPERTY("TCPWrapName", "s", NULL, offsetof(ExecContext, tcpwrap_name), SD_BUS_VTABLE_PROPERTY_CONST),
462 SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST),
463 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
464 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
465 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
466 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
467 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
468 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
469 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
470 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
471 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
472 SD_BUS_PROPERTY("SELinuxContext", "s", NULL, offsetof(ExecContext, selinux_context), SD_BUS_VTABLE_PROPERTY_CONST),
473 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
474 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
475 SD_BUS_PROPERTY("SystemCallFilter", "s", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
476 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno, 0, SD_BUS_VTABLE_PROPERTY_CONST),
477 SD_BUS_VTABLE_END
478 };
479
480 static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
481 int r;
482
483 assert(reply);
484 assert(c);
485
486 if (!c->path)
487 return 0;
488
489 r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
490 if (r < 0)
491 return r;
492
493 r = sd_bus_message_append(reply, "s", c->path);
494 if (r < 0)
495 return r;
496
497 r = sd_bus_message_append_strv(reply, c->argv);
498 if (r < 0)
499 return r;
500
501 r = sd_bus_message_append(reply, "bttttuii",
502 c->ignore,
503 c->exec_status.start_timestamp.realtime,
504 c->exec_status.start_timestamp.monotonic,
505 c->exec_status.exit_timestamp.realtime,
506 c->exec_status.exit_timestamp.monotonic,
507 (uint32_t) c->exec_status.pid,
508 (int32_t) c->exec_status.code,
509 (int32_t) c->exec_status.status);
510 if (r < 0)
511 return r;
512
513 return sd_bus_message_close_container(reply);
514 }
515
516 int bus_property_get_exec_command(
517 sd_bus *bus,
518 const char *path,
519 const char *interface,
520 const char *property,
521 sd_bus_message *reply,
522 void *userdata,
523 sd_bus_error *ret_error) {
524
525 ExecCommand *c = (ExecCommand*) userdata;
526 int r;
527
528 assert(bus);
529 assert(reply);
530
531 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
532 if (r < 0)
533 return r;
534
535 r = append_exec_command(reply, c);
536 if (r < 0)
537 return r;
538
539 return sd_bus_message_close_container(reply);
540 }
541
542 int bus_property_get_exec_command_list(
543 sd_bus *bus,
544 const char *path,
545 const char *interface,
546 const char *property,
547 sd_bus_message *reply,
548 void *userdata,
549 sd_bus_error *ret_error) {
550
551 ExecCommand *c = *(ExecCommand**) userdata;
552 int r;
553
554 assert(bus);
555 assert(reply);
556
557 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
558 if (r < 0)
559 return r;
560
561 LIST_FOREACH(command, c, c) {
562 r = append_exec_command(reply, c);
563 if (r < 0)
564 return r;
565 }
566
567 return sd_bus_message_close_container(reply);
568 }
569
570 int bus_exec_context_set_transient_property(
571 Unit *u,
572 ExecContext *c,
573 const char *name,
574 sd_bus_message *message,
575 UnitSetPropertiesMode mode,
576 sd_bus_error *error) {
577
578 int r;
579
580 assert(u);
581 assert(c);
582 assert(name);
583 assert(message);
584
585 if (streq(name, "User")) {
586 const char *uu;
587
588 r = sd_bus_message_read(message, "s", &uu);
589 if (r < 0)
590 return r;
591
592 if (mode != UNIT_CHECK) {
593
594 if (isempty(uu)) {
595 free(c->user);
596 c->user = NULL;
597 } else {
598 char *t;
599
600 t = strdup(uu);
601 if (!t)
602 return -ENOMEM;
603
604 free(c->user);
605 c->user = t;
606 }
607
608 unit_write_drop_in_private_format(u, mode, name, "User=%s\n", uu);
609 }
610
611 return 1;
612
613 } else if (streq(name, "Group")) {
614 const char *gg;
615
616 r = sd_bus_message_read(message, "s", &gg);
617 if (r < 0)
618 return r;
619
620 if (mode != UNIT_CHECK) {
621
622 if (isempty(gg)) {
623 free(c->group);
624 c->group = NULL;
625 } else {
626 char *t;
627
628 t = strdup(gg);
629 if (!t)
630 return -ENOMEM;
631
632 free(c->group);
633 c->group = t;
634 }
635
636 unit_write_drop_in_private_format(u, mode, name, "Group=%s\n", gg);
637 }
638
639 return 1;
640
641 } else if (streq(name, "Nice")) {
642 int n;
643
644 r = sd_bus_message_read(message, "i", &n);
645 if (r < 0)
646 return r;
647
648 if (n < PRIO_MIN || n >= PRIO_MAX)
649 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Nice value out of range");
650
651 if (mode != UNIT_CHECK) {
652 c->nice = n;
653 unit_write_drop_in_private_format(u, mode, name, "Nice=%i\n", n);
654 }
655
656 return 1;
657
658 } else if (streq(name, "Environment")) {
659
660 _cleanup_strv_free_ char **l = NULL;
661
662 r = sd_bus_message_read_strv(message, &l);
663 if (r < 0)
664 return r;
665
666 if (!strv_env_is_valid(l))
667 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
668
669 if (mode != UNIT_CHECK) {
670 _cleanup_free_ char *joined = NULL;
671 char **e;
672
673 e = strv_env_merge(2, c->environment, l);
674 if (!e)
675 return -ENOMEM;
676
677 strv_free(c->environment);
678 c->environment = e;
679
680 joined = strv_join(c->environment, " ");
681 if (!joined)
682 return -ENOMEM;
683
684 unit_write_drop_in_private_format(u, mode, name, "Environment=%s\n", joined);
685 }
686
687 return 1;
688 }
689
690 return 0;
691 }