]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-execute.c
systemd-run can now launch units with SyslogLevelPrefix
[thirdparty/systemd.git] / src / core / dbus-execute.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4139c1b2
LP
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
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
4139c1b2
LP
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 16 Lesser General Public License for more details.
4139c1b2 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
4139c1b2
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
82c121a4 22#include <sys/prctl.h>
4139c1b2 23
57183d11
LP
24#ifdef HAVE_SECCOMP
25#include <seccomp.h>
26#endif
27
718db961 28#include "bus-util.h"
82c121a4
LP
29#include "missing.h"
30#include "ioprio.h"
fe68089d 31#include "strv.h"
a5c32cff 32#include "fileio.h"
718db961 33#include "execute.h"
5ce70e5b 34#include "capability.h"
c7040b5d 35#include "env-util.h"
4298d0b5 36#include "af-list.h"
417116f2 37#include "namespace.h"
9b15b784
LP
38#include "path-util.h"
39#include "dbus-execute.h"
4139c1b2 40
57183d11
LP
41#ifdef HAVE_SECCOMP
42#include "seccomp-util.h"
43#endif
44
718db961 45BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
82c121a4 46
718db961 47static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
8c7be95e 48
023a4f67
LP
49static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode);
50
1b8689f9
LP
51static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_home, protect_home, ProtectHome);
52static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_system, protect_system, ProtectSystem);
417116f2 53
718db961
LP
54static int property_get_environment_files(
55 sd_bus *bus,
56 const char *path,
57 const char *interface,
58 const char *property,
59 sd_bus_message *reply,
ebcf1f97
LP
60 void *userdata,
61 sd_bus_error *error) {
8c7be95e 62
718db961
LP
63 ExecContext *c = userdata;
64 char **j;
65 int r;
8c7be95e 66
718db961
LP
67 assert(bus);
68 assert(reply);
69 assert(c);
70
71 r = sd_bus_message_open_container(reply, 'a', "(sb)");
72 if (r < 0)
73 return r;
8c7be95e 74
718db961
LP
75 STRV_FOREACH(j, c->environment_files) {
76 const char *fn = *j;
8c7be95e 77
718db961
LP
78 r = sd_bus_message_append(reply, "(sb)", fn[0] == '-' ? fn + 1 : fn, fn[0] == '-');
79 if (r < 0)
80 return r;
8c7be95e
LP
81 }
82
718db961
LP
83 return sd_bus_message_close_container(reply);
84}
85
86static int property_get_rlimit(
87 sd_bus *bus,
88 const char *path,
89 const char *interface,
90 const char *property,
91 sd_bus_message *reply,
ebcf1f97
LP
92 void *userdata,
93 sd_bus_error *error) {
718db961
LP
94
95 struct rlimit *rl;
96 uint64_t u;
a049d1a9 97 rlim_t x;
718db961
LP
98
99 assert(bus);
100 assert(reply);
101 assert(userdata);
8c7be95e 102
718db961
LP
103 rl = *(struct rlimit**) userdata;
104 if (rl)
a049d1a9 105 x = rl->rlim_max;
718db961
LP
106 else {
107 struct rlimit buf = {};
108 int z;
109
110 z = rlimit_from_string(property);
111 assert(z >= 0);
112
113 getrlimit(z, &buf);
a049d1a9 114 x = buf.rlim_max;
718db961
LP
115 }
116
a049d1a9
LP
117 /* rlim_t might have different sizes, let's map
118 * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
119 * all archs */
120 u = x == RLIM_INFINITY ? (uint64_t) -1 : (uint64_t) x;
121
718db961 122 return sd_bus_message_append(reply, "t", u);
8c7be95e
LP
123}
124
718db961
LP
125static int property_get_oom_score_adjust(
126 sd_bus *bus,
127 const char *path,
128 const char *interface,
129 const char *property,
130 sd_bus_message *reply,
ebcf1f97
LP
131 void *userdata,
132 sd_bus_error *error) {
718db961
LP
133
134
135 ExecContext *c = userdata;
82c121a4
LP
136 int32_t n;
137
718db961
LP
138 assert(bus);
139 assert(reply);
82c121a4
LP
140 assert(c);
141
dd6c17b1
LP
142 if (c->oom_score_adjust_set)
143 n = c->oom_score_adjust;
82c121a4 144 else {
68eda4bd 145 _cleanup_free_ char *t = NULL;
82c121a4
LP
146
147 n = 0;
718db961 148 if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0)
82c121a4 149 safe_atoi(t, &n);
82c121a4
LP
150 }
151
718db961 152 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
153}
154
718db961
LP
155static int property_get_nice(
156 sd_bus *bus,
157 const char *path,
158 const char *interface,
159 const char *property,
160 sd_bus_message *reply,
ebcf1f97
LP
161 void *userdata,
162 sd_bus_error *error) {
718db961
LP
163
164
165 ExecContext *c = userdata;
82c121a4
LP
166 int32_t n;
167
718db961
LP
168 assert(bus);
169 assert(reply);
82c121a4
LP
170 assert(c);
171
172 if (c->nice_set)
173 n = c->nice;
718db961
LP
174 else {
175 errno = 0;
82c121a4 176 n = getpriority(PRIO_PROCESS, 0);
718db961
LP
177 if (errno != 0)
178 n = 0;
179 }
82c121a4 180
718db961 181 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
182}
183
718db961
LP
184static int property_get_ioprio(
185 sd_bus *bus,
186 const char *path,
187 const char *interface,
188 const char *property,
189 sd_bus_message *reply,
ebcf1f97
LP
190 void *userdata,
191 sd_bus_error *error) {
718db961
LP
192
193
194 ExecContext *c = userdata;
82c121a4
LP
195 int32_t n;
196
718db961
LP
197 assert(bus);
198 assert(reply);
82c121a4
LP
199 assert(c);
200
201 if (c->ioprio_set)
202 n = c->ioprio;
718db961 203 else {
82c121a4 204 n = ioprio_get(IOPRIO_WHO_PROCESS, 0);
718db961
LP
205 if (n < 0)
206 n = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4);
207 }
82c121a4 208
718db961 209 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
210}
211
718db961
LP
212static int property_get_cpu_sched_policy(
213 sd_bus *bus,
214 const char *path,
215 const char *interface,
216 const char *property,
217 sd_bus_message *reply,
ebcf1f97
LP
218 void *userdata,
219 sd_bus_error *error) {
718db961
LP
220
221 ExecContext *c = userdata;
82c121a4
LP
222 int32_t n;
223
718db961
LP
224 assert(bus);
225 assert(reply);
82c121a4
LP
226 assert(c);
227
228 if (c->cpu_sched_set)
229 n = c->cpu_sched_policy;
718db961 230 else {
82c121a4 231 n = sched_getscheduler(0);
718db961
LP
232 if (n < 0)
233 n = SCHED_OTHER;
234 }
82c121a4 235
718db961 236 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
237}
238
718db961
LP
239static int property_get_cpu_sched_priority(
240 sd_bus *bus,
241 const char *path,
242 const char *interface,
243 const char *property,
244 sd_bus_message *reply,
ebcf1f97
LP
245 void *userdata,
246 sd_bus_error *error) {
718db961
LP
247
248 ExecContext *c = userdata;
82c121a4
LP
249 int32_t n;
250
718db961
LP
251 assert(bus);
252 assert(reply);
82c121a4
LP
253 assert(c);
254
255 if (c->cpu_sched_set)
256 n = c->cpu_sched_priority;
257 else {
b92bea5d 258 struct sched_param p = {};
82c121a4 259
82c121a4
LP
260 if (sched_getparam(0, &p) >= 0)
261 n = p.sched_priority;
e62d8c39
ZJS
262 else
263 n = 0;
82c121a4
LP
264 }
265
718db961 266 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
267}
268
718db961
LP
269static int property_get_cpu_affinity(
270 sd_bus *bus,
271 const char *path,
272 const char *interface,
273 const char *property,
274 sd_bus_message *reply,
ebcf1f97
LP
275 void *userdata,
276 sd_bus_error *error) {
82c121a4 277
718db961 278 ExecContext *c = userdata;
82c121a4 279
718db961
LP
280 assert(bus);
281 assert(reply);
282 assert(c);
82c121a4
LP
283
284 if (c->cpuset)
718db961 285 return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
82c121a4 286 else
718db961 287 return sd_bus_message_append_array(reply, 'y', NULL, 0);
82c121a4
LP
288}
289
718db961
LP
290static int property_get_timer_slack_nsec(
291 sd_bus *bus,
292 const char *path,
293 const char *interface,
294 const char *property,
295 sd_bus_message *reply,
ebcf1f97
LP
296 void *userdata,
297 sd_bus_error *error) {
718db961
LP
298
299 ExecContext *c = userdata;
82c121a4
LP
300 uint64_t u;
301
718db961
LP
302 assert(bus);
303 assert(reply);
82c121a4
LP
304 assert(c);
305
3a43da28 306 if (c->timer_slack_nsec != NSEC_INFINITY)
03fae018 307 u = (uint64_t) c->timer_slack_nsec;
82c121a4
LP
308 else
309 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
310
718db961 311 return sd_bus_message_append(reply, "t", u);
82c121a4
LP
312}
313
718db961
LP
314static int property_get_capability_bounding_set(
315 sd_bus *bus,
316 const char *path,
317 const char *interface,
318 const char *property,
319 sd_bus_message *reply,
ebcf1f97
LP
320 void *userdata,
321 sd_bus_error *error) {
260abb78 322
718db961
LP
323 ExecContext *c = userdata;
324
325 assert(bus);
326 assert(reply);
260abb78
LP
327 assert(c);
328
7c3d67ef 329 /* We store this negated internally, to match the kernel, but
260abb78 330 * we expose it normalized. */
718db961 331 return sd_bus_message_append(reply, "t", ~c->capability_bounding_set_drop);
260abb78
LP
332}
333
718db961
LP
334static int property_get_capabilities(
335 sd_bus *bus,
336 const char *path,
337 const char *interface,
338 const char *property,
339 sd_bus_message *reply,
ebcf1f97
LP
340 void *userdata,
341 sd_bus_error *error) {
718db961
LP
342
343 ExecContext *c = userdata;
5ce70e5b 344 _cleanup_cap_free_charp_ char *t = NULL;
82c121a4 345 const char *s;
82c121a4 346
718db961
LP
347 assert(bus);
348 assert(reply);
82c121a4
LP
349 assert(c);
350
351 if (c->capabilities)
352 s = t = cap_to_text(c->capabilities, NULL);
353 else
354 s = "";
355
674cdd19 356 if (!s)
82c121a4
LP
357 return -ENOMEM;
358
5ce70e5b 359 return sd_bus_message_append(reply, "s", s);
82c121a4
LP
360}
361
718db961
LP
362static int property_get_syscall_filter(
363 sd_bus *bus,
364 const char *path,
365 const char *interface,
366 const char *property,
367 sd_bus_message *reply,
ebcf1f97
LP
368 void *userdata,
369 sd_bus_error *error) {
82c121a4 370
17df7223
LP
371 ExecContext *c = userdata;
372 _cleanup_strv_free_ char **l = NULL;
57183d11
LP
373 int r;
374
351a19b1 375#ifdef HAVE_SECCOMP
17df7223
LP
376 Iterator i;
377 void *id;
351a19b1 378#endif
17df7223
LP
379
380 assert(bus);
381 assert(reply);
382 assert(c);
383
57183d11
LP
384 r = sd_bus_message_open_container(reply, 'r', "bas");
385 if (r < 0)
386 return r;
387
388 r = sd_bus_message_append(reply, "b", c->syscall_whitelist);
389 if (r < 0)
390 return r;
391
351a19b1 392#ifdef HAVE_SECCOMP
17df7223
LP
393 SET_FOREACH(id, c->syscall_filter, i) {
394 char *name;
395
396 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
397 if (!name)
398 continue;
399
6e18964d
ZJS
400 r = strv_consume(&l, name);
401 if (r < 0)
402 return r;
17df7223 403 }
351a19b1 404#endif
17df7223
LP
405
406 strv_sort(l);
407
57183d11
LP
408 r = sd_bus_message_append_strv(reply, l);
409 if (r < 0)
410 return r;
17df7223 411
57183d11
LP
412 return sd_bus_message_close_container(reply);
413}
17df7223 414
57183d11
LP
415static int property_get_syscall_archs(
416 sd_bus *bus,
417 const char *path,
418 const char *interface,
419 const char *property,
420 sd_bus_message *reply,
421 void *userdata,
422 sd_bus_error *error) {
423
424 ExecContext *c = userdata;
425 _cleanup_strv_free_ char **l = NULL;
426 int r;
427
428#ifdef HAVE_SECCOMP
429 Iterator i;
430 void *id;
431#endif
432
433 assert(bus);
434 assert(reply);
435 assert(c);
17df7223 436
57183d11
LP
437#ifdef HAVE_SECCOMP
438 SET_FOREACH(id, c->syscall_archs, i) {
439 const char *name;
440
441 name = seccomp_arch_to_string(PTR_TO_UINT32(id) - 1);
442 if (!name)
443 continue;
444
445 r = strv_extend(&l, name);
446 if (r < 0)
447 return -ENOMEM;
17df7223 448 }
57183d11
LP
449#endif
450
451 strv_sort(l);
452
453 r = sd_bus_message_append_strv(reply, l);
454 if (r < 0)
455 return r;
17df7223 456
57183d11 457 return 0;
17df7223
LP
458}
459
460static int property_get_syscall_errno(
461 sd_bus *bus,
462 const char *path,
463 const char *interface,
464 const char *property,
465 sd_bus_message *reply,
466 void *userdata,
467 sd_bus_error *error) {
468
718db961 469 ExecContext *c = userdata;
82c121a4 470
718db961
LP
471 assert(bus);
472 assert(reply);
473 assert(c);
82c121a4 474
17df7223 475 return sd_bus_message_append(reply, "i", (int32_t) c->syscall_errno);
718db961 476}
82c121a4 477
5f8640fb
LP
478static int property_get_selinux_context(
479 sd_bus *bus,
480 const char *path,
481 const char *interface,
482 const char *property,
483 sd_bus_message *reply,
484 void *userdata,
485 sd_bus_error *error) {
486
487 ExecContext *c = userdata;
488
489 assert(bus);
490 assert(reply);
491 assert(c);
492
493 return sd_bus_message_append(reply, "(bs)", c->selinux_context_ignore, c->selinux_context);
494}
495
eef65bf3
MS
496static int property_get_apparmor_profile(
497 sd_bus *bus,
498 const char *path,
499 const char *interface,
500 const char *property,
501 sd_bus_message *reply,
502 void *userdata,
503 sd_bus_error *error) {
504
505 ExecContext *c = userdata;
506
507 assert(bus);
508 assert(reply);
509 assert(c);
510
511 return sd_bus_message_append(reply, "(bs)", c->apparmor_profile_ignore, c->apparmor_profile);
512}
513
2ca620c4
WC
514static int property_get_smack_process_label(
515 sd_bus *bus,
516 const char *path,
517 const char *interface,
518 const char *property,
519 sd_bus_message *reply,
520 void *userdata,
521 sd_bus_error *error) {
522
523 ExecContext *c = userdata;
524
525 assert(bus);
526 assert(reply);
527 assert(c);
528
529 return sd_bus_message_append(reply, "(bs)", c->smack_process_label_ignore, c->smack_process_label);
530}
531
ac45f971
LP
532static int property_get_personality(
533 sd_bus *bus,
534 const char *path,
535 const char *interface,
536 const char *property,
537 sd_bus_message *reply,
538 void *userdata,
539 sd_bus_error *error) {
540
541 ExecContext *c = userdata;
542
543 assert(bus);
544 assert(reply);
545 assert(c);
546
547 return sd_bus_message_append(reply, "s", personality_to_string(c->personality));
548}
549
4298d0b5
LP
550static int property_get_address_families(
551 sd_bus *bus,
552 const char *path,
553 const char *interface,
554 const char *property,
555 sd_bus_message *reply,
556 void *userdata,
557 sd_bus_error *error) {
558
559 ExecContext *c = userdata;
560 _cleanup_strv_free_ char **l = NULL;
561 Iterator i;
562 void *af;
563 int r;
564
565 assert(bus);
566 assert(reply);
567 assert(c);
568
569 r = sd_bus_message_open_container(reply, 'r', "bas");
570 if (r < 0)
571 return r;
572
573 r = sd_bus_message_append(reply, "b", c->address_families_whitelist);
574 if (r < 0)
575 return r;
576
577 SET_FOREACH(af, c->address_families, i) {
578 const char *name;
579
580 name = af_to_name(PTR_TO_INT(af));
581 if (!name)
582 continue;
583
584 r = strv_extend(&l, name);
585 if (r < 0)
586 return -ENOMEM;
587 }
588
589 strv_sort(l);
590
591 r = sd_bus_message_append_strv(reply, l);
592 if (r < 0)
593 return r;
594
595 return sd_bus_message_close_container(reply);
596}
597
5f5d8eab
LP
598static int property_get_working_directory(
599 sd_bus *bus,
600 const char *path,
601 const char *interface,
602 const char *property,
603 sd_bus_message *reply,
604 void *userdata,
605 sd_bus_error *error) {
606
607 ExecContext *c = userdata;
608 const char *wd;
609
610 assert(bus);
611 assert(reply);
612 assert(c);
613
614 if (c->working_directory_home)
615 wd = "~";
616 else
617 wd = c->working_directory;
618
619 if (c->working_directory_missing_ok)
620 wd = strjoina("!", wd);
621
622 return sd_bus_message_append(reply, "s", wd);
623}
624
718db961
LP
625const sd_bus_vtable bus_exec_vtable[] = {
626 SD_BUS_VTABLE_START(0),
556089dc
LP
627 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
628 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
629 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
630 SD_BUS_PROPERTY("LimitCPU", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
631 SD_BUS_PROPERTY("LimitFSIZE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
632 SD_BUS_PROPERTY("LimitDATA", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
633 SD_BUS_PROPERTY("LimitSTACK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
634 SD_BUS_PROPERTY("LimitCORE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
635 SD_BUS_PROPERTY("LimitRSS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
636 SD_BUS_PROPERTY("LimitNOFILE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
637 SD_BUS_PROPERTY("LimitAS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
638 SD_BUS_PROPERTY("LimitNPROC", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
639 SD_BUS_PROPERTY("LimitMEMLOCK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
640 SD_BUS_PROPERTY("LimitLOCKS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
641 SD_BUS_PROPERTY("LimitSIGPENDING", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
642 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
643 SD_BUS_PROPERTY("LimitNICE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
644 SD_BUS_PROPERTY("LimitRTPRIO", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
645 SD_BUS_PROPERTY("LimitRTTIME", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
5f5d8eab 646 SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
647 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
648 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
649 SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
650 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST),
651 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
652 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
653 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
654 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
655 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST),
656 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST),
657 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST),
658 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST),
659 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST),
660 SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST),
661 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
662 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
663 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST),
664 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
665 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
666 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
667 SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
668 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
669 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
670 SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
671 SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
672 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
673 SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST),
674 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
675 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
676 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
677 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
678 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
679 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
7f112f50 680 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
1b8689f9
LP
681 SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST),
682 SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system, offsetof(ExecContext, protect_system), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
683 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
684 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
023a4f67 685 SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode, offsetof(ExecContext, utmp_mode), SD_BUS_VTABLE_PROPERTY_CONST),
5f8640fb 686 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context, 0, SD_BUS_VTABLE_PROPERTY_CONST),
eef65bf3 687 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2ca620c4 688 SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
689 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
690 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
57183d11
LP
691 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
692 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
17df7223 693 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno, 0, SD_BUS_VTABLE_PROPERTY_CONST),
ac45f971 694 SD_BUS_PROPERTY("Personality", "s", property_get_personality, 0, SD_BUS_VTABLE_PROPERTY_CONST),
4298d0b5 695 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST),
e66cf1a3
LP
696 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, runtime_directory_mode), SD_BUS_VTABLE_PROPERTY_CONST),
697 SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL, offsetof(ExecContext, runtime_directory), SD_BUS_VTABLE_PROPERTY_CONST),
718db961
LP
698 SD_BUS_VTABLE_END
699};
82c121a4 700
4d4c80d0
LP
701static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
702 int r;
703
704 assert(reply);
705 assert(c);
706
707 if (!c->path)
708 return 0;
709
710 r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
711 if (r < 0)
712 return r;
713
714 r = sd_bus_message_append(reply, "s", c->path);
715 if (r < 0)
716 return r;
717
718 r = sd_bus_message_append_strv(reply, c->argv);
719 if (r < 0)
720 return r;
721
722 r = sd_bus_message_append(reply, "bttttuii",
723 c->ignore,
724 c->exec_status.start_timestamp.realtime,
725 c->exec_status.start_timestamp.monotonic,
726 c->exec_status.exit_timestamp.realtime,
727 c->exec_status.exit_timestamp.monotonic,
728 (uint32_t) c->exec_status.pid,
729 (int32_t) c->exec_status.code,
730 (int32_t) c->exec_status.status);
731 if (r < 0)
732 return r;
733
734 return sd_bus_message_close_container(reply);
735}
736
718db961
LP
737int bus_property_get_exec_command(
738 sd_bus *bus,
739 const char *path,
740 const char *interface,
741 const char *property,
742 sd_bus_message *reply,
ebcf1f97
LP
743 void *userdata,
744 sd_bus_error *ret_error) {
fe68089d 745
4d4c80d0 746 ExecCommand *c = (ExecCommand*) userdata;
718db961 747 int r;
fe68089d 748
718db961
LP
749 assert(bus);
750 assert(reply);
fe68089d 751
718db961
LP
752 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
753 if (r < 0)
754 return r;
fe68089d 755
4d4c80d0
LP
756 r = append_exec_command(reply, c);
757 if (r < 0)
758 return r;
fe68089d 759
4d4c80d0
LP
760 return sd_bus_message_close_container(reply);
761}
718db961 762
4d4c80d0
LP
763int bus_property_get_exec_command_list(
764 sd_bus *bus,
765 const char *path,
766 const char *interface,
767 const char *property,
768 sd_bus_message *reply,
769 void *userdata,
770 sd_bus_error *ret_error) {
718db961 771
4d4c80d0
LP
772 ExecCommand *c = *(ExecCommand**) userdata;
773 int r;
718db961 774
4d4c80d0
LP
775 assert(bus);
776 assert(reply);
777
778 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
779 if (r < 0)
780 return r;
718db961 781
4d4c80d0
LP
782 LIST_FOREACH(command, c, c) {
783 r = append_exec_command(reply, c);
718db961
LP
784 if (r < 0)
785 return r;
fe68089d
LP
786 }
787
718db961 788 return sd_bus_message_close_container(reply);
8351ceae 789}
c7040b5d
LP
790
791int bus_exec_context_set_transient_property(
792 Unit *u,
793 ExecContext *c,
794 const char *name,
795 sd_bus_message *message,
796 UnitSetPropertiesMode mode,
797 sd_bus_error *error) {
798
799 int r;
800
801 assert(u);
802 assert(c);
803 assert(name);
804 assert(message);
805
806 if (streq(name, "User")) {
807 const char *uu;
808
809 r = sd_bus_message_read(message, "s", &uu);
810 if (r < 0)
811 return r;
812
813 if (mode != UNIT_CHECK) {
814
815 if (isempty(uu)) {
a1e58e8e 816 c->user = mfree(c->user);
c7040b5d
LP
817 } else {
818 char *t;
819
820 t = strdup(uu);
821 if (!t)
822 return -ENOMEM;
823
824 free(c->user);
825 c->user = t;
826 }
827
828 unit_write_drop_in_private_format(u, mode, name, "User=%s\n", uu);
829 }
830
831 return 1;
832
833 } else if (streq(name, "Group")) {
834 const char *gg;
835
836 r = sd_bus_message_read(message, "s", &gg);
837 if (r < 0)
838 return r;
839
840 if (mode != UNIT_CHECK) {
841
842 if (isempty(gg)) {
a1e58e8e 843 c->group = mfree(c->group);
c7040b5d
LP
844 } else {
845 char *t;
846
847 t = strdup(gg);
848 if (!t)
849 return -ENOMEM;
850
851 free(c->group);
852 c->group = t;
853 }
854
855 unit_write_drop_in_private_format(u, mode, name, "Group=%s\n", gg);
856 }
857
858 return 1;
859
860 } else if (streq(name, "Nice")) {
861 int n;
862
863 r = sd_bus_message_read(message, "i", &n);
864 if (r < 0)
865 return r;
866
867 if (n < PRIO_MIN || n >= PRIO_MAX)
868 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Nice value out of range");
869
870 if (mode != UNIT_CHECK) {
871 c->nice = n;
872 unit_write_drop_in_private_format(u, mode, name, "Nice=%i\n", n);
873 }
874
875 return 1;
876
5f5d8eab 877 } else if (STR_IN_SET(name, "TTYPath", "RootDirectory")) {
602b8355 878 const char *s;
9b15b784 879
602b8355 880 r = sd_bus_message_read(message, "s", &s);
9b15b784
LP
881 if (r < 0)
882 return r;
883
602b8355
NC
884 if (!path_is_absolute(s))
885 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s takes an absolute path", name);
9b15b784
LP
886
887 if (mode != UNIT_CHECK) {
5f5d8eab
LP
888 if (streq(name, "TTYPath"))
889 r = free_and_strdup(&c->tty_path, s);
890 else {
891 assert(streq(name, "RootDirectory"));
892 r = free_and_strdup(&c->root_directory, s);
602b8355 893 }
5f5d8eab
LP
894 if (r < 0)
895 return r;
9b15b784 896
602b8355 897 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, s);
9b15b784
LP
898 }
899
900 return 1;
901
5f5d8eab
LP
902 } else if (streq(name, "WorkingDirectory")) {
903 const char *s;
904 bool missing_ok;
905
906 r = sd_bus_message_read(message, "s", &s);
907 if (r < 0)
908 return r;
909
910 if (s[0] == '-') {
911 missing_ok = true;
912 s++;
913 } else
914 missing_ok = false;
915
916 if (!streq(s, "~") && !path_is_absolute(s))
917 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "WorkingDirectory= expects an absolute path or '~'");
918
919 if (mode != UNIT_CHECK) {
920 if (streq(s, "~")) {
921 c->working_directory = mfree(c->working_directory);
922 c->working_directory_home = true;
923 } else {
924 r = free_and_strdup(&c->working_directory, s);
925 if (r < 0)
926 return r;
927
928 c->working_directory_home = false;
929 }
930
931 c->working_directory_missing_ok = missing_ok;
932 unit_write_drop_in_private_format(u, mode, name, "WorkingDirectory=%s%s", missing_ok ? "-" : "", s);
933 }
934
935 return 1;
936
9b15b784
LP
937 } else if (streq(name, "StandardInput")) {
938 const char *s;
939 ExecInput p;
940
941 r = sd_bus_message_read(message, "s", &s);
942 if (r < 0)
943 return r;
944
945 p = exec_input_from_string(s);
946 if (p < 0)
947 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard input name");
948
949 if (mode != UNIT_CHECK) {
950 c->std_input = p;
951
952 unit_write_drop_in_private_format(u, mode, name, "StandardInput=%s\n", exec_input_to_string(p));
953 }
954
955 return 1;
956
957
958 } else if (streq(name, "StandardOutput")) {
959 const char *s;
960 ExecOutput p;
961
962 r = sd_bus_message_read(message, "s", &s);
963 if (r < 0)
964 return r;
965
966 p = exec_output_from_string(s);
967 if (p < 0)
968 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard output name");
969
970 if (mode != UNIT_CHECK) {
971 c->std_output = p;
972
973 unit_write_drop_in_private_format(u, mode, name, "StandardOutput=%s\n", exec_output_to_string(p));
974 }
975
976 return 1;
977
978 } else if (streq(name, "StandardError")) {
979 const char *s;
980 ExecOutput p;
981
982 r = sd_bus_message_read(message, "s", &s);
983 if (r < 0)
984 return r;
985
986 p = exec_output_from_string(s);
987 if (p < 0)
988 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard error name");
989
990 if (mode != UNIT_CHECK) {
991 c->std_error = p;
992
993 unit_write_drop_in_private_format(u, mode, name, "StandardError=%s\n", exec_output_to_string(p));
994 }
995
996 return 1;
997
b9c50073
GP
998 } else if (STR_IN_SET(name,
999 "IgnoreSIGPIPE", "TTYVHangup", "TTYReset",
1000 "PrivateTmp", "PrivateDevices", "PrivateNetwork",
047d9933 1001 "NoNewPrivileges", "SyslogLevelPrefix")) {
506711fd
LP
1002 int b;
1003
1004 r = sd_bus_message_read(message, "b", &b);
1005 if (r < 0)
1006 return r;
1007
1008 if (mode != UNIT_CHECK) {
b9c50073
GP
1009 if (streq(name, "IgnoreSIGPIPE"))
1010 c->ignore_sigpipe = b;
1011 else if (streq(name, "TTYVHangup"))
1012 c->tty_vhangup = b;
1013 else if (streq(name, "TTYReset"))
1014 c->tty_reset = b;
1015 else if (streq(name, "PrivateTmp"))
1016 c->private_tmp = b;
1017 else if (streq(name, "PrivateDevices"))
1018 c->private_devices = b;
1019 else if (streq(name, "PrivateNetwork"))
1020 c->private_network = b;
1021 else if (streq(name, "NoNewPrivileges"))
1022 c->no_new_privileges = b;
047d9933
EV
1023 else if (streq(name, "SyslogLevelPrefix"))
1024 c->syslog_level_prefix = b;
b9c50073
GP
1025
1026 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, yes_no(b));
506711fd
LP
1027 }
1028
1029 return 1;
1030
1031 } else if (streq(name, "UtmpIdentifier")) {
1032 const char *id;
1033
1034 r = sd_bus_message_read(message, "s", &id);
1035 if (r < 0)
1036 return r;
1037
1038 if (mode != UNIT_CHECK) {
1039 if (isempty(id))
1040 c->utmp_id = mfree(c->utmp_id);
1041 else if (free_and_strdup(&c->utmp_id, id) < 0)
1042 return -ENOMEM;
1043
1044 unit_write_drop_in_private_format(u, mode, name, "UtmpIdentifier=%s\n", strempty(id));
1045 }
1046
1047 return 1;
1048
1049 } else if (streq(name, "UtmpMode")) {
1050 const char *s;
1051 ExecUtmpMode m;
1052
1053 r = sd_bus_message_read(message, "s", &s);
1054 if (r < 0)
1055 return r;
1056
1057 m = exec_utmp_mode_from_string(s);
1058 if (m < 0)
1059 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid utmp mode");
1060
1061 if (mode != UNIT_CHECK) {
1062 c->utmp_mode = m;
1063
1064 unit_write_drop_in_private_format(u, mode, name, "UtmpMode=%s\n", exec_utmp_mode_to_string(m));
1065 }
1066
1067 return 1;
1068
1069 } else if (streq(name, "PAMName")) {
1070 const char *n;
1071
1072 r = sd_bus_message_read(message, "s", &n);
1073 if (r < 0)
1074 return r;
1075
1076 if (mode != UNIT_CHECK) {
1077 if (isempty(n))
1078 c->pam_name = mfree(c->pam_name);
1079 else if (free_and_strdup(&c->pam_name, n) < 0)
1080 return -ENOMEM;
1081
1082 unit_write_drop_in_private_format(u, mode, name, "PAMName=%s\n", strempty(n));
1083 }
1084
1085 return 1;
1086
c7040b5d
LP
1087 } else if (streq(name, "Environment")) {
1088
1089 _cleanup_strv_free_ char **l = NULL;
1090
1091 r = sd_bus_message_read_strv(message, &l);
1092 if (r < 0)
1093 return r;
1094
1095 if (!strv_env_is_valid(l))
1096 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
1097
1098 if (mode != UNIT_CHECK) {
1006a62d 1099 _cleanup_free_ char *joined = NULL;
c7040b5d
LP
1100 char **e;
1101
1102 e = strv_env_merge(2, c->environment, l);
1103 if (!e)
1104 return -ENOMEM;
1105
1106 strv_free(c->environment);
1107 c->environment = e;
1108
cdd7b7df 1109 joined = strv_join_quoted(c->environment);
c7040b5d
LP
1110 if (!joined)
1111 return -ENOMEM;
1112
1113 unit_write_drop_in_private_format(u, mode, name, "Environment=%s\n", joined);
1114 }
1115
d584f638
LP
1116 return 1;
1117
1118 } else if (rlimit_from_string(name) >= 0) {
1119 uint64_t rl;
1120 rlim_t x;
1121
1122 r = sd_bus_message_read(message, "t", &rl);
1123 if (r < 0)
1124 return r;
1125
1126 if (rl == (uint64_t) -1)
1127 x = RLIM_INFINITY;
1128 else {
1129 x = (rlim_t) rl;
1130
1131 if ((uint64_t) x != rl)
1132 return -ERANGE;
1133 }
1134
1135 if (mode != UNIT_CHECK) {
1136 int z;
1137
1138 z = rlimit_from_string(name);
1139
1140 if (!c->rlimit[z]) {
1141 c->rlimit[z] = new(struct rlimit, 1);
1142 if (!c->rlimit[z])
1143 return -ENOMEM;
1144 }
1145
1146 c->rlimit[z]->rlim_cur = c->rlimit[z]->rlim_max = x;
1147
1148 if (x == RLIM_INFINITY)
1149 unit_write_drop_in_private_format(u, mode, name, "%s=infinity\n", name);
1150 else
1151 unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64 "\n", name, rl);
1152 }
1153
c7040b5d
LP
1154 return 1;
1155 }
1156
1157 return 0;
1158}