1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
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.
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.
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/>.
22 #include <sys/prctl.h>
30 #include "dbus-execute.h"
31 #include "capability.h"
34 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
36 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
38 static int property_get_environment_files(
41 const char *interface,
43 sd_bus_message *reply,
45 sd_bus_error *error) {
47 ExecContext *c = userdata;
55 r = sd_bus_message_open_container(reply, 'a', "(sb)");
59 STRV_FOREACH(j, c->environment_files) {
62 r = sd_bus_message_append(reply, "(sb)", fn[0] == '-' ? fn + 1 : fn, fn[0] == '-');
67 return sd_bus_message_close_container(reply);
70 static int property_get_rlimit(
73 const char *interface,
75 sd_bus_message *reply,
77 sd_bus_error *error) {
86 rl = *(struct rlimit**) userdata;
88 u = (uint64_t) rl->rlim_max;
90 struct rlimit buf = {};
93 z = rlimit_from_string(property);
98 u = (uint64_t) buf.rlim_max;
101 return sd_bus_message_append(reply, "t", u);
104 static int property_get_oom_score_adjust(
107 const char *interface,
108 const char *property,
109 sd_bus_message *reply,
111 sd_bus_error *error) {
114 ExecContext *c = userdata;
121 if (c->oom_score_adjust_set)
122 n = c->oom_score_adjust;
124 _cleanup_free_ char *t = NULL;
127 if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0)
131 return sd_bus_message_append(reply, "i", n);
134 static int property_get_nice(
137 const char *interface,
138 const char *property,
139 sd_bus_message *reply,
141 sd_bus_error *error) {
144 ExecContext *c = userdata;
155 n = getpriority(PRIO_PROCESS, 0);
160 return sd_bus_message_append(reply, "i", n);
163 static int property_get_ioprio(
166 const char *interface,
167 const char *property,
168 sd_bus_message *reply,
170 sd_bus_error *error) {
173 ExecContext *c = userdata;
183 n = ioprio_get(IOPRIO_WHO_PROCESS, 0);
185 n = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4);
188 return sd_bus_message_append(reply, "i", n);
191 static int property_get_cpu_sched_policy(
194 const char *interface,
195 const char *property,
196 sd_bus_message *reply,
198 sd_bus_error *error) {
200 ExecContext *c = userdata;
207 if (c->cpu_sched_set)
208 n = c->cpu_sched_policy;
210 n = sched_getscheduler(0);
215 return sd_bus_message_append(reply, "i", n);
218 static int property_get_cpu_sched_priority(
221 const char *interface,
222 const char *property,
223 sd_bus_message *reply,
225 sd_bus_error *error) {
227 ExecContext *c = userdata;
234 if (c->cpu_sched_set)
235 n = c->cpu_sched_priority;
237 struct sched_param p = {};
239 if (sched_getparam(0, &p) >= 0)
240 n = p.sched_priority;
245 return sd_bus_message_append(reply, "i", n);
248 static int property_get_cpu_affinity(
251 const char *interface,
252 const char *property,
253 sd_bus_message *reply,
255 sd_bus_error *error) {
257 ExecContext *c = userdata;
264 return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
266 return sd_bus_message_append_array(reply, 'y', NULL, 0);
269 static int property_get_timer_slack_nsec(
272 const char *interface,
273 const char *property,
274 sd_bus_message *reply,
276 sd_bus_error *error) {
278 ExecContext *c = userdata;
285 if (c->timer_slack_nsec != (nsec_t) -1)
286 u = (uint64_t) c->timer_slack_nsec;
288 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
290 return sd_bus_message_append(reply, "t", u);
293 static int property_get_capability_bounding_set(
296 const char *interface,
297 const char *property,
298 sd_bus_message *reply,
300 sd_bus_error *error) {
302 ExecContext *c = userdata;
308 /* We store this negated internally, to match the kernel, but
309 * we expose it normalized. */
310 return sd_bus_message_append(reply, "t", ~c->capability_bounding_set_drop);
313 static int property_get_capabilities(
316 const char *interface,
317 const char *property,
318 sd_bus_message *reply,
320 sd_bus_error *error) {
322 ExecContext *c = userdata;
323 _cleanup_cap_free_charp_ char *t = NULL;
331 s = t = cap_to_text(c->capabilities, NULL);
338 return sd_bus_message_append(reply, "s", s);
341 static int property_get_syscall_filter(
344 const char *interface,
345 const char *property,
346 sd_bus_message *reply,
348 sd_bus_error *error) {
350 ExecContext *c = userdata;
351 _cleanup_strv_free_ char **l = NULL;
352 _cleanup_free_ char *t = NULL;
361 SET_FOREACH(id, c->syscall_filter, i) {
364 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
368 r = strv_push(&l, name);
377 t = strv_join(l, " ");
381 if (!c->syscall_whitelist) {
384 d = strappend("~", t);
392 return sd_bus_message_append(reply, "s", t);
395 static int property_get_syscall_errno(
398 const char *interface,
399 const char *property,
400 sd_bus_message *reply,
402 sd_bus_error *error) {
404 ExecContext *c = userdata;
410 return sd_bus_message_append(reply, "i", (int32_t) c->syscall_errno);
413 const sd_bus_vtable bus_exec_vtable[] = {
414 SD_BUS_VTABLE_START(0),
415 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
416 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
417 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
418 SD_BUS_PROPERTY("LimitCPU", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
419 SD_BUS_PROPERTY("LimitFSIZE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
420 SD_BUS_PROPERTY("LimitDATA", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
421 SD_BUS_PROPERTY("LimitSTACK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
422 SD_BUS_PROPERTY("LimitCORE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
423 SD_BUS_PROPERTY("LimitRSS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
424 SD_BUS_PROPERTY("LimitNOFILE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
425 SD_BUS_PROPERTY("LimitAS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
426 SD_BUS_PROPERTY("LimitNPROC", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
427 SD_BUS_PROPERTY("LimitMEMLOCK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
428 SD_BUS_PROPERTY("LimitLOCKS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
429 SD_BUS_PROPERTY("LimitSIGPENDING", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
430 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
431 SD_BUS_PROPERTY("LimitNICE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
432 SD_BUS_PROPERTY("LimitRTPRIO", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
433 SD_BUS_PROPERTY("LimitRTTIME", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
434 SD_BUS_PROPERTY("WorkingDirectory", "s", NULL, offsetof(ExecContext, working_directory), SD_BUS_VTABLE_PROPERTY_CONST),
435 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
436 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
437 SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
438 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST),
439 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
440 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
441 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
442 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
443 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST),
444 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST),
445 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST),
446 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST),
447 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST),
448 SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST),
449 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
450 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
451 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST),
452 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
453 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
454 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
455 SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
456 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
457 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
458 SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
459 SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
460 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
461 SD_BUS_PROPERTY("TCPWrapName", "s", NULL, offsetof(ExecContext, tcpwrap_name), SD_BUS_VTABLE_PROPERTY_CONST),
462 SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST),
463 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
464 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
465 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
466 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
467 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
468 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
469 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
470 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
471 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
472 SD_BUS_PROPERTY("SELinuxContext", "s", NULL, offsetof(ExecContext, selinux_context), SD_BUS_VTABLE_PROPERTY_CONST),
473 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
474 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
475 SD_BUS_PROPERTY("SystemCallFilter", "s", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
476 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno, 0, SD_BUS_VTABLE_PROPERTY_CONST),
480 static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
489 r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
493 r = sd_bus_message_append(reply, "s", c->path);
497 r = sd_bus_message_append_strv(reply, c->argv);
501 r = sd_bus_message_append(reply, "bttttuii",
503 c->exec_status.start_timestamp.realtime,
504 c->exec_status.start_timestamp.monotonic,
505 c->exec_status.exit_timestamp.realtime,
506 c->exec_status.exit_timestamp.monotonic,
507 (uint32_t) c->exec_status.pid,
508 (int32_t) c->exec_status.code,
509 (int32_t) c->exec_status.status);
513 return sd_bus_message_close_container(reply);
516 int bus_property_get_exec_command(
519 const char *interface,
520 const char *property,
521 sd_bus_message *reply,
523 sd_bus_error *ret_error) {
525 ExecCommand *c = (ExecCommand*) userdata;
531 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
535 r = append_exec_command(reply, c);
539 return sd_bus_message_close_container(reply);
542 int bus_property_get_exec_command_list(
545 const char *interface,
546 const char *property,
547 sd_bus_message *reply,
549 sd_bus_error *ret_error) {
551 ExecCommand *c = *(ExecCommand**) userdata;
557 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
561 LIST_FOREACH(command, c, c) {
562 r = append_exec_command(reply, c);
567 return sd_bus_message_close_container(reply);
570 int bus_exec_context_set_transient_property(
574 sd_bus_message *message,
575 UnitSetPropertiesMode mode,
576 sd_bus_error *error) {
585 if (streq(name, "User")) {
588 r = sd_bus_message_read(message, "s", &uu);
592 if (mode != UNIT_CHECK) {
608 unit_write_drop_in_private_format(u, mode, name, "User=%s\n", uu);
613 } else if (streq(name, "Group")) {
616 r = sd_bus_message_read(message, "s", &gg);
620 if (mode != UNIT_CHECK) {
636 unit_write_drop_in_private_format(u, mode, name, "Group=%s\n", gg);
641 } else if (streq(name, "Nice")) {
644 r = sd_bus_message_read(message, "i", &n);
648 if (n < PRIO_MIN || n >= PRIO_MAX)
649 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Nice value out of range");
651 if (mode != UNIT_CHECK) {
653 unit_write_drop_in_private_format(u, mode, name, "Nice=%i\n", n);
658 } else if (streq(name, "Environment")) {
660 _cleanup_strv_free_ char **l = NULL;
662 r = sd_bus_message_read_strv(message, &l);
666 if (!strv_env_is_valid(l))
667 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
669 if (mode != UNIT_CHECK) {
670 _cleanup_free_ char *joined = NULL;
673 e = strv_env_merge(2, c->environment, l);
677 strv_free(c->environment);
680 joined = strv_join(c->environment, " ");
684 unit_write_drop_in_private_format(u, mode, name, "Environment=%s\n", joined);