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 "capability.h"
37 #include "namespace.h"
38 #include "path-util.h"
40 #include "dbus-execute.h"
43 #include "seccomp-util.h"
46 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output
, exec_output
, ExecOutput
);
48 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input
, exec_input
, ExecInput
);
50 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_utmp_mode
, exec_utmp_mode
, ExecUtmpMode
);
52 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_home
, protect_home
, ProtectHome
);
53 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_system
, protect_system
, ProtectSystem
);
55 static int property_get_environment_files(
58 const char *interface
,
60 sd_bus_message
*reply
,
62 sd_bus_error
*error
) {
64 ExecContext
*c
= userdata
;
72 r
= sd_bus_message_open_container(reply
, 'a', "(sb)");
76 STRV_FOREACH(j
, c
->environment_files
) {
79 r
= sd_bus_message_append(reply
, "(sb)", fn
[0] == '-' ? fn
+ 1 : fn
, fn
[0] == '-');
84 return sd_bus_message_close_container(reply
);
87 static int property_get_oom_score_adjust(
90 const char *interface
,
92 sd_bus_message
*reply
,
94 sd_bus_error
*error
) {
97 ExecContext
*c
= userdata
;
104 if (c
->oom_score_adjust_set
)
105 n
= c
->oom_score_adjust
;
107 _cleanup_free_
char *t
= NULL
;
110 if (read_one_line_file("/proc/self/oom_score_adj", &t
) >= 0)
114 return sd_bus_message_append(reply
, "i", n
);
117 static int property_get_nice(
120 const char *interface
,
121 const char *property
,
122 sd_bus_message
*reply
,
124 sd_bus_error
*error
) {
127 ExecContext
*c
= userdata
;
138 n
= getpriority(PRIO_PROCESS
, 0);
143 return sd_bus_message_append(reply
, "i", n
);
146 static int property_get_ioprio(
149 const char *interface
,
150 const char *property
,
151 sd_bus_message
*reply
,
153 sd_bus_error
*error
) {
156 ExecContext
*c
= userdata
;
166 n
= ioprio_get(IOPRIO_WHO_PROCESS
, 0);
168 n
= IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE
, 4);
171 return sd_bus_message_append(reply
, "i", n
);
174 static int property_get_cpu_sched_policy(
177 const char *interface
,
178 const char *property
,
179 sd_bus_message
*reply
,
181 sd_bus_error
*error
) {
183 ExecContext
*c
= userdata
;
190 if (c
->cpu_sched_set
)
191 n
= c
->cpu_sched_policy
;
193 n
= sched_getscheduler(0);
198 return sd_bus_message_append(reply
, "i", n
);
201 static int property_get_cpu_sched_priority(
204 const char *interface
,
205 const char *property
,
206 sd_bus_message
*reply
,
208 sd_bus_error
*error
) {
210 ExecContext
*c
= userdata
;
217 if (c
->cpu_sched_set
)
218 n
= c
->cpu_sched_priority
;
220 struct sched_param p
= {};
222 if (sched_getparam(0, &p
) >= 0)
223 n
= p
.sched_priority
;
228 return sd_bus_message_append(reply
, "i", n
);
231 static int property_get_cpu_affinity(
234 const char *interface
,
235 const char *property
,
236 sd_bus_message
*reply
,
238 sd_bus_error
*error
) {
240 ExecContext
*c
= userdata
;
247 return sd_bus_message_append_array(reply
, 'y', c
->cpuset
, CPU_ALLOC_SIZE(c
->cpuset_ncpus
));
249 return sd_bus_message_append_array(reply
, 'y', NULL
, 0);
252 static int property_get_timer_slack_nsec(
255 const char *interface
,
256 const char *property
,
257 sd_bus_message
*reply
,
259 sd_bus_error
*error
) {
261 ExecContext
*c
= userdata
;
268 if (c
->timer_slack_nsec
!= NSEC_INFINITY
)
269 u
= (uint64_t) c
->timer_slack_nsec
;
271 u
= (uint64_t) prctl(PR_GET_TIMERSLACK
);
273 return sd_bus_message_append(reply
, "t", u
);
276 static int property_get_capability_bounding_set(
279 const char *interface
,
280 const char *property
,
281 sd_bus_message
*reply
,
283 sd_bus_error
*error
) {
285 ExecContext
*c
= userdata
;
291 /* We store this negated internally, to match the kernel, but
292 * we expose it normalized. */
293 return sd_bus_message_append(reply
, "t", ~c
->capability_bounding_set_drop
);
296 static int property_get_capabilities(
299 const char *interface
,
300 const char *property
,
301 sd_bus_message
*reply
,
303 sd_bus_error
*error
) {
305 ExecContext
*c
= userdata
;
306 _cleanup_cap_free_charp_
char *t
= NULL
;
314 s
= t
= cap_to_text(c
->capabilities
, NULL
);
321 return sd_bus_message_append(reply
, "s", s
);
324 static int property_get_syscall_filter(
327 const char *interface
,
328 const char *property
,
329 sd_bus_message
*reply
,
331 sd_bus_error
*error
) {
333 ExecContext
*c
= userdata
;
334 _cleanup_strv_free_
char **l
= NULL
;
346 r
= sd_bus_message_open_container(reply
, 'r', "bas");
350 r
= sd_bus_message_append(reply
, "b", c
->syscall_whitelist
);
355 SET_FOREACH(id
, c
->syscall_filter
, i
) {
358 name
= seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE
, PTR_TO_INT(id
) - 1);
362 r
= strv_consume(&l
, name
);
370 r
= sd_bus_message_append_strv(reply
, l
);
374 return sd_bus_message_close_container(reply
);
377 static int property_get_syscall_archs(
380 const char *interface
,
381 const char *property
,
382 sd_bus_message
*reply
,
384 sd_bus_error
*error
) {
386 ExecContext
*c
= userdata
;
387 _cleanup_strv_free_
char **l
= NULL
;
400 SET_FOREACH(id
, c
->syscall_archs
, i
) {
403 name
= seccomp_arch_to_string(PTR_TO_UINT32(id
) - 1);
407 r
= strv_extend(&l
, name
);
415 r
= sd_bus_message_append_strv(reply
, l
);
422 static int property_get_syscall_errno(
425 const char *interface
,
426 const char *property
,
427 sd_bus_message
*reply
,
429 sd_bus_error
*error
) {
431 ExecContext
*c
= userdata
;
437 return sd_bus_message_append(reply
, "i", (int32_t) c
->syscall_errno
);
440 static int property_get_selinux_context(
443 const char *interface
,
444 const char *property
,
445 sd_bus_message
*reply
,
447 sd_bus_error
*error
) {
449 ExecContext
*c
= userdata
;
455 return sd_bus_message_append(reply
, "(bs)", c
->selinux_context_ignore
, c
->selinux_context
);
458 static int property_get_apparmor_profile(
461 const char *interface
,
462 const char *property
,
463 sd_bus_message
*reply
,
465 sd_bus_error
*error
) {
467 ExecContext
*c
= userdata
;
473 return sd_bus_message_append(reply
, "(bs)", c
->apparmor_profile_ignore
, c
->apparmor_profile
);
476 static int property_get_smack_process_label(
479 const char *interface
,
480 const char *property
,
481 sd_bus_message
*reply
,
483 sd_bus_error
*error
) {
485 ExecContext
*c
= userdata
;
491 return sd_bus_message_append(reply
, "(bs)", c
->smack_process_label_ignore
, c
->smack_process_label
);
494 static int property_get_personality(
497 const char *interface
,
498 const char *property
,
499 sd_bus_message
*reply
,
501 sd_bus_error
*error
) {
503 ExecContext
*c
= userdata
;
509 return sd_bus_message_append(reply
, "s", personality_to_string(c
->personality
));
512 static int property_get_address_families(
515 const char *interface
,
516 const char *property
,
517 sd_bus_message
*reply
,
519 sd_bus_error
*error
) {
521 ExecContext
*c
= userdata
;
522 _cleanup_strv_free_
char **l
= NULL
;
531 r
= sd_bus_message_open_container(reply
, 'r', "bas");
535 r
= sd_bus_message_append(reply
, "b", c
->address_families_whitelist
);
539 SET_FOREACH(af
, c
->address_families
, i
) {
542 name
= af_to_name(PTR_TO_INT(af
));
546 r
= strv_extend(&l
, name
);
553 r
= sd_bus_message_append_strv(reply
, l
);
557 return sd_bus_message_close_container(reply
);
560 static int property_get_working_directory(
563 const char *interface
,
564 const char *property
,
565 sd_bus_message
*reply
,
567 sd_bus_error
*error
) {
569 ExecContext
*c
= userdata
;
576 if (c
->working_directory_home
)
579 wd
= c
->working_directory
;
581 if (c
->working_directory_missing_ok
)
582 wd
= strjoina("!", wd
);
584 return sd_bus_message_append(reply
, "s", wd
);
587 static int property_get_syslog_level(
590 const char *interface
,
591 const char *property
,
592 sd_bus_message
*reply
,
594 sd_bus_error
*error
) {
596 ExecContext
*c
= userdata
;
602 return sd_bus_message_append(reply
, "i", LOG_PRI(c
->syslog_priority
));
605 static int property_get_syslog_facility(
608 const char *interface
,
609 const char *property
,
610 sd_bus_message
*reply
,
612 sd_bus_error
*error
) {
614 ExecContext
*c
= userdata
;
620 return sd_bus_message_append(reply
, "i", LOG_FAC(c
->syslog_priority
));
623 const sd_bus_vtable bus_exec_vtable
[] = {
624 SD_BUS_VTABLE_START(0),
625 SD_BUS_PROPERTY("Environment", "as", NULL
, offsetof(ExecContext
, environment
), SD_BUS_VTABLE_PROPERTY_CONST
),
626 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
627 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode
, offsetof(ExecContext
, umask
), SD_BUS_VTABLE_PROPERTY_CONST
),
628 SD_BUS_PROPERTY("LimitCPU", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CPU
]), SD_BUS_VTABLE_PROPERTY_CONST
),
629 SD_BUS_PROPERTY("LimitFSIZE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_FSIZE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
630 SD_BUS_PROPERTY("LimitDATA", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_DATA
]), SD_BUS_VTABLE_PROPERTY_CONST
),
631 SD_BUS_PROPERTY("LimitSTACK", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_STACK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
632 SD_BUS_PROPERTY("LimitCORE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CORE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
633 SD_BUS_PROPERTY("LimitRSS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RSS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
634 SD_BUS_PROPERTY("LimitNOFILE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NOFILE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
635 SD_BUS_PROPERTY("LimitAS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_AS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
636 SD_BUS_PROPERTY("LimitNPROC", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NPROC
]), SD_BUS_VTABLE_PROPERTY_CONST
),
637 SD_BUS_PROPERTY("LimitMEMLOCK", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MEMLOCK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
638 SD_BUS_PROPERTY("LimitLOCKS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_LOCKS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
639 SD_BUS_PROPERTY("LimitSIGPENDING", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_SIGPENDING
]), SD_BUS_VTABLE_PROPERTY_CONST
),
640 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MSGQUEUE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
641 SD_BUS_PROPERTY("LimitNICE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NICE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
642 SD_BUS_PROPERTY("LimitRTPRIO", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTPRIO
]), SD_BUS_VTABLE_PROPERTY_CONST
),
643 SD_BUS_PROPERTY("LimitRTTIME", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTTIME
]), SD_BUS_VTABLE_PROPERTY_CONST
),
644 SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
645 SD_BUS_PROPERTY("RootDirectory", "s", NULL
, offsetof(ExecContext
, root_directory
), SD_BUS_VTABLE_PROPERTY_CONST
),
646 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
647 SD_BUS_PROPERTY("Nice", "i", property_get_nice
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
648 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
649 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
650 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
651 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
652 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
653 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool
, offsetof(ExecContext
, cpu_sched_reset_on_fork
), SD_BUS_VTABLE_PROPERTY_CONST
),
654 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool
, offsetof(ExecContext
, non_blocking
), SD_BUS_VTABLE_PROPERTY_CONST
),
655 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input
, offsetof(ExecContext
, std_input
), SD_BUS_VTABLE_PROPERTY_CONST
),
656 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output
, offsetof(ExecContext
, std_output
), SD_BUS_VTABLE_PROPERTY_CONST
),
657 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output
, offsetof(ExecContext
, std_error
), SD_BUS_VTABLE_PROPERTY_CONST
),
658 SD_BUS_PROPERTY("TTYPath", "s", NULL
, offsetof(ExecContext
, tty_path
), SD_BUS_VTABLE_PROPERTY_CONST
),
659 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_reset
), SD_BUS_VTABLE_PROPERTY_CONST
),
660 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_vhangup
), SD_BUS_VTABLE_PROPERTY_CONST
),
661 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_vt_disallocate
), SD_BUS_VTABLE_PROPERTY_CONST
),
662 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int
, offsetof(ExecContext
, syslog_priority
), SD_BUS_VTABLE_PROPERTY_CONST
),
663 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL
, offsetof(ExecContext
, syslog_identifier
), SD_BUS_VTABLE_PROPERTY_CONST
),
664 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool
, offsetof(ExecContext
, syslog_level_prefix
), SD_BUS_VTABLE_PROPERTY_CONST
),
665 SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
666 SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
667 SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
668 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int
, offsetof(ExecContext
, secure_bits
), SD_BUS_VTABLE_PROPERTY_CONST
),
669 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
670 SD_BUS_PROPERTY("User", "s", NULL
, offsetof(ExecContext
, user
), SD_BUS_VTABLE_PROPERTY_CONST
),
671 SD_BUS_PROPERTY("Group", "s", NULL
, offsetof(ExecContext
, group
), SD_BUS_VTABLE_PROPERTY_CONST
),
672 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL
, offsetof(ExecContext
, supplementary_groups
), SD_BUS_VTABLE_PROPERTY_CONST
),
673 SD_BUS_PROPERTY("PAMName", "s", NULL
, offsetof(ExecContext
, pam_name
), SD_BUS_VTABLE_PROPERTY_CONST
),
674 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL
, offsetof(ExecContext
, read_write_dirs
), SD_BUS_VTABLE_PROPERTY_CONST
),
675 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL
, offsetof(ExecContext
, read_only_dirs
), SD_BUS_VTABLE_PROPERTY_CONST
),
676 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL
, offsetof(ExecContext
, inaccessible_dirs
), SD_BUS_VTABLE_PROPERTY_CONST
),
677 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong
, offsetof(ExecContext
, mount_flags
), SD_BUS_VTABLE_PROPERTY_CONST
),
678 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool
, offsetof(ExecContext
, private_tmp
), SD_BUS_VTABLE_PROPERTY_CONST
),
679 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool
, offsetof(ExecContext
, private_network
), SD_BUS_VTABLE_PROPERTY_CONST
),
680 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool
, offsetof(ExecContext
, private_devices
), SD_BUS_VTABLE_PROPERTY_CONST
),
681 SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home
, offsetof(ExecContext
, protect_home
), SD_BUS_VTABLE_PROPERTY_CONST
),
682 SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system
, offsetof(ExecContext
, protect_system
), SD_BUS_VTABLE_PROPERTY_CONST
),
683 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool
, offsetof(ExecContext
, same_pgrp
), SD_BUS_VTABLE_PROPERTY_CONST
),
684 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL
, offsetof(ExecContext
, utmp_id
), SD_BUS_VTABLE_PROPERTY_CONST
),
685 SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode
, offsetof(ExecContext
, utmp_mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
686 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
687 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
688 SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
689 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool
, offsetof(ExecContext
, ignore_sigpipe
), SD_BUS_VTABLE_PROPERTY_CONST
),
690 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool
, offsetof(ExecContext
, no_new_privileges
), SD_BUS_VTABLE_PROPERTY_CONST
),
691 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
692 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
693 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
694 SD_BUS_PROPERTY("Personality", "s", property_get_personality
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
695 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
696 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode
, offsetof(ExecContext
, runtime_directory_mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
697 SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL
, offsetof(ExecContext
, runtime_directory
), SD_BUS_VTABLE_PROPERTY_CONST
),
701 static int append_exec_command(sd_bus_message
*reply
, ExecCommand
*c
) {
710 r
= sd_bus_message_open_container(reply
, 'r', "sasbttttuii");
714 r
= sd_bus_message_append(reply
, "s", c
->path
);
718 r
= sd_bus_message_append_strv(reply
, c
->argv
);
722 r
= sd_bus_message_append(reply
, "bttttuii",
724 c
->exec_status
.start_timestamp
.realtime
,
725 c
->exec_status
.start_timestamp
.monotonic
,
726 c
->exec_status
.exit_timestamp
.realtime
,
727 c
->exec_status
.exit_timestamp
.monotonic
,
728 (uint32_t) c
->exec_status
.pid
,
729 (int32_t) c
->exec_status
.code
,
730 (int32_t) c
->exec_status
.status
);
734 return sd_bus_message_close_container(reply
);
737 int bus_property_get_exec_command(
740 const char *interface
,
741 const char *property
,
742 sd_bus_message
*reply
,
744 sd_bus_error
*ret_error
) {
746 ExecCommand
*c
= (ExecCommand
*) userdata
;
752 r
= sd_bus_message_open_container(reply
, 'a', "(sasbttttuii)");
756 r
= append_exec_command(reply
, c
);
760 return sd_bus_message_close_container(reply
);
763 int bus_property_get_exec_command_list(
766 const char *interface
,
767 const char *property
,
768 sd_bus_message
*reply
,
770 sd_bus_error
*ret_error
) {
772 ExecCommand
*c
= *(ExecCommand
**) userdata
;
778 r
= sd_bus_message_open_container(reply
, 'a', "(sasbttttuii)");
782 LIST_FOREACH(command
, c
, c
) {
783 r
= append_exec_command(reply
, c
);
788 return sd_bus_message_close_container(reply
);
791 int bus_exec_context_set_transient_property(
795 sd_bus_message
*message
,
796 UnitSetPropertiesMode mode
,
797 sd_bus_error
*error
) {
806 if (streq(name
, "User")) {
809 r
= sd_bus_message_read(message
, "s", &uu
);
813 if (mode
!= UNIT_CHECK
) {
816 c
->user
= mfree(c
->user
);
828 unit_write_drop_in_private_format(u
, mode
, name
, "User=%s\n", uu
);
833 } else if (streq(name
, "Group")) {
836 r
= sd_bus_message_read(message
, "s", &gg
);
840 if (mode
!= UNIT_CHECK
) {
843 c
->group
= mfree(c
->group
);
855 unit_write_drop_in_private_format(u
, mode
, name
, "Group=%s\n", gg
);
859 } else if (streq(name
, "SyslogIdentifier")) {
862 r
= sd_bus_message_read(message
, "s", &id
);
866 if (mode
!= UNIT_CHECK
) {
869 c
->syslog_identifier
= mfree(c
->syslog_identifier
);
877 free(c
->syslog_identifier
);
878 c
->syslog_identifier
= t
;
881 unit_write_drop_in_private_format(u
, mode
, name
, "SyslogIdentifier=%s\n", id
);
885 } else if (streq(name
, "SyslogLevel")) {
888 r
= sd_bus_message_read(message
, "i", &level
);
892 if (!log_level_is_valid(level
))
893 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Log level value out of range");
895 if (mode
!= UNIT_CHECK
) {
896 c
->syslog_priority
= (c
->syslog_priority
& LOG_FACMASK
) | level
;
897 unit_write_drop_in_private_format(u
, mode
, name
, "SyslogLevel=%i\n", level
);
901 } else if (streq(name
, "SyslogFacility")) {
904 r
= sd_bus_message_read(message
, "i", &facility
);
908 if (!log_facility_unshifted_is_valid(facility
))
909 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Log facility value out of range");
911 if (mode
!= UNIT_CHECK
) {
912 c
->syslog_priority
= (facility
<< 3) | LOG_PRI(c
->syslog_priority
);
913 unit_write_drop_in_private_format(u
, mode
, name
, "SyslogFacility=%i\n", facility
);
917 } else if (streq(name
, "Nice")) {
920 r
= sd_bus_message_read(message
, "i", &n
);
924 if (n
< PRIO_MIN
|| n
>= PRIO_MAX
)
925 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Nice value out of range");
927 if (mode
!= UNIT_CHECK
) {
929 unit_write_drop_in_private_format(u
, mode
, name
, "Nice=%i\n", n
);
934 } else if (STR_IN_SET(name
, "TTYPath", "RootDirectory")) {
937 r
= sd_bus_message_read(message
, "s", &s
);
941 if (!path_is_absolute(s
))
942 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s takes an absolute path", name
);
944 if (mode
!= UNIT_CHECK
) {
945 if (streq(name
, "TTYPath"))
946 r
= free_and_strdup(&c
->tty_path
, s
);
948 assert(streq(name
, "RootDirectory"));
949 r
= free_and_strdup(&c
->root_directory
, s
);
954 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, s
);
959 } else if (streq(name
, "WorkingDirectory")) {
963 r
= sd_bus_message_read(message
, "s", &s
);
973 if (!streq(s
, "~") && !path_is_absolute(s
))
974 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "WorkingDirectory= expects an absolute path or '~'");
976 if (mode
!= UNIT_CHECK
) {
978 c
->working_directory
= mfree(c
->working_directory
);
979 c
->working_directory_home
= true;
981 r
= free_and_strdup(&c
->working_directory
, s
);
985 c
->working_directory_home
= false;
988 c
->working_directory_missing_ok
= missing_ok
;
989 unit_write_drop_in_private_format(u
, mode
, name
, "WorkingDirectory=%s%s", missing_ok
? "-" : "", s
);
994 } else if (streq(name
, "StandardInput")) {
998 r
= sd_bus_message_read(message
, "s", &s
);
1002 p
= exec_input_from_string(s
);
1004 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard input name");
1006 if (mode
!= UNIT_CHECK
) {
1009 unit_write_drop_in_private_format(u
, mode
, name
, "StandardInput=%s\n", exec_input_to_string(p
));
1015 } else if (streq(name
, "StandardOutput")) {
1019 r
= sd_bus_message_read(message
, "s", &s
);
1023 p
= exec_output_from_string(s
);
1025 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard output name");
1027 if (mode
!= UNIT_CHECK
) {
1030 unit_write_drop_in_private_format(u
, mode
, name
, "StandardOutput=%s\n", exec_output_to_string(p
));
1035 } else if (streq(name
, "StandardError")) {
1039 r
= sd_bus_message_read(message
, "s", &s
);
1043 p
= exec_output_from_string(s
);
1045 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard error name");
1047 if (mode
!= UNIT_CHECK
) {
1050 unit_write_drop_in_private_format(u
, mode
, name
, "StandardError=%s\n", exec_output_to_string(p
));
1055 } else if (STR_IN_SET(name
,
1056 "IgnoreSIGPIPE", "TTYVHangup", "TTYReset",
1057 "PrivateTmp", "PrivateDevices", "PrivateNetwork",
1058 "NoNewPrivileges", "SyslogLevelPrefix")) {
1061 r
= sd_bus_message_read(message
, "b", &b
);
1065 if (mode
!= UNIT_CHECK
) {
1066 if (streq(name
, "IgnoreSIGPIPE"))
1067 c
->ignore_sigpipe
= b
;
1068 else if (streq(name
, "TTYVHangup"))
1070 else if (streq(name
, "TTYReset"))
1072 else if (streq(name
, "PrivateTmp"))
1074 else if (streq(name
, "PrivateDevices"))
1075 c
->private_devices
= b
;
1076 else if (streq(name
, "PrivateNetwork"))
1077 c
->private_network
= b
;
1078 else if (streq(name
, "NoNewPrivileges"))
1079 c
->no_new_privileges
= b
;
1080 else if (streq(name
, "SyslogLevelPrefix"))
1081 c
->syslog_level_prefix
= b
;
1083 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, yes_no(b
));
1088 } else if (streq(name
, "UtmpIdentifier")) {
1091 r
= sd_bus_message_read(message
, "s", &id
);
1095 if (mode
!= UNIT_CHECK
) {
1097 c
->utmp_id
= mfree(c
->utmp_id
);
1098 else if (free_and_strdup(&c
->utmp_id
, id
) < 0)
1101 unit_write_drop_in_private_format(u
, mode
, name
, "UtmpIdentifier=%s\n", strempty(id
));
1106 } else if (streq(name
, "UtmpMode")) {
1110 r
= sd_bus_message_read(message
, "s", &s
);
1114 m
= exec_utmp_mode_from_string(s
);
1116 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid utmp mode");
1118 if (mode
!= UNIT_CHECK
) {
1121 unit_write_drop_in_private_format(u
, mode
, name
, "UtmpMode=%s\n", exec_utmp_mode_to_string(m
));
1126 } else if (streq(name
, "PAMName")) {
1129 r
= sd_bus_message_read(message
, "s", &n
);
1133 if (mode
!= UNIT_CHECK
) {
1135 c
->pam_name
= mfree(c
->pam_name
);
1136 else if (free_and_strdup(&c
->pam_name
, n
) < 0)
1139 unit_write_drop_in_private_format(u
, mode
, name
, "PAMName=%s\n", strempty(n
));
1144 } else if (streq(name
, "Environment")) {
1146 _cleanup_strv_free_
char **l
= NULL
;
1148 r
= sd_bus_message_read_strv(message
, &l
);
1152 if (!strv_env_is_valid(l
))
1153 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid environment block.");
1155 if (mode
!= UNIT_CHECK
) {
1156 _cleanup_free_
char *joined
= NULL
;
1159 if (strv_length(l
) == 0) {
1160 c
->environment
= strv_free(c
->environment
);
1161 unit_write_drop_in_private_format(u
, mode
, name
, "Environment=\n");
1163 e
= strv_env_merge(2, c
->environment
, l
);
1167 strv_free(c
->environment
);
1170 joined
= strv_join_quoted(c
->environment
);
1174 unit_write_drop_in_private_format(u
, mode
, name
, "Environment=%s\n", joined
);
1180 } else if (streq(name
, "TimerSlackNSec")) {
1184 r
= sd_bus_message_read(message
, "t", &n
);
1188 if (mode
!= UNIT_CHECK
) {
1189 c
->timer_slack_nsec
= n
;
1190 unit_write_drop_in_private_format(u
, mode
, name
, "TimerSlackNSec=" NSEC_FMT
"\n", n
);
1195 } else if (streq(name
, "OOMScoreAdjust")) {
1198 r
= sd_bus_message_read(message
, "i", &oa
);
1202 if (!oom_score_adjust_is_valid(oa
))
1203 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "OOM score adjust value out of range");
1205 if (mode
!= UNIT_CHECK
) {
1206 c
->oom_score_adjust
= oa
;
1207 c
->oom_score_adjust_set
= true;
1208 unit_write_drop_in_private_format(u
, mode
, name
, "OOMScoreAdjust=%i\n", oa
);
1213 } else if (streq(name
, "EnvironmentFiles")) {
1215 _cleanup_free_
char *joined
= NULL
;
1216 _cleanup_fclose_
FILE *f
= NULL
;
1217 _cleanup_free_
char **l
= NULL
;
1221 r
= sd_bus_message_enter_container(message
, 'a', "(sb)");
1225 f
= open_memstream(&joined
, &size
);
1229 STRV_FOREACH(i
, c
->environment_files
)
1230 fprintf(f
, "EnvironmentFile=%s\n", *i
);
1232 while ((r
= sd_bus_message_enter_container(message
, 'r', "sb")) > 0) {
1236 r
= sd_bus_message_read(message
, "sb", &path
, &b
);
1240 r
= sd_bus_message_exit_container(message
);
1244 if (!isempty(path
) && !path_is_absolute(path
))
1245 return sd_bus_error_set_errnof(error
, EINVAL
, "Path %s is not absolute.", path
);
1247 if (mode
!= UNIT_CHECK
) {
1250 buf
= strjoin(b
? "-" : "", path
, NULL
);
1254 fprintf(f
, "EnvironmentFile=%s\n", buf
);
1256 r
= strv_consume(&l
, buf
);
1264 r
= sd_bus_message_exit_container(message
);
1268 r
= fflush_and_check(f
);
1272 if (mode
!= UNIT_CHECK
) {
1273 if (strv_isempty(l
)) {
1274 c
->environment_files
= strv_free(c
->environment_files
);
1275 unit_write_drop_in_private(u
, mode
, name
, "EnvironmentFile=\n");
1277 r
= strv_extend_strv(&c
->environment_files
, l
, true);
1281 unit_write_drop_in_private(u
, mode
, name
, joined
);
1287 } else if (STR_IN_SET(name
, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories")) {
1289 _cleanup_strv_free_
char **l
= NULL
;
1293 r
= sd_bus_message_read_strv(message
, &l
);
1297 STRV_FOREACH(p
, l
) {
1299 if (!utf8_is_valid(*p
))
1300 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid %s", name
);
1302 offset
= **p
== '-';
1303 if (!path_is_absolute(*p
+ offset
))
1304 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid %s", name
);
1307 if (mode
!= UNIT_CHECK
) {
1308 _cleanup_free_
char *joined
= NULL
;
1310 if (streq(name
, "ReadWriteDirectories"))
1311 dirs
= &c
->read_write_dirs
;
1312 else if (streq(name
, "ReadOnlyDirectories"))
1313 dirs
= &c
->read_only_dirs
;
1314 else if (streq(name
, "InaccessibleDirectories"))
1315 dirs
= &c
->inaccessible_dirs
;
1317 if (strv_length(l
) == 0) {
1318 *dirs
= strv_free(*dirs
);
1319 unit_write_drop_in_private_format(u
, mode
, name
, "%s=\n", name
);
1321 r
= strv_extend_strv(dirs
, l
, true);
1326 joined
= strv_join_quoted(*dirs
);
1330 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, joined
);
1337 } else if (streq(name
, "ProtectSystem")) {
1341 r
= sd_bus_message_read(message
, "s", &s
);
1345 r
= parse_boolean(s
);
1347 ps
= PROTECT_SYSTEM_YES
;
1349 ps
= PROTECT_SYSTEM_NO
;
1351 ps
= protect_system_from_string(s
);
1353 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Failed to parse protect system value");
1356 if (mode
!= UNIT_CHECK
) {
1357 c
->protect_system
= ps
;
1358 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, s
);
1363 } else if (rlimit_from_string(name
) >= 0) {
1367 r
= sd_bus_message_read(message
, "t", &rl
);
1371 if (rl
== (uint64_t) -1)
1376 if ((uint64_t) x
!= rl
)
1380 if (mode
!= UNIT_CHECK
) {
1383 z
= rlimit_from_string(name
);
1385 if (!c
->rlimit
[z
]) {
1386 c
->rlimit
[z
] = new(struct rlimit
, 1);
1391 c
->rlimit
[z
]->rlim_cur
= c
->rlimit
[z
]->rlim_max
= x
;
1393 if (x
== RLIM_INFINITY
)
1394 unit_write_drop_in_private_format(u
, mode
, name
, "%s=infinity\n", name
);
1396 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%" PRIu64
"\n", name
, rl
);