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 static int property_get_selinux_context(
470 const char *interface,
471 const char *property,
472 sd_bus_message *reply,
474 sd_bus_error *error) {
476 ExecContext *c = userdata;
482 return sd_bus_message_append(reply, "(bs)", c->selinux_context_ignore, c->selinux_context);
485 static int property_get_apparmor_profile(
488 const char *interface,
489 const char *property,
490 sd_bus_message *reply,
492 sd_bus_error *error) {
494 ExecContext *c = userdata;
500 return sd_bus_message_append(reply, "(bs)", c->apparmor_profile_ignore, c->apparmor_profile);
503 static int property_get_personality(
506 const char *interface,
507 const char *property,
508 sd_bus_message *reply,
510 sd_bus_error *error) {
512 ExecContext *c = userdata;
518 return sd_bus_message_append(reply, "s", personality_to_string(c->personality));
521 const sd_bus_vtable bus_exec_vtable[] = {
522 SD_BUS_VTABLE_START(0),
523 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
524 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
525 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
526 SD_BUS_PROPERTY("LimitCPU", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
527 SD_BUS_PROPERTY("LimitFSIZE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
528 SD_BUS_PROPERTY("LimitDATA", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
529 SD_BUS_PROPERTY("LimitSTACK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
530 SD_BUS_PROPERTY("LimitCORE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
531 SD_BUS_PROPERTY("LimitRSS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
532 SD_BUS_PROPERTY("LimitNOFILE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
533 SD_BUS_PROPERTY("LimitAS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
534 SD_BUS_PROPERTY("LimitNPROC", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
535 SD_BUS_PROPERTY("LimitMEMLOCK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
536 SD_BUS_PROPERTY("LimitLOCKS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
537 SD_BUS_PROPERTY("LimitSIGPENDING", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
538 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
539 SD_BUS_PROPERTY("LimitNICE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
540 SD_BUS_PROPERTY("LimitRTPRIO", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
541 SD_BUS_PROPERTY("LimitRTTIME", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
542 SD_BUS_PROPERTY("WorkingDirectory", "s", NULL, offsetof(ExecContext, working_directory), SD_BUS_VTABLE_PROPERTY_CONST),
543 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
544 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
545 SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
546 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST),
547 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
548 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
549 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
550 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
551 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST),
552 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST),
553 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST),
554 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST),
555 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST),
556 SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST),
557 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
558 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
559 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST),
560 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
561 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
562 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
563 SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
564 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
565 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
566 SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
567 SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
568 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
569 SD_BUS_PROPERTY("TCPWrapName", "s", NULL, offsetof(ExecContext, tcpwrap_name), SD_BUS_VTABLE_PROPERTY_CONST),
570 SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST),
571 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
572 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
573 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
574 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
575 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
576 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
577 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
578 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
579 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
580 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context, 0, SD_BUS_VTABLE_PROPERTY_CONST),
581 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile, 0, SD_BUS_VTABLE_PROPERTY_CONST),
582 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
583 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
584 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
585 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
586 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno, 0, SD_BUS_VTABLE_PROPERTY_CONST),
587 SD_BUS_PROPERTY("Personality", "s", property_get_personality, 0, SD_BUS_VTABLE_PROPERTY_CONST),
591 static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
600 r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
604 r = sd_bus_message_append(reply, "s", c->path);
608 r = sd_bus_message_append_strv(reply, c->argv);
612 r = sd_bus_message_append(reply, "bttttuii",
614 c->exec_status.start_timestamp.realtime,
615 c->exec_status.start_timestamp.monotonic,
616 c->exec_status.exit_timestamp.realtime,
617 c->exec_status.exit_timestamp.monotonic,
618 (uint32_t) c->exec_status.pid,
619 (int32_t) c->exec_status.code,
620 (int32_t) c->exec_status.status);
624 return sd_bus_message_close_container(reply);
627 int bus_property_get_exec_command(
630 const char *interface,
631 const char *property,
632 sd_bus_message *reply,
634 sd_bus_error *ret_error) {
636 ExecCommand *c = (ExecCommand*) userdata;
642 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
646 r = append_exec_command(reply, c);
650 return sd_bus_message_close_container(reply);
653 int bus_property_get_exec_command_list(
656 const char *interface,
657 const char *property,
658 sd_bus_message *reply,
660 sd_bus_error *ret_error) {
662 ExecCommand *c = *(ExecCommand**) userdata;
668 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
672 LIST_FOREACH(command, c, c) {
673 r = append_exec_command(reply, c);
678 return sd_bus_message_close_container(reply);
681 int bus_exec_context_set_transient_property(
685 sd_bus_message *message,
686 UnitSetPropertiesMode mode,
687 sd_bus_error *error) {
696 if (streq(name, "User")) {
699 r = sd_bus_message_read(message, "s", &uu);
703 if (mode != UNIT_CHECK) {
719 unit_write_drop_in_private_format(u, mode, name, "User=%s\n", uu);
724 } else if (streq(name, "Group")) {
727 r = sd_bus_message_read(message, "s", &gg);
731 if (mode != UNIT_CHECK) {
747 unit_write_drop_in_private_format(u, mode, name, "Group=%s\n", gg);
752 } else if (streq(name, "Nice")) {
755 r = sd_bus_message_read(message, "i", &n);
759 if (n < PRIO_MIN || n >= PRIO_MAX)
760 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Nice value out of range");
762 if (mode != UNIT_CHECK) {
764 unit_write_drop_in_private_format(u, mode, name, "Nice=%i\n", n);
769 } else if (streq(name, "Environment")) {
771 _cleanup_strv_free_ char **l = NULL;
773 r = sd_bus_message_read_strv(message, &l);
777 if (!strv_env_is_valid(l))
778 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
780 if (mode != UNIT_CHECK) {
781 _cleanup_free_ char *joined = NULL;
784 e = strv_env_merge(2, c->environment, l);
788 strv_free(c->environment);
791 joined = strv_join(c->environment, " ");
795 unit_write_drop_in_private_format(u, mode, name, "Environment=%s\n", joined);