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