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>
34 #include "dbus-execute.h"
35 #include "capability.h"
39 #include "seccomp-util.h"
42 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
44 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
46 static int property_get_environment_files(
49 const char *interface,
51 sd_bus_message *reply,
53 sd_bus_error *error) {
55 ExecContext *c = userdata;
63 r = sd_bus_message_open_container(reply, 'a', "(sb)");
67 STRV_FOREACH(j, c->environment_files) {
70 r = sd_bus_message_append(reply, "(sb)", fn[0] == '-' ? fn + 1 : fn, fn[0] == '-');
75 return sd_bus_message_close_container(reply);
78 static int property_get_rlimit(
81 const char *interface,
83 sd_bus_message *reply,
85 sd_bus_error *error) {
94 rl = *(struct rlimit**) userdata;
96 u = (uint64_t) rl->rlim_max;
98 struct rlimit buf = {};
101 z = rlimit_from_string(property);
106 u = (uint64_t) buf.rlim_max;
109 return sd_bus_message_append(reply, "t", u);
112 static int property_get_oom_score_adjust(
115 const char *interface,
116 const char *property,
117 sd_bus_message *reply,
119 sd_bus_error *error) {
122 ExecContext *c = userdata;
129 if (c->oom_score_adjust_set)
130 n = c->oom_score_adjust;
132 _cleanup_free_ char *t = NULL;
135 if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0)
139 return sd_bus_message_append(reply, "i", n);
142 static int property_get_nice(
145 const char *interface,
146 const char *property,
147 sd_bus_message *reply,
149 sd_bus_error *error) {
152 ExecContext *c = userdata;
163 n = getpriority(PRIO_PROCESS, 0);
168 return sd_bus_message_append(reply, "i", n);
171 static int property_get_ioprio(
174 const char *interface,
175 const char *property,
176 sd_bus_message *reply,
178 sd_bus_error *error) {
181 ExecContext *c = userdata;
191 n = ioprio_get(IOPRIO_WHO_PROCESS, 0);
193 n = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4);
196 return sd_bus_message_append(reply, "i", n);
199 static int property_get_cpu_sched_policy(
202 const char *interface,
203 const char *property,
204 sd_bus_message *reply,
206 sd_bus_error *error) {
208 ExecContext *c = userdata;
215 if (c->cpu_sched_set)
216 n = c->cpu_sched_policy;
218 n = sched_getscheduler(0);
223 return sd_bus_message_append(reply, "i", n);
226 static int property_get_cpu_sched_priority(
229 const char *interface,
230 const char *property,
231 sd_bus_message *reply,
233 sd_bus_error *error) {
235 ExecContext *c = userdata;
242 if (c->cpu_sched_set)
243 n = c->cpu_sched_priority;
245 struct sched_param p = {};
247 if (sched_getparam(0, &p) >= 0)
248 n = p.sched_priority;
253 return sd_bus_message_append(reply, "i", n);
256 static int property_get_cpu_affinity(
259 const char *interface,
260 const char *property,
261 sd_bus_message *reply,
263 sd_bus_error *error) {
265 ExecContext *c = userdata;
272 return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
274 return sd_bus_message_append_array(reply, 'y', NULL, 0);
277 static int property_get_timer_slack_nsec(
280 const char *interface,
281 const char *property,
282 sd_bus_message *reply,
284 sd_bus_error *error) {
286 ExecContext *c = userdata;
293 if (c->timer_slack_nsec != (nsec_t) -1)
294 u = (uint64_t) c->timer_slack_nsec;
296 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
298 return sd_bus_message_append(reply, "t", u);
301 static int property_get_capability_bounding_set(
304 const char *interface,
305 const char *property,
306 sd_bus_message *reply,
308 sd_bus_error *error) {
310 ExecContext *c = userdata;
316 /* We store this negated internally, to match the kernel, but
317 * we expose it normalized. */
318 return sd_bus_message_append(reply, "t", ~c->capability_bounding_set_drop);
321 static int property_get_capabilities(
324 const char *interface,
325 const char *property,
326 sd_bus_message *reply,
328 sd_bus_error *error) {
330 ExecContext *c = userdata;
331 _cleanup_cap_free_charp_ char *t = NULL;
339 s = t = cap_to_text(c->capabilities, NULL);
346 return sd_bus_message_append(reply, "s", s);
349 static int property_get_syscall_filter(
352 const char *interface,
353 const char *property,
354 sd_bus_message *reply,
356 sd_bus_error *error) {
358 ExecContext *c = userdata;
359 _cleanup_strv_free_ char **l = NULL;
371 r = sd_bus_message_open_container(reply, 'r', "bas");
375 r = sd_bus_message_append(reply, "b", c->syscall_whitelist);
380 SET_FOREACH(id, c->syscall_filter, i) {
383 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
387 r = strv_push(&l, name);
397 r = sd_bus_message_append_strv(reply, l);
401 return sd_bus_message_close_container(reply);
404 static int property_get_syscall_archs(
407 const char *interface,
408 const char *property,
409 sd_bus_message *reply,
411 sd_bus_error *error) {
413 ExecContext *c = userdata;
414 _cleanup_strv_free_ char **l = NULL;
427 SET_FOREACH(id, c->syscall_archs, i) {
430 name = seccomp_arch_to_string(PTR_TO_UINT32(id) - 1);
434 r = strv_extend(&l, name);
442 r = sd_bus_message_append_strv(reply, l);
449 static int property_get_syscall_errno(
452 const char *interface,
453 const char *property,
454 sd_bus_message *reply,
456 sd_bus_error *error) {
458 ExecContext *c = userdata;
464 return sd_bus_message_append(reply, "i", (int32_t) c->syscall_errno);
467 const sd_bus_vtable bus_exec_vtable[] = {
468 SD_BUS_VTABLE_START(0),
469 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
470 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
471 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
472 SD_BUS_PROPERTY("LimitCPU", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
473 SD_BUS_PROPERTY("LimitFSIZE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
474 SD_BUS_PROPERTY("LimitDATA", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
475 SD_BUS_PROPERTY("LimitSTACK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
476 SD_BUS_PROPERTY("LimitCORE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
477 SD_BUS_PROPERTY("LimitRSS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
478 SD_BUS_PROPERTY("LimitNOFILE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
479 SD_BUS_PROPERTY("LimitAS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
480 SD_BUS_PROPERTY("LimitNPROC", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
481 SD_BUS_PROPERTY("LimitMEMLOCK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
482 SD_BUS_PROPERTY("LimitLOCKS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
483 SD_BUS_PROPERTY("LimitSIGPENDING", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
484 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
485 SD_BUS_PROPERTY("LimitNICE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
486 SD_BUS_PROPERTY("LimitRTPRIO", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
487 SD_BUS_PROPERTY("LimitRTTIME", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
488 SD_BUS_PROPERTY("WorkingDirectory", "s", NULL, offsetof(ExecContext, working_directory), SD_BUS_VTABLE_PROPERTY_CONST),
489 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
490 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
491 SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
492 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST),
493 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
494 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
495 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
496 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
497 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST),
498 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST),
499 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST),
500 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST),
501 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST),
502 SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST),
503 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
504 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
505 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST),
506 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
507 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
508 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
509 SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
510 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
511 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
512 SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
513 SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
514 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
515 SD_BUS_PROPERTY("TCPWrapName", "s", NULL, offsetof(ExecContext, tcpwrap_name), SD_BUS_VTABLE_PROPERTY_CONST),
516 SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST),
517 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
518 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
519 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
520 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
521 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
522 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
523 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
524 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
525 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
526 SD_BUS_PROPERTY("SELinuxContext", "s", NULL, offsetof(ExecContext, selinux_context), SD_BUS_VTABLE_PROPERTY_CONST),
527 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
528 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
529 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
530 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
531 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno, 0, SD_BUS_VTABLE_PROPERTY_CONST),
535 static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
544 r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
548 r = sd_bus_message_append(reply, "s", c->path);
552 r = sd_bus_message_append_strv(reply, c->argv);
556 r = sd_bus_message_append(reply, "bttttuii",
558 c->exec_status.start_timestamp.realtime,
559 c->exec_status.start_timestamp.monotonic,
560 c->exec_status.exit_timestamp.realtime,
561 c->exec_status.exit_timestamp.monotonic,
562 (uint32_t) c->exec_status.pid,
563 (int32_t) c->exec_status.code,
564 (int32_t) c->exec_status.status);
568 return sd_bus_message_close_container(reply);
571 int bus_property_get_exec_command(
574 const char *interface,
575 const char *property,
576 sd_bus_message *reply,
578 sd_bus_error *ret_error) {
580 ExecCommand *c = (ExecCommand*) userdata;
586 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
590 r = append_exec_command(reply, c);
594 return sd_bus_message_close_container(reply);
597 int bus_property_get_exec_command_list(
600 const char *interface,
601 const char *property,
602 sd_bus_message *reply,
604 sd_bus_error *ret_error) {
606 ExecCommand *c = *(ExecCommand**) userdata;
612 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
616 LIST_FOREACH(command, c, c) {
617 r = append_exec_command(reply, c);
622 return sd_bus_message_close_container(reply);
625 int bus_exec_context_set_transient_property(
629 sd_bus_message *message,
630 UnitSetPropertiesMode mode,
631 sd_bus_error *error) {
640 if (streq(name, "User")) {
643 r = sd_bus_message_read(message, "s", &uu);
647 if (mode != UNIT_CHECK) {
663 unit_write_drop_in_private_format(u, mode, name, "User=%s\n", uu);
668 } else if (streq(name, "Group")) {
671 r = sd_bus_message_read(message, "s", &gg);
675 if (mode != UNIT_CHECK) {
691 unit_write_drop_in_private_format(u, mode, name, "Group=%s\n", gg);
696 } else if (streq(name, "Nice")) {
699 r = sd_bus_message_read(message, "i", &n);
703 if (n < PRIO_MIN || n >= PRIO_MAX)
704 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Nice value out of range");
706 if (mode != UNIT_CHECK) {
708 unit_write_drop_in_private_format(u, mode, name, "Nice=%i\n", n);
713 } else if (streq(name, "Environment")) {
715 _cleanup_strv_free_ char **l = NULL;
717 r = sd_bus_message_read_strv(message, &l);
721 if (!strv_env_is_valid(l))
722 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
724 if (mode != UNIT_CHECK) {
725 _cleanup_free_ char *joined = NULL;
728 e = strv_env_merge(2, c->environment, l);
732 strv_free(c->environment);
735 joined = strv_join(c->environment, " ");
739 unit_write_drop_in_private_format(u, mode, name, "Environment=%s\n", joined);