]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-execute.c
core: add new RestrictAddressFamilies= switch
[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 #ifdef HAVE_SECCOMP
25 #include <seccomp.h>
26 #endif
27
28 #include "bus-util.h"
29 #include "missing.h"
30 #include "ioprio.h"
31 #include "strv.h"
32 #include "fileio.h"
33 #include "execute.h"
34 #include "dbus-execute.h"
35 #include "capability.h"
36 #include "env-util.h"
37 #include "af-list.h"
38
39 #ifdef HAVE_SECCOMP
40 #include "seccomp-util.h"
41 #endif
42
43 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
44
45 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
46
47 static int property_get_environment_files(
48 sd_bus *bus,
49 const char *path,
50 const char *interface,
51 const char *property,
52 sd_bus_message *reply,
53 void *userdata,
54 sd_bus_error *error) {
55
56 ExecContext *c = userdata;
57 char **j;
58 int r;
59
60 assert(bus);
61 assert(reply);
62 assert(c);
63
64 r = sd_bus_message_open_container(reply, 'a', "(sb)");
65 if (r < 0)
66 return r;
67
68 STRV_FOREACH(j, c->environment_files) {
69 const char *fn = *j;
70
71 r = sd_bus_message_append(reply, "(sb)", fn[0] == '-' ? fn + 1 : fn, fn[0] == '-');
72 if (r < 0)
73 return r;
74 }
75
76 return sd_bus_message_close_container(reply);
77 }
78
79 static int property_get_rlimit(
80 sd_bus *bus,
81 const char *path,
82 const char *interface,
83 const char *property,
84 sd_bus_message *reply,
85 void *userdata,
86 sd_bus_error *error) {
87
88 struct rlimit *rl;
89 uint64_t u;
90
91 assert(bus);
92 assert(reply);
93 assert(userdata);
94
95 rl = *(struct rlimit**) userdata;
96 if (rl)
97 u = (uint64_t) rl->rlim_max;
98 else {
99 struct rlimit buf = {};
100 int z;
101
102 z = rlimit_from_string(property);
103 assert(z >= 0);
104
105 getrlimit(z, &buf);
106
107 u = (uint64_t) buf.rlim_max;
108 }
109
110 return sd_bus_message_append(reply, "t", u);
111 }
112
113 static int property_get_oom_score_adjust(
114 sd_bus *bus,
115 const char *path,
116 const char *interface,
117 const char *property,
118 sd_bus_message *reply,
119 void *userdata,
120 sd_bus_error *error) {
121
122
123 ExecContext *c = userdata;
124 int32_t n;
125
126 assert(bus);
127 assert(reply);
128 assert(c);
129
130 if (c->oom_score_adjust_set)
131 n = c->oom_score_adjust;
132 else {
133 _cleanup_free_ char *t = NULL;
134
135 n = 0;
136 if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0)
137 safe_atoi(t, &n);
138 }
139
140 return sd_bus_message_append(reply, "i", n);
141 }
142
143 static int property_get_nice(
144 sd_bus *bus,
145 const char *path,
146 const char *interface,
147 const char *property,
148 sd_bus_message *reply,
149 void *userdata,
150 sd_bus_error *error) {
151
152
153 ExecContext *c = userdata;
154 int32_t n;
155
156 assert(bus);
157 assert(reply);
158 assert(c);
159
160 if (c->nice_set)
161 n = c->nice;
162 else {
163 errno = 0;
164 n = getpriority(PRIO_PROCESS, 0);
165 if (errno != 0)
166 n = 0;
167 }
168
169 return sd_bus_message_append(reply, "i", n);
170 }
171
172 static int property_get_ioprio(
173 sd_bus *bus,
174 const char *path,
175 const char *interface,
176 const char *property,
177 sd_bus_message *reply,
178 void *userdata,
179 sd_bus_error *error) {
180
181
182 ExecContext *c = userdata;
183 int32_t n;
184
185 assert(bus);
186 assert(reply);
187 assert(c);
188
189 if (c->ioprio_set)
190 n = c->ioprio;
191 else {
192 n = ioprio_get(IOPRIO_WHO_PROCESS, 0);
193 if (n < 0)
194 n = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4);
195 }
196
197 return sd_bus_message_append(reply, "i", n);
198 }
199
200 static int property_get_cpu_sched_policy(
201 sd_bus *bus,
202 const char *path,
203 const char *interface,
204 const char *property,
205 sd_bus_message *reply,
206 void *userdata,
207 sd_bus_error *error) {
208
209 ExecContext *c = userdata;
210 int32_t n;
211
212 assert(bus);
213 assert(reply);
214 assert(c);
215
216 if (c->cpu_sched_set)
217 n = c->cpu_sched_policy;
218 else {
219 n = sched_getscheduler(0);
220 if (n < 0)
221 n = SCHED_OTHER;
222 }
223
224 return sd_bus_message_append(reply, "i", n);
225 }
226
227 static int property_get_cpu_sched_priority(
228 sd_bus *bus,
229 const char *path,
230 const char *interface,
231 const char *property,
232 sd_bus_message *reply,
233 void *userdata,
234 sd_bus_error *error) {
235
236 ExecContext *c = userdata;
237 int32_t n;
238
239 assert(bus);
240 assert(reply);
241 assert(c);
242
243 if (c->cpu_sched_set)
244 n = c->cpu_sched_priority;
245 else {
246 struct sched_param p = {};
247
248 if (sched_getparam(0, &p) >= 0)
249 n = p.sched_priority;
250 else
251 n = 0;
252 }
253
254 return sd_bus_message_append(reply, "i", n);
255 }
256
257 static int property_get_cpu_affinity(
258 sd_bus *bus,
259 const char *path,
260 const char *interface,
261 const char *property,
262 sd_bus_message *reply,
263 void *userdata,
264 sd_bus_error *error) {
265
266 ExecContext *c = userdata;
267
268 assert(bus);
269 assert(reply);
270 assert(c);
271
272 if (c->cpuset)
273 return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
274 else
275 return sd_bus_message_append_array(reply, 'y', NULL, 0);
276 }
277
278 static int property_get_timer_slack_nsec(
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 uint64_t u;
289
290 assert(bus);
291 assert(reply);
292 assert(c);
293
294 if (c->timer_slack_nsec != (nsec_t) -1)
295 u = (uint64_t) c->timer_slack_nsec;
296 else
297 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
298
299 return sd_bus_message_append(reply, "t", u);
300 }
301
302 static int property_get_capability_bounding_set(
303 sd_bus *bus,
304 const char *path,
305 const char *interface,
306 const char *property,
307 sd_bus_message *reply,
308 void *userdata,
309 sd_bus_error *error) {
310
311 ExecContext *c = userdata;
312
313 assert(bus);
314 assert(reply);
315 assert(c);
316
317 /* We store this negated internally, to match the kernel, but
318 * we expose it normalized. */
319 return sd_bus_message_append(reply, "t", ~c->capability_bounding_set_drop);
320 }
321
322 static int property_get_capabilities(
323 sd_bus *bus,
324 const char *path,
325 const char *interface,
326 const char *property,
327 sd_bus_message *reply,
328 void *userdata,
329 sd_bus_error *error) {
330
331 ExecContext *c = userdata;
332 _cleanup_cap_free_charp_ char *t = NULL;
333 const char *s;
334
335 assert(bus);
336 assert(reply);
337 assert(c);
338
339 if (c->capabilities)
340 s = t = cap_to_text(c->capabilities, NULL);
341 else
342 s = "";
343
344 if (!s)
345 return -ENOMEM;
346
347 return sd_bus_message_append(reply, "s", s);
348 }
349
350 static int property_get_syscall_filter(
351 sd_bus *bus,
352 const char *path,
353 const char *interface,
354 const char *property,
355 sd_bus_message *reply,
356 void *userdata,
357 sd_bus_error *error) {
358
359 ExecContext *c = userdata;
360 _cleanup_strv_free_ char **l = NULL;
361 int r;
362
363 #ifdef HAVE_SECCOMP
364 Iterator i;
365 void *id;
366 #endif
367
368 assert(bus);
369 assert(reply);
370 assert(c);
371
372 r = sd_bus_message_open_container(reply, 'r', "bas");
373 if (r < 0)
374 return r;
375
376 r = sd_bus_message_append(reply, "b", c->syscall_whitelist);
377 if (r < 0)
378 return r;
379
380 #ifdef HAVE_SECCOMP
381 SET_FOREACH(id, c->syscall_filter, i) {
382 char *name;
383
384 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
385 if (!name)
386 continue;
387
388 r = strv_push(&l, name);
389 if (r < 0) {
390 free(name);
391 return -ENOMEM;
392 }
393 }
394 #endif
395
396 strv_sort(l);
397
398 r = sd_bus_message_append_strv(reply, l);
399 if (r < 0)
400 return r;
401
402 return sd_bus_message_close_container(reply);
403 }
404
405 static int property_get_syscall_archs(
406 sd_bus *bus,
407 const char *path,
408 const char *interface,
409 const char *property,
410 sd_bus_message *reply,
411 void *userdata,
412 sd_bus_error *error) {
413
414 ExecContext *c = userdata;
415 _cleanup_strv_free_ char **l = NULL;
416 int r;
417
418 #ifdef HAVE_SECCOMP
419 Iterator i;
420 void *id;
421 #endif
422
423 assert(bus);
424 assert(reply);
425 assert(c);
426
427 #ifdef HAVE_SECCOMP
428 SET_FOREACH(id, c->syscall_archs, i) {
429 const char *name;
430
431 name = seccomp_arch_to_string(PTR_TO_UINT32(id) - 1);
432 if (!name)
433 continue;
434
435 r = strv_extend(&l, name);
436 if (r < 0)
437 return -ENOMEM;
438 }
439 #endif
440
441 strv_sort(l);
442
443 r = sd_bus_message_append_strv(reply, l);
444 if (r < 0)
445 return r;
446
447 return 0;
448 }
449
450 static int property_get_syscall_errno(
451 sd_bus *bus,
452 const char *path,
453 const char *interface,
454 const char *property,
455 sd_bus_message *reply,
456 void *userdata,
457 sd_bus_error *error) {
458
459 ExecContext *c = userdata;
460
461 assert(bus);
462 assert(reply);
463 assert(c);
464
465 return sd_bus_message_append(reply, "i", (int32_t) c->syscall_errno);
466 }
467
468 static int property_get_selinux_context(
469 sd_bus *bus,
470 const char *path,
471 const char *interface,
472 const char *property,
473 sd_bus_message *reply,
474 void *userdata,
475 sd_bus_error *error) {
476
477 ExecContext *c = userdata;
478
479 assert(bus);
480 assert(reply);
481 assert(c);
482
483 return sd_bus_message_append(reply, "(bs)", c->selinux_context_ignore, c->selinux_context);
484 }
485
486 static int property_get_apparmor_profile(
487 sd_bus *bus,
488 const char *path,
489 const char *interface,
490 const char *property,
491 sd_bus_message *reply,
492 void *userdata,
493 sd_bus_error *error) {
494
495 ExecContext *c = userdata;
496
497 assert(bus);
498 assert(reply);
499 assert(c);
500
501 return sd_bus_message_append(reply, "(bs)", c->apparmor_profile_ignore, c->apparmor_profile);
502 }
503
504 static int property_get_personality(
505 sd_bus *bus,
506 const char *path,
507 const char *interface,
508 const char *property,
509 sd_bus_message *reply,
510 void *userdata,
511 sd_bus_error *error) {
512
513 ExecContext *c = userdata;
514
515 assert(bus);
516 assert(reply);
517 assert(c);
518
519 return sd_bus_message_append(reply, "s", personality_to_string(c->personality));
520 }
521
522 static int property_get_address_families(
523 sd_bus *bus,
524 const char *path,
525 const char *interface,
526 const char *property,
527 sd_bus_message *reply,
528 void *userdata,
529 sd_bus_error *error) {
530
531 ExecContext *c = userdata;
532 _cleanup_strv_free_ char **l = NULL;
533 Iterator i;
534 void *af;
535 int r;
536
537 assert(bus);
538 assert(reply);
539 assert(c);
540
541 r = sd_bus_message_open_container(reply, 'r', "bas");
542 if (r < 0)
543 return r;
544
545 r = sd_bus_message_append(reply, "b", c->address_families_whitelist);
546 if (r < 0)
547 return r;
548
549 SET_FOREACH(af, c->address_families, i) {
550 const char *name;
551
552 name = af_to_name(PTR_TO_INT(af));
553 if (!name)
554 continue;
555
556 r = strv_extend(&l, name);
557 if (r < 0)
558 return -ENOMEM;
559 }
560
561 strv_sort(l);
562
563 r = sd_bus_message_append_strv(reply, l);
564 if (r < 0)
565 return r;
566
567 return sd_bus_message_close_container(reply);
568 }
569
570 const sd_bus_vtable bus_exec_vtable[] = {
571 SD_BUS_VTABLE_START(0),
572 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
573 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
574 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
575 SD_BUS_PROPERTY("LimitCPU", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
576 SD_BUS_PROPERTY("LimitFSIZE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
577 SD_BUS_PROPERTY("LimitDATA", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
578 SD_BUS_PROPERTY("LimitSTACK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
579 SD_BUS_PROPERTY("LimitCORE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
580 SD_BUS_PROPERTY("LimitRSS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
581 SD_BUS_PROPERTY("LimitNOFILE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
582 SD_BUS_PROPERTY("LimitAS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
583 SD_BUS_PROPERTY("LimitNPROC", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
584 SD_BUS_PROPERTY("LimitMEMLOCK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
585 SD_BUS_PROPERTY("LimitLOCKS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
586 SD_BUS_PROPERTY("LimitSIGPENDING", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
587 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
588 SD_BUS_PROPERTY("LimitNICE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
589 SD_BUS_PROPERTY("LimitRTPRIO", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
590 SD_BUS_PROPERTY("LimitRTTIME", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
591 SD_BUS_PROPERTY("WorkingDirectory", "s", NULL, offsetof(ExecContext, working_directory), SD_BUS_VTABLE_PROPERTY_CONST),
592 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
593 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
594 SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
595 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST),
596 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
597 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
598 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
599 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
600 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST),
601 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST),
602 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST),
603 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST),
604 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST),
605 SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST),
606 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
607 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
608 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST),
609 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
610 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
611 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
612 SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
613 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
614 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
615 SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
616 SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
617 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
618 SD_BUS_PROPERTY("TCPWrapName", "s", NULL, offsetof(ExecContext, tcpwrap_name), SD_BUS_VTABLE_PROPERTY_CONST),
619 SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST),
620 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
621 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
622 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
623 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
624 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
625 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
626 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
627 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
628 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
629 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context, 0, SD_BUS_VTABLE_PROPERTY_CONST),
630 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile, 0, SD_BUS_VTABLE_PROPERTY_CONST),
631 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
632 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
633 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
634 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
635 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno, 0, SD_BUS_VTABLE_PROPERTY_CONST),
636 SD_BUS_PROPERTY("Personality", "s", property_get_personality, 0, SD_BUS_VTABLE_PROPERTY_CONST),
637 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST),
638 SD_BUS_VTABLE_END
639 };
640
641 static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
642 int r;
643
644 assert(reply);
645 assert(c);
646
647 if (!c->path)
648 return 0;
649
650 r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
651 if (r < 0)
652 return r;
653
654 r = sd_bus_message_append(reply, "s", c->path);
655 if (r < 0)
656 return r;
657
658 r = sd_bus_message_append_strv(reply, c->argv);
659 if (r < 0)
660 return r;
661
662 r = sd_bus_message_append(reply, "bttttuii",
663 c->ignore,
664 c->exec_status.start_timestamp.realtime,
665 c->exec_status.start_timestamp.monotonic,
666 c->exec_status.exit_timestamp.realtime,
667 c->exec_status.exit_timestamp.monotonic,
668 (uint32_t) c->exec_status.pid,
669 (int32_t) c->exec_status.code,
670 (int32_t) c->exec_status.status);
671 if (r < 0)
672 return r;
673
674 return sd_bus_message_close_container(reply);
675 }
676
677 int bus_property_get_exec_command(
678 sd_bus *bus,
679 const char *path,
680 const char *interface,
681 const char *property,
682 sd_bus_message *reply,
683 void *userdata,
684 sd_bus_error *ret_error) {
685
686 ExecCommand *c = (ExecCommand*) userdata;
687 int r;
688
689 assert(bus);
690 assert(reply);
691
692 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
693 if (r < 0)
694 return r;
695
696 r = append_exec_command(reply, c);
697 if (r < 0)
698 return r;
699
700 return sd_bus_message_close_container(reply);
701 }
702
703 int bus_property_get_exec_command_list(
704 sd_bus *bus,
705 const char *path,
706 const char *interface,
707 const char *property,
708 sd_bus_message *reply,
709 void *userdata,
710 sd_bus_error *ret_error) {
711
712 ExecCommand *c = *(ExecCommand**) userdata;
713 int r;
714
715 assert(bus);
716 assert(reply);
717
718 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
719 if (r < 0)
720 return r;
721
722 LIST_FOREACH(command, c, c) {
723 r = append_exec_command(reply, c);
724 if (r < 0)
725 return r;
726 }
727
728 return sd_bus_message_close_container(reply);
729 }
730
731 int bus_exec_context_set_transient_property(
732 Unit *u,
733 ExecContext *c,
734 const char *name,
735 sd_bus_message *message,
736 UnitSetPropertiesMode mode,
737 sd_bus_error *error) {
738
739 int r;
740
741 assert(u);
742 assert(c);
743 assert(name);
744 assert(message);
745
746 if (streq(name, "User")) {
747 const char *uu;
748
749 r = sd_bus_message_read(message, "s", &uu);
750 if (r < 0)
751 return r;
752
753 if (mode != UNIT_CHECK) {
754
755 if (isempty(uu)) {
756 free(c->user);
757 c->user = NULL;
758 } else {
759 char *t;
760
761 t = strdup(uu);
762 if (!t)
763 return -ENOMEM;
764
765 free(c->user);
766 c->user = t;
767 }
768
769 unit_write_drop_in_private_format(u, mode, name, "User=%s\n", uu);
770 }
771
772 return 1;
773
774 } else if (streq(name, "Group")) {
775 const char *gg;
776
777 r = sd_bus_message_read(message, "s", &gg);
778 if (r < 0)
779 return r;
780
781 if (mode != UNIT_CHECK) {
782
783 if (isempty(gg)) {
784 free(c->group);
785 c->group = NULL;
786 } else {
787 char *t;
788
789 t = strdup(gg);
790 if (!t)
791 return -ENOMEM;
792
793 free(c->group);
794 c->group = t;
795 }
796
797 unit_write_drop_in_private_format(u, mode, name, "Group=%s\n", gg);
798 }
799
800 return 1;
801
802 } else if (streq(name, "Nice")) {
803 int n;
804
805 r = sd_bus_message_read(message, "i", &n);
806 if (r < 0)
807 return r;
808
809 if (n < PRIO_MIN || n >= PRIO_MAX)
810 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Nice value out of range");
811
812 if (mode != UNIT_CHECK) {
813 c->nice = n;
814 unit_write_drop_in_private_format(u, mode, name, "Nice=%i\n", n);
815 }
816
817 return 1;
818
819 } else if (streq(name, "Environment")) {
820
821 _cleanup_strv_free_ char **l = NULL;
822
823 r = sd_bus_message_read_strv(message, &l);
824 if (r < 0)
825 return r;
826
827 if (!strv_env_is_valid(l))
828 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
829
830 if (mode != UNIT_CHECK) {
831 _cleanup_free_ char *joined = NULL;
832 char **e;
833
834 e = strv_env_merge(2, c->environment, l);
835 if (!e)
836 return -ENOMEM;
837
838 strv_free(c->environment);
839 c->environment = e;
840
841 joined = strv_join(c->environment, " ");
842 if (!joined)
843 return -ENOMEM;
844
845 unit_write_drop_in_private_format(u, mode, name, "Environment=%s\n", joined);
846 }
847
848 return 1;
849 }
850
851 return 0;
852 }