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