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