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