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>
29 #include "alloc-util.h"
31 #include "capability-util.h"
32 #include "dbus-execute.h"
39 #include "namespace.h"
40 #include "parse-util.h"
41 #include "path-util.h"
42 #include "process-util.h"
43 #include "rlimit-util.h"
45 #include "seccomp-util.h"
48 #include "syslog-util.h"
51 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output
, exec_output
, ExecOutput
);
53 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input
, exec_input
, ExecInput
);
55 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_utmp_mode
, exec_utmp_mode
, ExecUtmpMode
);
57 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_home
, protect_home
, ProtectHome
);
58 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_system
, protect_system
, ProtectSystem
);
60 static int property_get_environment_files(
63 const char *interface
,
65 sd_bus_message
*reply
,
67 sd_bus_error
*error
) {
69 ExecContext
*c
= userdata
;
77 r
= sd_bus_message_open_container(reply
, 'a', "(sb)");
81 STRV_FOREACH(j
, c
->environment_files
) {
84 r
= sd_bus_message_append(reply
, "(sb)", fn
[0] == '-' ? fn
+ 1 : fn
, fn
[0] == '-');
89 return sd_bus_message_close_container(reply
);
92 static int property_get_oom_score_adjust(
95 const char *interface
,
97 sd_bus_message
*reply
,
99 sd_bus_error
*error
) {
102 ExecContext
*c
= userdata
;
109 if (c
->oom_score_adjust_set
)
110 n
= c
->oom_score_adjust
;
112 _cleanup_free_
char *t
= NULL
;
115 if (read_one_line_file("/proc/self/oom_score_adj", &t
) >= 0)
119 return sd_bus_message_append(reply
, "i", n
);
122 static int property_get_nice(
125 const char *interface
,
126 const char *property
,
127 sd_bus_message
*reply
,
129 sd_bus_error
*error
) {
132 ExecContext
*c
= userdata
;
143 n
= getpriority(PRIO_PROCESS
, 0);
148 return sd_bus_message_append(reply
, "i", n
);
151 static int property_get_ioprio(
154 const char *interface
,
155 const char *property
,
156 sd_bus_message
*reply
,
158 sd_bus_error
*error
) {
161 ExecContext
*c
= userdata
;
171 n
= ioprio_get(IOPRIO_WHO_PROCESS
, 0);
173 n
= IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE
, 4);
176 return sd_bus_message_append(reply
, "i", n
);
179 static int property_get_cpu_sched_policy(
182 const char *interface
,
183 const char *property
,
184 sd_bus_message
*reply
,
186 sd_bus_error
*error
) {
188 ExecContext
*c
= userdata
;
195 if (c
->cpu_sched_set
)
196 n
= c
->cpu_sched_policy
;
198 n
= sched_getscheduler(0);
203 return sd_bus_message_append(reply
, "i", n
);
206 static int property_get_cpu_sched_priority(
209 const char *interface
,
210 const char *property
,
211 sd_bus_message
*reply
,
213 sd_bus_error
*error
) {
215 ExecContext
*c
= userdata
;
222 if (c
->cpu_sched_set
)
223 n
= c
->cpu_sched_priority
;
225 struct sched_param p
= {};
227 if (sched_getparam(0, &p
) >= 0)
228 n
= p
.sched_priority
;
233 return sd_bus_message_append(reply
, "i", n
);
236 static int property_get_cpu_affinity(
239 const char *interface
,
240 const char *property
,
241 sd_bus_message
*reply
,
243 sd_bus_error
*error
) {
245 ExecContext
*c
= userdata
;
252 return sd_bus_message_append_array(reply
, 'y', c
->cpuset
, CPU_ALLOC_SIZE(c
->cpuset_ncpus
));
254 return sd_bus_message_append_array(reply
, 'y', NULL
, 0);
257 static int property_get_timer_slack_nsec(
260 const char *interface
,
261 const char *property
,
262 sd_bus_message
*reply
,
264 sd_bus_error
*error
) {
266 ExecContext
*c
= userdata
;
273 if (c
->timer_slack_nsec
!= NSEC_INFINITY
)
274 u
= (uint64_t) c
->timer_slack_nsec
;
276 u
= (uint64_t) prctl(PR_GET_TIMERSLACK
);
278 return sd_bus_message_append(reply
, "t", u
);
281 static int property_get_capability_bounding_set(
284 const char *interface
,
285 const char *property
,
286 sd_bus_message
*reply
,
288 sd_bus_error
*error
) {
290 ExecContext
*c
= userdata
;
296 /* We store this negated internally, to match the kernel, but
297 * we expose it normalized. */
298 return sd_bus_message_append(reply
, "t", ~c
->capability_bounding_set_drop
);
301 static int property_get_capabilities(
304 const char *interface
,
305 const char *property
,
306 sd_bus_message
*reply
,
308 sd_bus_error
*error
) {
310 ExecContext
*c
= userdata
;
311 _cleanup_cap_free_charp_
char *t
= NULL
;
319 s
= t
= cap_to_text(c
->capabilities
, NULL
);
326 return sd_bus_message_append(reply
, "s", s
);
329 static int property_get_syscall_filter(
332 const char *interface
,
333 const char *property
,
334 sd_bus_message
*reply
,
336 sd_bus_error
*error
) {
338 ExecContext
*c
= userdata
;
339 _cleanup_strv_free_
char **l
= NULL
;
351 r
= sd_bus_message_open_container(reply
, 'r', "bas");
355 r
= sd_bus_message_append(reply
, "b", c
->syscall_whitelist
);
360 SET_FOREACH(id
, c
->syscall_filter
, i
) {
363 name
= seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE
, PTR_TO_INT(id
) - 1);
367 r
= strv_consume(&l
, name
);
375 r
= sd_bus_message_append_strv(reply
, l
);
379 return sd_bus_message_close_container(reply
);
382 static int property_get_syscall_archs(
385 const char *interface
,
386 const char *property
,
387 sd_bus_message
*reply
,
389 sd_bus_error
*error
) {
391 ExecContext
*c
= userdata
;
392 _cleanup_strv_free_
char **l
= NULL
;
405 SET_FOREACH(id
, c
->syscall_archs
, i
) {
408 name
= seccomp_arch_to_string(PTR_TO_UINT32(id
) - 1);
412 r
= strv_extend(&l
, name
);
420 r
= sd_bus_message_append_strv(reply
, l
);
427 static int property_get_syscall_errno(
430 const char *interface
,
431 const char *property
,
432 sd_bus_message
*reply
,
434 sd_bus_error
*error
) {
436 ExecContext
*c
= userdata
;
442 return sd_bus_message_append(reply
, "i", (int32_t) c
->syscall_errno
);
445 static int property_get_selinux_context(
448 const char *interface
,
449 const char *property
,
450 sd_bus_message
*reply
,
452 sd_bus_error
*error
) {
454 ExecContext
*c
= userdata
;
460 return sd_bus_message_append(reply
, "(bs)", c
->selinux_context_ignore
, c
->selinux_context
);
463 static int property_get_apparmor_profile(
466 const char *interface
,
467 const char *property
,
468 sd_bus_message
*reply
,
470 sd_bus_error
*error
) {
472 ExecContext
*c
= userdata
;
478 return sd_bus_message_append(reply
, "(bs)", c
->apparmor_profile_ignore
, c
->apparmor_profile
);
481 static int property_get_smack_process_label(
484 const char *interface
,
485 const char *property
,
486 sd_bus_message
*reply
,
488 sd_bus_error
*error
) {
490 ExecContext
*c
= userdata
;
496 return sd_bus_message_append(reply
, "(bs)", c
->smack_process_label_ignore
, c
->smack_process_label
);
499 static int property_get_personality(
502 const char *interface
,
503 const char *property
,
504 sd_bus_message
*reply
,
506 sd_bus_error
*error
) {
508 ExecContext
*c
= userdata
;
514 return sd_bus_message_append(reply
, "s", personality_to_string(c
->personality
));
517 static int property_get_address_families(
520 const char *interface
,
521 const char *property
,
522 sd_bus_message
*reply
,
524 sd_bus_error
*error
) {
526 ExecContext
*c
= userdata
;
527 _cleanup_strv_free_
char **l
= NULL
;
536 r
= sd_bus_message_open_container(reply
, 'r', "bas");
540 r
= sd_bus_message_append(reply
, "b", c
->address_families_whitelist
);
544 SET_FOREACH(af
, c
->address_families
, i
) {
547 name
= af_to_name(PTR_TO_INT(af
));
551 r
= strv_extend(&l
, name
);
558 r
= sd_bus_message_append_strv(reply
, l
);
562 return sd_bus_message_close_container(reply
);
565 static int property_get_working_directory(
568 const char *interface
,
569 const char *property
,
570 sd_bus_message
*reply
,
572 sd_bus_error
*error
) {
574 ExecContext
*c
= userdata
;
581 if (c
->working_directory_home
)
584 wd
= c
->working_directory
;
586 if (c
->working_directory_missing_ok
)
587 wd
= strjoina("!", wd
);
589 return sd_bus_message_append(reply
, "s", wd
);
592 static int property_get_syslog_level(
595 const char *interface
,
596 const char *property
,
597 sd_bus_message
*reply
,
599 sd_bus_error
*error
) {
601 ExecContext
*c
= userdata
;
607 return sd_bus_message_append(reply
, "i", LOG_PRI(c
->syslog_priority
));
610 static int property_get_syslog_facility(
613 const char *interface
,
614 const char *property
,
615 sd_bus_message
*reply
,
617 sd_bus_error
*error
) {
619 ExecContext
*c
= userdata
;
625 return sd_bus_message_append(reply
, "i", LOG_FAC(c
->syslog_priority
));
628 const sd_bus_vtable bus_exec_vtable
[] = {
629 SD_BUS_VTABLE_START(0),
630 SD_BUS_PROPERTY("Environment", "as", NULL
, offsetof(ExecContext
, environment
), SD_BUS_VTABLE_PROPERTY_CONST
),
631 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
632 SD_BUS_PROPERTY("PassEnvironment", "as", NULL
, offsetof(ExecContext
, pass_environment
), SD_BUS_VTABLE_PROPERTY_CONST
),
633 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode
, offsetof(ExecContext
, umask
), SD_BUS_VTABLE_PROPERTY_CONST
),
634 SD_BUS_PROPERTY("LimitCPU", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CPU
]), SD_BUS_VTABLE_PROPERTY_CONST
),
635 SD_BUS_PROPERTY("LimitFSIZE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_FSIZE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
636 SD_BUS_PROPERTY("LimitDATA", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_DATA
]), SD_BUS_VTABLE_PROPERTY_CONST
),
637 SD_BUS_PROPERTY("LimitSTACK", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_STACK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
638 SD_BUS_PROPERTY("LimitCORE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CORE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
639 SD_BUS_PROPERTY("LimitRSS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RSS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
640 SD_BUS_PROPERTY("LimitNOFILE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NOFILE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
641 SD_BUS_PROPERTY("LimitAS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_AS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
642 SD_BUS_PROPERTY("LimitNPROC", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NPROC
]), SD_BUS_VTABLE_PROPERTY_CONST
),
643 SD_BUS_PROPERTY("LimitMEMLOCK", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MEMLOCK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
644 SD_BUS_PROPERTY("LimitLOCKS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_LOCKS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
645 SD_BUS_PROPERTY("LimitSIGPENDING", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_SIGPENDING
]), SD_BUS_VTABLE_PROPERTY_CONST
),
646 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MSGQUEUE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
647 SD_BUS_PROPERTY("LimitNICE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NICE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
648 SD_BUS_PROPERTY("LimitRTPRIO", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTPRIO
]), SD_BUS_VTABLE_PROPERTY_CONST
),
649 SD_BUS_PROPERTY("LimitRTTIME", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTTIME
]), SD_BUS_VTABLE_PROPERTY_CONST
),
650 SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
651 SD_BUS_PROPERTY("RootDirectory", "s", NULL
, offsetof(ExecContext
, root_directory
), SD_BUS_VTABLE_PROPERTY_CONST
),
652 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
653 SD_BUS_PROPERTY("Nice", "i", property_get_nice
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
654 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
655 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
656 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
657 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
658 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
659 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool
, offsetof(ExecContext
, cpu_sched_reset_on_fork
), SD_BUS_VTABLE_PROPERTY_CONST
),
660 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool
, offsetof(ExecContext
, non_blocking
), SD_BUS_VTABLE_PROPERTY_CONST
),
661 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input
, offsetof(ExecContext
, std_input
), SD_BUS_VTABLE_PROPERTY_CONST
),
662 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output
, offsetof(ExecContext
, std_output
), SD_BUS_VTABLE_PROPERTY_CONST
),
663 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output
, offsetof(ExecContext
, std_error
), SD_BUS_VTABLE_PROPERTY_CONST
),
664 SD_BUS_PROPERTY("TTYPath", "s", NULL
, offsetof(ExecContext
, tty_path
), SD_BUS_VTABLE_PROPERTY_CONST
),
665 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_reset
), SD_BUS_VTABLE_PROPERTY_CONST
),
666 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_vhangup
), SD_BUS_VTABLE_PROPERTY_CONST
),
667 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_vt_disallocate
), SD_BUS_VTABLE_PROPERTY_CONST
),
668 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int
, offsetof(ExecContext
, syslog_priority
), SD_BUS_VTABLE_PROPERTY_CONST
),
669 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL
, offsetof(ExecContext
, syslog_identifier
), SD_BUS_VTABLE_PROPERTY_CONST
),
670 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool
, offsetof(ExecContext
, syslog_level_prefix
), SD_BUS_VTABLE_PROPERTY_CONST
),
671 SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
672 SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
673 SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
674 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int
, offsetof(ExecContext
, secure_bits
), SD_BUS_VTABLE_PROPERTY_CONST
),
675 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
676 SD_BUS_PROPERTY("User", "s", NULL
, offsetof(ExecContext
, user
), SD_BUS_VTABLE_PROPERTY_CONST
),
677 SD_BUS_PROPERTY("Group", "s", NULL
, offsetof(ExecContext
, group
), SD_BUS_VTABLE_PROPERTY_CONST
),
678 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL
, offsetof(ExecContext
, supplementary_groups
), SD_BUS_VTABLE_PROPERTY_CONST
),
679 SD_BUS_PROPERTY("PAMName", "s", NULL
, offsetof(ExecContext
, pam_name
), SD_BUS_VTABLE_PROPERTY_CONST
),
680 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL
, offsetof(ExecContext
, read_write_dirs
), SD_BUS_VTABLE_PROPERTY_CONST
),
681 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL
, offsetof(ExecContext
, read_only_dirs
), SD_BUS_VTABLE_PROPERTY_CONST
),
682 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL
, offsetof(ExecContext
, inaccessible_dirs
), SD_BUS_VTABLE_PROPERTY_CONST
),
683 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong
, offsetof(ExecContext
, mount_flags
), SD_BUS_VTABLE_PROPERTY_CONST
),
684 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool
, offsetof(ExecContext
, private_tmp
), SD_BUS_VTABLE_PROPERTY_CONST
),
685 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool
, offsetof(ExecContext
, private_network
), SD_BUS_VTABLE_PROPERTY_CONST
),
686 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool
, offsetof(ExecContext
, private_devices
), SD_BUS_VTABLE_PROPERTY_CONST
),
687 SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home
, offsetof(ExecContext
, protect_home
), SD_BUS_VTABLE_PROPERTY_CONST
),
688 SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system
, offsetof(ExecContext
, protect_system
), SD_BUS_VTABLE_PROPERTY_CONST
),
689 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool
, offsetof(ExecContext
, same_pgrp
), SD_BUS_VTABLE_PROPERTY_CONST
),
690 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL
, offsetof(ExecContext
, utmp_id
), SD_BUS_VTABLE_PROPERTY_CONST
),
691 SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode
, offsetof(ExecContext
, utmp_mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
692 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
693 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
694 SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
695 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool
, offsetof(ExecContext
, ignore_sigpipe
), SD_BUS_VTABLE_PROPERTY_CONST
),
696 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool
, offsetof(ExecContext
, no_new_privileges
), SD_BUS_VTABLE_PROPERTY_CONST
),
697 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
698 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
699 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
700 SD_BUS_PROPERTY("Personality", "s", property_get_personality
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
701 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
702 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode
, offsetof(ExecContext
, runtime_directory_mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
703 SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL
, offsetof(ExecContext
, runtime_directory
), SD_BUS_VTABLE_PROPERTY_CONST
),
707 static int append_exec_command(sd_bus_message
*reply
, ExecCommand
*c
) {
716 r
= sd_bus_message_open_container(reply
, 'r', "sasbttttuii");
720 r
= sd_bus_message_append(reply
, "s", c
->path
);
724 r
= sd_bus_message_append_strv(reply
, c
->argv
);
728 r
= sd_bus_message_append(reply
, "bttttuii",
730 c
->exec_status
.start_timestamp
.realtime
,
731 c
->exec_status
.start_timestamp
.monotonic
,
732 c
->exec_status
.exit_timestamp
.realtime
,
733 c
->exec_status
.exit_timestamp
.monotonic
,
734 (uint32_t) c
->exec_status
.pid
,
735 (int32_t) c
->exec_status
.code
,
736 (int32_t) c
->exec_status
.status
);
740 return sd_bus_message_close_container(reply
);
743 int bus_property_get_exec_command(
746 const char *interface
,
747 const char *property
,
748 sd_bus_message
*reply
,
750 sd_bus_error
*ret_error
) {
752 ExecCommand
*c
= (ExecCommand
*) userdata
;
758 r
= sd_bus_message_open_container(reply
, 'a', "(sasbttttuii)");
762 r
= append_exec_command(reply
, c
);
766 return sd_bus_message_close_container(reply
);
769 int bus_property_get_exec_command_list(
772 const char *interface
,
773 const char *property
,
774 sd_bus_message
*reply
,
776 sd_bus_error
*ret_error
) {
778 ExecCommand
*c
= *(ExecCommand
**) userdata
;
784 r
= sd_bus_message_open_container(reply
, 'a', "(sasbttttuii)");
788 LIST_FOREACH(command
, c
, c
) {
789 r
= append_exec_command(reply
, c
);
794 return sd_bus_message_close_container(reply
);
797 int bus_exec_context_set_transient_property(
801 sd_bus_message
*message
,
802 UnitSetPropertiesMode mode
,
803 sd_bus_error
*error
) {
812 if (streq(name
, "User")) {
815 r
= sd_bus_message_read(message
, "s", &uu
);
819 if (mode
!= UNIT_CHECK
) {
822 c
->user
= mfree(c
->user
);
834 unit_write_drop_in_private_format(u
, mode
, name
, "User=%s\n", uu
);
839 } else if (streq(name
, "Group")) {
842 r
= sd_bus_message_read(message
, "s", &gg
);
846 if (mode
!= UNIT_CHECK
) {
849 c
->group
= mfree(c
->group
);
861 unit_write_drop_in_private_format(u
, mode
, name
, "Group=%s\n", gg
);
865 } else if (streq(name
, "SyslogIdentifier")) {
868 r
= sd_bus_message_read(message
, "s", &id
);
872 if (mode
!= UNIT_CHECK
) {
875 c
->syslog_identifier
= mfree(c
->syslog_identifier
);
883 free(c
->syslog_identifier
);
884 c
->syslog_identifier
= t
;
887 unit_write_drop_in_private_format(u
, mode
, name
, "SyslogIdentifier=%s\n", id
);
891 } else if (streq(name
, "SyslogLevel")) {
894 r
= sd_bus_message_read(message
, "i", &level
);
898 if (!log_level_is_valid(level
))
899 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Log level value out of range");
901 if (mode
!= UNIT_CHECK
) {
902 c
->syslog_priority
= (c
->syslog_priority
& LOG_FACMASK
) | level
;
903 unit_write_drop_in_private_format(u
, mode
, name
, "SyslogLevel=%i\n", level
);
907 } else if (streq(name
, "SyslogFacility")) {
910 r
= sd_bus_message_read(message
, "i", &facility
);
914 if (!log_facility_unshifted_is_valid(facility
))
915 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Log facility value out of range");
917 if (mode
!= UNIT_CHECK
) {
918 c
->syslog_priority
= (facility
<< 3) | LOG_PRI(c
->syslog_priority
);
919 unit_write_drop_in_private_format(u
, mode
, name
, "SyslogFacility=%i\n", facility
);
923 } else if (streq(name
, "Nice")) {
926 r
= sd_bus_message_read(message
, "i", &n
);
930 if (n
< PRIO_MIN
|| n
>= PRIO_MAX
)
931 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Nice value out of range");
933 if (mode
!= UNIT_CHECK
) {
935 unit_write_drop_in_private_format(u
, mode
, name
, "Nice=%i\n", n
);
940 } else if (STR_IN_SET(name
, "TTYPath", "RootDirectory")) {
943 r
= sd_bus_message_read(message
, "s", &s
);
947 if (!path_is_absolute(s
))
948 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s takes an absolute path", name
);
950 if (mode
!= UNIT_CHECK
) {
951 if (streq(name
, "TTYPath"))
952 r
= free_and_strdup(&c
->tty_path
, s
);
954 assert(streq(name
, "RootDirectory"));
955 r
= free_and_strdup(&c
->root_directory
, s
);
960 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, s
);
965 } else if (streq(name
, "WorkingDirectory")) {
969 r
= sd_bus_message_read(message
, "s", &s
);
979 if (!streq(s
, "~") && !path_is_absolute(s
))
980 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "WorkingDirectory= expects an absolute path or '~'");
982 if (mode
!= UNIT_CHECK
) {
984 c
->working_directory
= mfree(c
->working_directory
);
985 c
->working_directory_home
= true;
987 r
= free_and_strdup(&c
->working_directory
, s
);
991 c
->working_directory_home
= false;
994 c
->working_directory_missing_ok
= missing_ok
;
995 unit_write_drop_in_private_format(u
, mode
, name
, "WorkingDirectory=%s%s", missing_ok
? "-" : "", s
);
1000 } else if (streq(name
, "StandardInput")) {
1004 r
= sd_bus_message_read(message
, "s", &s
);
1008 p
= exec_input_from_string(s
);
1010 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard input name");
1012 if (mode
!= UNIT_CHECK
) {
1015 unit_write_drop_in_private_format(u
, mode
, name
, "StandardInput=%s\n", exec_input_to_string(p
));
1021 } else if (streq(name
, "StandardOutput")) {
1025 r
= sd_bus_message_read(message
, "s", &s
);
1029 p
= exec_output_from_string(s
);
1031 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard output name");
1033 if (mode
!= UNIT_CHECK
) {
1036 unit_write_drop_in_private_format(u
, mode
, name
, "StandardOutput=%s\n", exec_output_to_string(p
));
1041 } else if (streq(name
, "StandardError")) {
1045 r
= sd_bus_message_read(message
, "s", &s
);
1049 p
= exec_output_from_string(s
);
1051 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard error name");
1053 if (mode
!= UNIT_CHECK
) {
1056 unit_write_drop_in_private_format(u
, mode
, name
, "StandardError=%s\n", exec_output_to_string(p
));
1061 } else if (STR_IN_SET(name
,
1062 "IgnoreSIGPIPE", "TTYVHangup", "TTYReset",
1063 "PrivateTmp", "PrivateDevices", "PrivateNetwork",
1064 "NoNewPrivileges", "SyslogLevelPrefix")) {
1067 r
= sd_bus_message_read(message
, "b", &b
);
1071 if (mode
!= UNIT_CHECK
) {
1072 if (streq(name
, "IgnoreSIGPIPE"))
1073 c
->ignore_sigpipe
= b
;
1074 else if (streq(name
, "TTYVHangup"))
1076 else if (streq(name
, "TTYReset"))
1078 else if (streq(name
, "PrivateTmp"))
1080 else if (streq(name
, "PrivateDevices"))
1081 c
->private_devices
= b
;
1082 else if (streq(name
, "PrivateNetwork"))
1083 c
->private_network
= b
;
1084 else if (streq(name
, "NoNewPrivileges"))
1085 c
->no_new_privileges
= b
;
1086 else if (streq(name
, "SyslogLevelPrefix"))
1087 c
->syslog_level_prefix
= b
;
1089 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, yes_no(b
));
1094 } else if (streq(name
, "UtmpIdentifier")) {
1097 r
= sd_bus_message_read(message
, "s", &id
);
1101 if (mode
!= UNIT_CHECK
) {
1103 c
->utmp_id
= mfree(c
->utmp_id
);
1104 else if (free_and_strdup(&c
->utmp_id
, id
) < 0)
1107 unit_write_drop_in_private_format(u
, mode
, name
, "UtmpIdentifier=%s\n", strempty(id
));
1112 } else if (streq(name
, "UtmpMode")) {
1116 r
= sd_bus_message_read(message
, "s", &s
);
1120 m
= exec_utmp_mode_from_string(s
);
1122 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid utmp mode");
1124 if (mode
!= UNIT_CHECK
) {
1127 unit_write_drop_in_private_format(u
, mode
, name
, "UtmpMode=%s\n", exec_utmp_mode_to_string(m
));
1132 } else if (streq(name
, "PAMName")) {
1135 r
= sd_bus_message_read(message
, "s", &n
);
1139 if (mode
!= UNIT_CHECK
) {
1141 c
->pam_name
= mfree(c
->pam_name
);
1142 else if (free_and_strdup(&c
->pam_name
, n
) < 0)
1145 unit_write_drop_in_private_format(u
, mode
, name
, "PAMName=%s\n", strempty(n
));
1150 } else if (streq(name
, "Environment")) {
1152 _cleanup_strv_free_
char **l
= NULL
;
1154 r
= sd_bus_message_read_strv(message
, &l
);
1158 if (!strv_env_is_valid(l
))
1159 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid environment block.");
1161 if (mode
!= UNIT_CHECK
) {
1162 _cleanup_free_
char *joined
= NULL
;
1165 if (strv_length(l
) == 0) {
1166 c
->environment
= strv_free(c
->environment
);
1167 unit_write_drop_in_private_format(u
, mode
, name
, "Environment=\n");
1169 e
= strv_env_merge(2, c
->environment
, l
);
1173 strv_free(c
->environment
);
1176 joined
= strv_join_quoted(c
->environment
);
1180 unit_write_drop_in_private_format(u
, mode
, name
, "Environment=%s\n", joined
);
1186 } else if (streq(name
, "TimerSlackNSec")) {
1190 r
= sd_bus_message_read(message
, "t", &n
);
1194 if (mode
!= UNIT_CHECK
) {
1195 c
->timer_slack_nsec
= n
;
1196 unit_write_drop_in_private_format(u
, mode
, name
, "TimerSlackNSec=" NSEC_FMT
"\n", n
);
1201 } else if (streq(name
, "OOMScoreAdjust")) {
1204 r
= sd_bus_message_read(message
, "i", &oa
);
1208 if (!oom_score_adjust_is_valid(oa
))
1209 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "OOM score adjust value out of range");
1211 if (mode
!= UNIT_CHECK
) {
1212 c
->oom_score_adjust
= oa
;
1213 c
->oom_score_adjust_set
= true;
1214 unit_write_drop_in_private_format(u
, mode
, name
, "OOMScoreAdjust=%i\n", oa
);
1219 } else if (streq(name
, "EnvironmentFiles")) {
1221 _cleanup_free_
char *joined
= NULL
;
1222 _cleanup_fclose_
FILE *f
= NULL
;
1223 _cleanup_free_
char **l
= NULL
;
1227 r
= sd_bus_message_enter_container(message
, 'a', "(sb)");
1231 f
= open_memstream(&joined
, &size
);
1235 STRV_FOREACH(i
, c
->environment_files
)
1236 fprintf(f
, "EnvironmentFile=%s\n", *i
);
1238 while ((r
= sd_bus_message_enter_container(message
, 'r', "sb")) > 0) {
1242 r
= sd_bus_message_read(message
, "sb", &path
, &b
);
1246 r
= sd_bus_message_exit_container(message
);
1250 if (!isempty(path
) && !path_is_absolute(path
))
1251 return sd_bus_error_set_errnof(error
, EINVAL
, "Path %s is not absolute.", path
);
1253 if (mode
!= UNIT_CHECK
) {
1256 buf
= strjoin(b
? "-" : "", path
, NULL
);
1260 fprintf(f
, "EnvironmentFile=%s\n", buf
);
1262 r
= strv_consume(&l
, buf
);
1270 r
= sd_bus_message_exit_container(message
);
1274 r
= fflush_and_check(f
);
1278 if (mode
!= UNIT_CHECK
) {
1279 if (strv_isempty(l
)) {
1280 c
->environment_files
= strv_free(c
->environment_files
);
1281 unit_write_drop_in_private(u
, mode
, name
, "EnvironmentFile=\n");
1283 r
= strv_extend_strv(&c
->environment_files
, l
, true);
1287 unit_write_drop_in_private(u
, mode
, name
, joined
);
1293 } else if (streq(name
, "PassEnvironment")) {
1295 _cleanup_strv_free_
char **l
= NULL
;
1297 r
= sd_bus_message_read_strv(message
, &l
);
1301 if (!strv_env_name_is_valid(l
))
1302 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid PassEnvironment block.");
1304 if (mode
!= UNIT_CHECK
) {
1305 if (strv_isempty(l
)) {
1306 c
->pass_environment
= strv_free(c
->pass_environment
);
1307 unit_write_drop_in_private_format(u
, mode
, name
, "PassEnvironment=\n");
1309 _cleanup_free_
char *joined
= NULL
;
1311 r
= strv_extend_strv(&c
->pass_environment
, l
, true);
1315 joined
= strv_join_quoted(c
->pass_environment
);
1319 unit_write_drop_in_private_format(u
, mode
, name
, "PassEnvironment=%s\n", joined
);
1325 } else if (STR_IN_SET(name
, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories")) {
1327 _cleanup_strv_free_
char **l
= NULL
;
1331 r
= sd_bus_message_read_strv(message
, &l
);
1335 STRV_FOREACH(p
, l
) {
1337 if (!utf8_is_valid(*p
))
1338 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid %s", name
);
1340 offset
= **p
== '-';
1341 if (!path_is_absolute(*p
+ offset
))
1342 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid %s", name
);
1345 if (mode
!= UNIT_CHECK
) {
1346 _cleanup_free_
char *joined
= NULL
;
1348 if (streq(name
, "ReadWriteDirectories"))
1349 dirs
= &c
->read_write_dirs
;
1350 else if (streq(name
, "ReadOnlyDirectories"))
1351 dirs
= &c
->read_only_dirs
;
1352 else if (streq(name
, "InaccessibleDirectories"))
1353 dirs
= &c
->inaccessible_dirs
;
1355 if (strv_length(l
) == 0) {
1356 *dirs
= strv_free(*dirs
);
1357 unit_write_drop_in_private_format(u
, mode
, name
, "%s=\n", name
);
1359 r
= strv_extend_strv(dirs
, l
, true);
1364 joined
= strv_join_quoted(*dirs
);
1368 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, joined
);
1375 } else if (streq(name
, "ProtectSystem")) {
1379 r
= sd_bus_message_read(message
, "s", &s
);
1383 r
= parse_boolean(s
);
1385 ps
= PROTECT_SYSTEM_YES
;
1387 ps
= PROTECT_SYSTEM_NO
;
1389 ps
= protect_system_from_string(s
);
1391 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Failed to parse protect system value");
1394 if (mode
!= UNIT_CHECK
) {
1395 c
->protect_system
= ps
;
1396 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, s
);
1401 } else if (streq(name
, "ProtectHome")) {
1405 r
= sd_bus_message_read(message
, "s", &s
);
1409 r
= parse_boolean(s
);
1411 ph
= PROTECT_HOME_YES
;
1413 ph
= PROTECT_HOME_NO
;
1415 ph
= protect_home_from_string(s
);
1417 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Failed to parse protect home value");
1420 if (mode
!= UNIT_CHECK
) {
1421 c
->protect_home
= ph
;
1422 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, s
);
1427 } else if (streq(name
, "RuntimeDirectory")) {
1428 _cleanup_strv_free_
char **l
= NULL
;
1431 r
= sd_bus_message_read_strv(message
, &l
);
1435 STRV_FOREACH(p
, l
) {
1436 if (!filename_is_valid(*p
))
1437 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Runtime directory is not valid %s", *p
);
1440 if (mode
!= UNIT_CHECK
) {
1441 _cleanup_free_
char *joined
= NULL
;
1443 if (strv_isempty(l
)) {
1444 c
->runtime_directory
= strv_free(c
->runtime_directory
);
1445 unit_write_drop_in_private_format(u
, mode
, name
, "%s=\n", name
);
1447 r
= strv_extend_strv(&c
->runtime_directory
, l
, true);
1452 joined
= strv_join_quoted(c
->runtime_directory
);
1456 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, joined
);
1462 } else if (rlimit_from_string(name
) >= 0) {
1466 r
= sd_bus_message_read(message
, "t", &rl
);
1470 if (rl
== (uint64_t) -1)
1475 if ((uint64_t) x
!= rl
)
1479 if (mode
!= UNIT_CHECK
) {
1482 z
= rlimit_from_string(name
);
1484 if (!c
->rlimit
[z
]) {
1485 c
->rlimit
[z
] = new(struct rlimit
, 1);
1490 c
->rlimit
[z
]->rlim_cur
= c
->rlimit
[z
]->rlim_max
= x
;
1492 if (x
== RLIM_INFINITY
)
1493 unit_write_drop_in_private_format(u
, mode
, name
, "%s=infinity\n", name
);
1495 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%" PRIu64
"\n", name
, rl
);