]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-execute.c
smack: introduce new SmackProcessLabel option
[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_INFINITY)
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_smack_process_label(
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, "(bs)", c->smack_process_label_ignore, c->smack_process_label);
527 }
528
529 static int property_get_personality(
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
540 assert(bus);
541 assert(reply);
542 assert(c);
543
544 return sd_bus_message_append(reply, "s", personality_to_string(c->personality));
545 }
546
547 static int property_get_address_families(
548 sd_bus *bus,
549 const char *path,
550 const char *interface,
551 const char *property,
552 sd_bus_message *reply,
553 void *userdata,
554 sd_bus_error *error) {
555
556 ExecContext *c = userdata;
557 _cleanup_strv_free_ char **l = NULL;
558 Iterator i;
559 void *af;
560 int r;
561
562 assert(bus);
563 assert(reply);
564 assert(c);
565
566 r = sd_bus_message_open_container(reply, 'r', "bas");
567 if (r < 0)
568 return r;
569
570 r = sd_bus_message_append(reply, "b", c->address_families_whitelist);
571 if (r < 0)
572 return r;
573
574 SET_FOREACH(af, c->address_families, i) {
575 const char *name;
576
577 name = af_to_name(PTR_TO_INT(af));
578 if (!name)
579 continue;
580
581 r = strv_extend(&l, name);
582 if (r < 0)
583 return -ENOMEM;
584 }
585
586 strv_sort(l);
587
588 r = sd_bus_message_append_strv(reply, l);
589 if (r < 0)
590 return r;
591
592 return sd_bus_message_close_container(reply);
593 }
594
595 const sd_bus_vtable bus_exec_vtable[] = {
596 SD_BUS_VTABLE_START(0),
597 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
598 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
599 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
600 SD_BUS_PROPERTY("LimitCPU", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
601 SD_BUS_PROPERTY("LimitFSIZE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
602 SD_BUS_PROPERTY("LimitDATA", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
603 SD_BUS_PROPERTY("LimitSTACK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
604 SD_BUS_PROPERTY("LimitCORE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
605 SD_BUS_PROPERTY("LimitRSS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
606 SD_BUS_PROPERTY("LimitNOFILE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
607 SD_BUS_PROPERTY("LimitAS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
608 SD_BUS_PROPERTY("LimitNPROC", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
609 SD_BUS_PROPERTY("LimitMEMLOCK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
610 SD_BUS_PROPERTY("LimitLOCKS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
611 SD_BUS_PROPERTY("LimitSIGPENDING", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
612 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
613 SD_BUS_PROPERTY("LimitNICE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
614 SD_BUS_PROPERTY("LimitRTPRIO", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
615 SD_BUS_PROPERTY("LimitRTTIME", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
616 SD_BUS_PROPERTY("WorkingDirectory", "s", NULL, offsetof(ExecContext, working_directory), SD_BUS_VTABLE_PROPERTY_CONST),
617 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
618 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
619 SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
620 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST),
621 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
622 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
623 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
624 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
625 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST),
626 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST),
627 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST),
628 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST),
629 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST),
630 SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST),
631 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
632 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
633 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST),
634 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
635 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
636 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
637 SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
638 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
639 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
640 SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
641 SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
642 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
643 SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST),
644 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
645 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
646 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
647 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
648 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
649 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
650 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
651 SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST),
652 SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system, offsetof(ExecContext, protect_system), SD_BUS_VTABLE_PROPERTY_CONST),
653 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
654 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
655 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context, 0, SD_BUS_VTABLE_PROPERTY_CONST),
656 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile, 0, SD_BUS_VTABLE_PROPERTY_CONST),
657 SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label, 0, SD_BUS_VTABLE_PROPERTY_CONST),
658 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
659 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
660 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
661 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
662 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno, 0, SD_BUS_VTABLE_PROPERTY_CONST),
663 SD_BUS_PROPERTY("Personality", "s", property_get_personality, 0, SD_BUS_VTABLE_PROPERTY_CONST),
664 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST),
665 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, runtime_directory_mode), SD_BUS_VTABLE_PROPERTY_CONST),
666 SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL, offsetof(ExecContext, runtime_directory), SD_BUS_VTABLE_PROPERTY_CONST),
667 SD_BUS_VTABLE_END
668 };
669
670 static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
671 int r;
672
673 assert(reply);
674 assert(c);
675
676 if (!c->path)
677 return 0;
678
679 r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
680 if (r < 0)
681 return r;
682
683 r = sd_bus_message_append(reply, "s", c->path);
684 if (r < 0)
685 return r;
686
687 r = sd_bus_message_append_strv(reply, c->argv);
688 if (r < 0)
689 return r;
690
691 r = sd_bus_message_append(reply, "bttttuii",
692 c->ignore,
693 c->exec_status.start_timestamp.realtime,
694 c->exec_status.start_timestamp.monotonic,
695 c->exec_status.exit_timestamp.realtime,
696 c->exec_status.exit_timestamp.monotonic,
697 (uint32_t) c->exec_status.pid,
698 (int32_t) c->exec_status.code,
699 (int32_t) c->exec_status.status);
700 if (r < 0)
701 return r;
702
703 return sd_bus_message_close_container(reply);
704 }
705
706 int bus_property_get_exec_command(
707 sd_bus *bus,
708 const char *path,
709 const char *interface,
710 const char *property,
711 sd_bus_message *reply,
712 void *userdata,
713 sd_bus_error *ret_error) {
714
715 ExecCommand *c = (ExecCommand*) userdata;
716 int r;
717
718 assert(bus);
719 assert(reply);
720
721 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
722 if (r < 0)
723 return r;
724
725 r = append_exec_command(reply, c);
726 if (r < 0)
727 return r;
728
729 return sd_bus_message_close_container(reply);
730 }
731
732 int bus_property_get_exec_command_list(
733 sd_bus *bus,
734 const char *path,
735 const char *interface,
736 const char *property,
737 sd_bus_message *reply,
738 void *userdata,
739 sd_bus_error *ret_error) {
740
741 ExecCommand *c = *(ExecCommand**) userdata;
742 int r;
743
744 assert(bus);
745 assert(reply);
746
747 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
748 if (r < 0)
749 return r;
750
751 LIST_FOREACH(command, c, c) {
752 r = append_exec_command(reply, c);
753 if (r < 0)
754 return r;
755 }
756
757 return sd_bus_message_close_container(reply);
758 }
759
760 int bus_exec_context_set_transient_property(
761 Unit *u,
762 ExecContext *c,
763 const char *name,
764 sd_bus_message *message,
765 UnitSetPropertiesMode mode,
766 sd_bus_error *error) {
767
768 int r;
769
770 assert(u);
771 assert(c);
772 assert(name);
773 assert(message);
774
775 if (streq(name, "User")) {
776 const char *uu;
777
778 r = sd_bus_message_read(message, "s", &uu);
779 if (r < 0)
780 return r;
781
782 if (mode != UNIT_CHECK) {
783
784 if (isempty(uu)) {
785 free(c->user);
786 c->user = NULL;
787 } else {
788 char *t;
789
790 t = strdup(uu);
791 if (!t)
792 return -ENOMEM;
793
794 free(c->user);
795 c->user = t;
796 }
797
798 unit_write_drop_in_private_format(u, mode, name, "User=%s\n", uu);
799 }
800
801 return 1;
802
803 } else if (streq(name, "Group")) {
804 const char *gg;
805
806 r = sd_bus_message_read(message, "s", &gg);
807 if (r < 0)
808 return r;
809
810 if (mode != UNIT_CHECK) {
811
812 if (isempty(gg)) {
813 free(c->group);
814 c->group = NULL;
815 } else {
816 char *t;
817
818 t = strdup(gg);
819 if (!t)
820 return -ENOMEM;
821
822 free(c->group);
823 c->group = t;
824 }
825
826 unit_write_drop_in_private_format(u, mode, name, "Group=%s\n", gg);
827 }
828
829 return 1;
830
831 } else if (streq(name, "Nice")) {
832 int n;
833
834 r = sd_bus_message_read(message, "i", &n);
835 if (r < 0)
836 return r;
837
838 if (n < PRIO_MIN || n >= PRIO_MAX)
839 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Nice value out of range");
840
841 if (mode != UNIT_CHECK) {
842 c->nice = n;
843 unit_write_drop_in_private_format(u, mode, name, "Nice=%i\n", n);
844 }
845
846 return 1;
847
848 } else if (streq(name, "Environment")) {
849
850 _cleanup_strv_free_ char **l = NULL;
851
852 r = sd_bus_message_read_strv(message, &l);
853 if (r < 0)
854 return r;
855
856 if (!strv_env_is_valid(l))
857 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
858
859 if (mode != UNIT_CHECK) {
860 _cleanup_free_ char *joined = NULL;
861 char **e;
862
863 e = strv_env_merge(2, c->environment, l);
864 if (!e)
865 return -ENOMEM;
866
867 strv_free(c->environment);
868 c->environment = e;
869
870 joined = strv_join_quoted(c->environment);
871 if (!joined)
872 return -ENOMEM;
873
874 unit_write_drop_in_private_format(u, mode, name, "Environment=%s\n", joined);
875 }
876
877 return 1;
878
879 } else if (rlimit_from_string(name) >= 0) {
880 uint64_t rl;
881 rlim_t x;
882
883 r = sd_bus_message_read(message, "t", &rl);
884 if (r < 0)
885 return r;
886
887 if (rl == (uint64_t) -1)
888 x = RLIM_INFINITY;
889 else {
890 x = (rlim_t) rl;
891
892 if ((uint64_t) x != rl)
893 return -ERANGE;
894 }
895
896 if (mode != UNIT_CHECK) {
897 int z;
898
899 z = rlimit_from_string(name);
900
901 if (!c->rlimit[z]) {
902 c->rlimit[z] = new(struct rlimit, 1);
903 if (!c->rlimit[z])
904 return -ENOMEM;
905 }
906
907 c->rlimit[z]->rlim_cur = c->rlimit[z]->rlim_max = x;
908
909 if (x == RLIM_INFINITY)
910 unit_write_drop_in_private_format(u, mode, name, "%s=infinity\n", name);
911 else
912 unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64 "\n", name, rl);
913 }
914
915 return 1;
916 }
917
918 return 0;
919 }