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