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