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 return sd_bus_message_append(reply
, "t", c
->capability_bounding_set
);
299 static int property_get_ambient_capabilities(
302 const char *interface
,
303 const char *property
,
304 sd_bus_message
*reply
,
306 sd_bus_error
*error
) {
308 ExecContext
*c
= userdata
;
314 return sd_bus_message_append(reply
, "t", c
->capability_ambient_set
);
317 static int property_get_capabilities(
320 const char *interface
,
321 const char *property
,
322 sd_bus_message
*reply
,
324 sd_bus_error
*error
) {
326 ExecContext
*c
= userdata
;
327 _cleanup_cap_free_charp_
char *t
= NULL
;
335 s
= t
= cap_to_text(c
->capabilities
, NULL
);
342 return sd_bus_message_append(reply
, "s", s
);
345 static int property_get_syscall_filter(
348 const char *interface
,
349 const char *property
,
350 sd_bus_message
*reply
,
352 sd_bus_error
*error
) {
354 ExecContext
*c
= userdata
;
355 _cleanup_strv_free_
char **l
= NULL
;
367 r
= sd_bus_message_open_container(reply
, 'r', "bas");
371 r
= sd_bus_message_append(reply
, "b", c
->syscall_whitelist
);
376 SET_FOREACH(id
, c
->syscall_filter
, i
) {
379 name
= seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE
, PTR_TO_INT(id
) - 1);
383 r
= strv_consume(&l
, name
);
391 r
= sd_bus_message_append_strv(reply
, l
);
395 return sd_bus_message_close_container(reply
);
398 static int property_get_syscall_archs(
401 const char *interface
,
402 const char *property
,
403 sd_bus_message
*reply
,
405 sd_bus_error
*error
) {
407 ExecContext
*c
= userdata
;
408 _cleanup_strv_free_
char **l
= NULL
;
421 SET_FOREACH(id
, c
->syscall_archs
, i
) {
424 name
= seccomp_arch_to_string(PTR_TO_UINT32(id
) - 1);
428 r
= strv_extend(&l
, name
);
436 r
= sd_bus_message_append_strv(reply
, l
);
443 static int property_get_syscall_errno(
446 const char *interface
,
447 const char *property
,
448 sd_bus_message
*reply
,
450 sd_bus_error
*error
) {
452 ExecContext
*c
= userdata
;
458 return sd_bus_message_append(reply
, "i", (int32_t) c
->syscall_errno
);
461 static int property_get_selinux_context(
464 const char *interface
,
465 const char *property
,
466 sd_bus_message
*reply
,
468 sd_bus_error
*error
) {
470 ExecContext
*c
= userdata
;
476 return sd_bus_message_append(reply
, "(bs)", c
->selinux_context_ignore
, c
->selinux_context
);
479 static int property_get_apparmor_profile(
482 const char *interface
,
483 const char *property
,
484 sd_bus_message
*reply
,
486 sd_bus_error
*error
) {
488 ExecContext
*c
= userdata
;
494 return sd_bus_message_append(reply
, "(bs)", c
->apparmor_profile_ignore
, c
->apparmor_profile
);
497 static int property_get_smack_process_label(
500 const char *interface
,
501 const char *property
,
502 sd_bus_message
*reply
,
504 sd_bus_error
*error
) {
506 ExecContext
*c
= userdata
;
512 return sd_bus_message_append(reply
, "(bs)", c
->smack_process_label_ignore
, c
->smack_process_label
);
515 static int property_get_personality(
518 const char *interface
,
519 const char *property
,
520 sd_bus_message
*reply
,
522 sd_bus_error
*error
) {
524 ExecContext
*c
= userdata
;
530 return sd_bus_message_append(reply
, "s", personality_to_string(c
->personality
));
533 static int property_get_address_families(
536 const char *interface
,
537 const char *property
,
538 sd_bus_message
*reply
,
540 sd_bus_error
*error
) {
542 ExecContext
*c
= userdata
;
543 _cleanup_strv_free_
char **l
= NULL
;
552 r
= sd_bus_message_open_container(reply
, 'r', "bas");
556 r
= sd_bus_message_append(reply
, "b", c
->address_families_whitelist
);
560 SET_FOREACH(af
, c
->address_families
, i
) {
563 name
= af_to_name(PTR_TO_INT(af
));
567 r
= strv_extend(&l
, name
);
574 r
= sd_bus_message_append_strv(reply
, l
);
578 return sd_bus_message_close_container(reply
);
581 static int property_get_working_directory(
584 const char *interface
,
585 const char *property
,
586 sd_bus_message
*reply
,
588 sd_bus_error
*error
) {
590 ExecContext
*c
= userdata
;
597 if (c
->working_directory_home
)
600 wd
= c
->working_directory
;
602 if (c
->working_directory_missing_ok
)
603 wd
= strjoina("!", wd
);
605 return sd_bus_message_append(reply
, "s", wd
);
608 static int property_get_syslog_level(
611 const char *interface
,
612 const char *property
,
613 sd_bus_message
*reply
,
615 sd_bus_error
*error
) {
617 ExecContext
*c
= userdata
;
623 return sd_bus_message_append(reply
, "i", LOG_PRI(c
->syslog_priority
));
626 static int property_get_syslog_facility(
629 const char *interface
,
630 const char *property
,
631 sd_bus_message
*reply
,
633 sd_bus_error
*error
) {
635 ExecContext
*c
= userdata
;
641 return sd_bus_message_append(reply
, "i", LOG_FAC(c
->syslog_priority
));
644 const sd_bus_vtable bus_exec_vtable
[] = {
645 SD_BUS_VTABLE_START(0),
646 SD_BUS_PROPERTY("Environment", "as", NULL
, offsetof(ExecContext
, environment
), SD_BUS_VTABLE_PROPERTY_CONST
),
647 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
648 SD_BUS_PROPERTY("PassEnvironment", "as", NULL
, offsetof(ExecContext
, pass_environment
), SD_BUS_VTABLE_PROPERTY_CONST
),
649 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode
, offsetof(ExecContext
, umask
), SD_BUS_VTABLE_PROPERTY_CONST
),
650 SD_BUS_PROPERTY("LimitCPU", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CPU
]), SD_BUS_VTABLE_PROPERTY_CONST
),
651 SD_BUS_PROPERTY("LimitCPUSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CPU
]), SD_BUS_VTABLE_PROPERTY_CONST
),
652 SD_BUS_PROPERTY("LimitFSIZE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_FSIZE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
653 SD_BUS_PROPERTY("LimitFSIZESoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_FSIZE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
654 SD_BUS_PROPERTY("LimitDATA", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_DATA
]), SD_BUS_VTABLE_PROPERTY_CONST
),
655 SD_BUS_PROPERTY("LimitDATASoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_DATA
]), SD_BUS_VTABLE_PROPERTY_CONST
),
656 SD_BUS_PROPERTY("LimitSTACK", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_STACK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
657 SD_BUS_PROPERTY("LimitSTACKSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_STACK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
658 SD_BUS_PROPERTY("LimitCORE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CORE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
659 SD_BUS_PROPERTY("LimitCORESoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CORE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
660 SD_BUS_PROPERTY("LimitRSS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RSS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
661 SD_BUS_PROPERTY("LimitRSSSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RSS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
662 SD_BUS_PROPERTY("LimitNOFILE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NOFILE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
663 SD_BUS_PROPERTY("LimitNOFILESoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NOFILE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
664 SD_BUS_PROPERTY("LimitAS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_AS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
665 SD_BUS_PROPERTY("LimitASSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_AS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
666 SD_BUS_PROPERTY("LimitNPROC", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NPROC
]), SD_BUS_VTABLE_PROPERTY_CONST
),
667 SD_BUS_PROPERTY("LimitNPROCSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NPROC
]), SD_BUS_VTABLE_PROPERTY_CONST
),
668 SD_BUS_PROPERTY("LimitMEMLOCK", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MEMLOCK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
669 SD_BUS_PROPERTY("LimitMEMLOCKSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MEMLOCK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
670 SD_BUS_PROPERTY("LimitLOCKS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_LOCKS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
671 SD_BUS_PROPERTY("LimitLOCKSSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_LOCKS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
672 SD_BUS_PROPERTY("LimitSIGPENDING", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_SIGPENDING
]), SD_BUS_VTABLE_PROPERTY_CONST
),
673 SD_BUS_PROPERTY("LimitSIGPENDINGSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_SIGPENDING
]), SD_BUS_VTABLE_PROPERTY_CONST
),
674 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MSGQUEUE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
675 SD_BUS_PROPERTY("LimitMSGQUEUESoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MSGQUEUE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
676 SD_BUS_PROPERTY("LimitNICE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NICE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
677 SD_BUS_PROPERTY("LimitNICESoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NICE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
678 SD_BUS_PROPERTY("LimitRTPRIO", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTPRIO
]), SD_BUS_VTABLE_PROPERTY_CONST
),
679 SD_BUS_PROPERTY("LimitRTPRIOSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTPRIO
]), SD_BUS_VTABLE_PROPERTY_CONST
),
680 SD_BUS_PROPERTY("LimitRTTIME", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTTIME
]), SD_BUS_VTABLE_PROPERTY_CONST
),
681 SD_BUS_PROPERTY("LimitRTTIMESoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTTIME
]), SD_BUS_VTABLE_PROPERTY_CONST
),
682 SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
683 SD_BUS_PROPERTY("RootDirectory", "s", NULL
, offsetof(ExecContext
, root_directory
), SD_BUS_VTABLE_PROPERTY_CONST
),
684 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
685 SD_BUS_PROPERTY("Nice", "i", property_get_nice
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
686 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
687 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
688 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
689 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
690 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
691 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool
, offsetof(ExecContext
, cpu_sched_reset_on_fork
), SD_BUS_VTABLE_PROPERTY_CONST
),
692 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool
, offsetof(ExecContext
, non_blocking
), SD_BUS_VTABLE_PROPERTY_CONST
),
693 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input
, offsetof(ExecContext
, std_input
), SD_BUS_VTABLE_PROPERTY_CONST
),
694 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output
, offsetof(ExecContext
, std_output
), SD_BUS_VTABLE_PROPERTY_CONST
),
695 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output
, offsetof(ExecContext
, std_error
), SD_BUS_VTABLE_PROPERTY_CONST
),
696 SD_BUS_PROPERTY("TTYPath", "s", NULL
, offsetof(ExecContext
, tty_path
), SD_BUS_VTABLE_PROPERTY_CONST
),
697 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_reset
), SD_BUS_VTABLE_PROPERTY_CONST
),
698 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_vhangup
), SD_BUS_VTABLE_PROPERTY_CONST
),
699 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_vt_disallocate
), SD_BUS_VTABLE_PROPERTY_CONST
),
700 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int
, offsetof(ExecContext
, syslog_priority
), SD_BUS_VTABLE_PROPERTY_CONST
),
701 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL
, offsetof(ExecContext
, syslog_identifier
), SD_BUS_VTABLE_PROPERTY_CONST
),
702 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool
, offsetof(ExecContext
, syslog_level_prefix
), SD_BUS_VTABLE_PROPERTY_CONST
),
703 SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
704 SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
705 SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
706 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int
, offsetof(ExecContext
, secure_bits
), SD_BUS_VTABLE_PROPERTY_CONST
),
707 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
708 SD_BUS_PROPERTY("AmbientCapabilities", "t", property_get_ambient_capabilities
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
709 SD_BUS_PROPERTY("User", "s", NULL
, offsetof(ExecContext
, user
), SD_BUS_VTABLE_PROPERTY_CONST
),
710 SD_BUS_PROPERTY("Group", "s", NULL
, offsetof(ExecContext
, group
), SD_BUS_VTABLE_PROPERTY_CONST
),
711 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL
, offsetof(ExecContext
, supplementary_groups
), SD_BUS_VTABLE_PROPERTY_CONST
),
712 SD_BUS_PROPERTY("PAMName", "s", NULL
, offsetof(ExecContext
, pam_name
), SD_BUS_VTABLE_PROPERTY_CONST
),
713 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL
, offsetof(ExecContext
, read_write_dirs
), SD_BUS_VTABLE_PROPERTY_CONST
),
714 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL
, offsetof(ExecContext
, read_only_dirs
), SD_BUS_VTABLE_PROPERTY_CONST
),
715 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL
, offsetof(ExecContext
, inaccessible_dirs
), SD_BUS_VTABLE_PROPERTY_CONST
),
716 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong
, offsetof(ExecContext
, mount_flags
), SD_BUS_VTABLE_PROPERTY_CONST
),
717 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool
, offsetof(ExecContext
, private_tmp
), SD_BUS_VTABLE_PROPERTY_CONST
),
718 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool
, offsetof(ExecContext
, private_network
), SD_BUS_VTABLE_PROPERTY_CONST
),
719 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool
, offsetof(ExecContext
, private_devices
), SD_BUS_VTABLE_PROPERTY_CONST
),
720 SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home
, offsetof(ExecContext
, protect_home
), SD_BUS_VTABLE_PROPERTY_CONST
),
721 SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system
, offsetof(ExecContext
, protect_system
), SD_BUS_VTABLE_PROPERTY_CONST
),
722 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool
, offsetof(ExecContext
, same_pgrp
), SD_BUS_VTABLE_PROPERTY_CONST
),
723 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL
, offsetof(ExecContext
, utmp_id
), SD_BUS_VTABLE_PROPERTY_CONST
),
724 SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode
, offsetof(ExecContext
, utmp_mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
725 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
726 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
727 SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
728 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool
, offsetof(ExecContext
, ignore_sigpipe
), SD_BUS_VTABLE_PROPERTY_CONST
),
729 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool
, offsetof(ExecContext
, no_new_privileges
), SD_BUS_VTABLE_PROPERTY_CONST
),
730 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
731 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
732 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
733 SD_BUS_PROPERTY("Personality", "s", property_get_personality
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
734 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
735 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode
, offsetof(ExecContext
, runtime_directory_mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
736 SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL
, offsetof(ExecContext
, runtime_directory
), SD_BUS_VTABLE_PROPERTY_CONST
),
740 static int append_exec_command(sd_bus_message
*reply
, ExecCommand
*c
) {
749 r
= sd_bus_message_open_container(reply
, 'r', "sasbttttuii");
753 r
= sd_bus_message_append(reply
, "s", c
->path
);
757 r
= sd_bus_message_append_strv(reply
, c
->argv
);
761 r
= sd_bus_message_append(reply
, "bttttuii",
763 c
->exec_status
.start_timestamp
.realtime
,
764 c
->exec_status
.start_timestamp
.monotonic
,
765 c
->exec_status
.exit_timestamp
.realtime
,
766 c
->exec_status
.exit_timestamp
.monotonic
,
767 (uint32_t) c
->exec_status
.pid
,
768 (int32_t) c
->exec_status
.code
,
769 (int32_t) c
->exec_status
.status
);
773 return sd_bus_message_close_container(reply
);
776 int bus_property_get_exec_command(
779 const char *interface
,
780 const char *property
,
781 sd_bus_message
*reply
,
783 sd_bus_error
*ret_error
) {
785 ExecCommand
*c
= (ExecCommand
*) userdata
;
791 r
= sd_bus_message_open_container(reply
, 'a', "(sasbttttuii)");
795 r
= append_exec_command(reply
, c
);
799 return sd_bus_message_close_container(reply
);
802 int bus_property_get_exec_command_list(
805 const char *interface
,
806 const char *property
,
807 sd_bus_message
*reply
,
809 sd_bus_error
*ret_error
) {
811 ExecCommand
*c
= *(ExecCommand
**) userdata
;
817 r
= sd_bus_message_open_container(reply
, 'a', "(sasbttttuii)");
821 LIST_FOREACH(command
, c
, c
) {
822 r
= append_exec_command(reply
, c
);
827 return sd_bus_message_close_container(reply
);
830 int bus_exec_context_set_transient_property(
834 sd_bus_message
*message
,
835 UnitSetPropertiesMode mode
,
836 sd_bus_error
*error
) {
845 if (streq(name
, "User")) {
848 r
= sd_bus_message_read(message
, "s", &uu
);
852 if (mode
!= UNIT_CHECK
) {
855 c
->user
= mfree(c
->user
);
867 unit_write_drop_in_private_format(u
, mode
, name
, "User=%s\n", uu
);
872 } else if (streq(name
, "Group")) {
875 r
= sd_bus_message_read(message
, "s", &gg
);
879 if (mode
!= UNIT_CHECK
) {
882 c
->group
= mfree(c
->group
);
894 unit_write_drop_in_private_format(u
, mode
, name
, "Group=%s\n", gg
);
898 } else if (streq(name
, "SyslogIdentifier")) {
901 r
= sd_bus_message_read(message
, "s", &id
);
905 if (mode
!= UNIT_CHECK
) {
908 c
->syslog_identifier
= mfree(c
->syslog_identifier
);
916 free(c
->syslog_identifier
);
917 c
->syslog_identifier
= t
;
920 unit_write_drop_in_private_format(u
, mode
, name
, "SyslogIdentifier=%s\n", id
);
924 } else if (streq(name
, "SyslogLevel")) {
927 r
= sd_bus_message_read(message
, "i", &level
);
931 if (!log_level_is_valid(level
))
932 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Log level value out of range");
934 if (mode
!= UNIT_CHECK
) {
935 c
->syslog_priority
= (c
->syslog_priority
& LOG_FACMASK
) | level
;
936 unit_write_drop_in_private_format(u
, mode
, name
, "SyslogLevel=%i\n", level
);
940 } else if (streq(name
, "SyslogFacility")) {
943 r
= sd_bus_message_read(message
, "i", &facility
);
947 if (!log_facility_unshifted_is_valid(facility
))
948 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Log facility value out of range");
950 if (mode
!= UNIT_CHECK
) {
951 c
->syslog_priority
= (facility
<< 3) | LOG_PRI(c
->syslog_priority
);
952 unit_write_drop_in_private_format(u
, mode
, name
, "SyslogFacility=%i\n", facility
);
956 } else if (streq(name
, "Nice")) {
959 r
= sd_bus_message_read(message
, "i", &n
);
963 if (n
< PRIO_MIN
|| n
>= PRIO_MAX
)
964 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Nice value out of range");
966 if (mode
!= UNIT_CHECK
) {
968 unit_write_drop_in_private_format(u
, mode
, name
, "Nice=%i\n", n
);
973 } else if (STR_IN_SET(name
, "TTYPath", "RootDirectory")) {
976 r
= sd_bus_message_read(message
, "s", &s
);
980 if (!path_is_absolute(s
))
981 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s takes an absolute path", name
);
983 if (mode
!= UNIT_CHECK
) {
984 if (streq(name
, "TTYPath"))
985 r
= free_and_strdup(&c
->tty_path
, s
);
987 assert(streq(name
, "RootDirectory"));
988 r
= free_and_strdup(&c
->root_directory
, s
);
993 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, s
);
998 } else if (streq(name
, "WorkingDirectory")) {
1002 r
= sd_bus_message_read(message
, "s", &s
);
1012 if (!streq(s
, "~") && !path_is_absolute(s
))
1013 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "WorkingDirectory= expects an absolute path or '~'");
1015 if (mode
!= UNIT_CHECK
) {
1016 if (streq(s
, "~")) {
1017 c
->working_directory
= mfree(c
->working_directory
);
1018 c
->working_directory_home
= true;
1020 r
= free_and_strdup(&c
->working_directory
, s
);
1024 c
->working_directory_home
= false;
1027 c
->working_directory_missing_ok
= missing_ok
;
1028 unit_write_drop_in_private_format(u
, mode
, name
, "WorkingDirectory=%s%s", missing_ok
? "-" : "", s
);
1033 } else if (streq(name
, "StandardInput")) {
1037 r
= sd_bus_message_read(message
, "s", &s
);
1041 p
= exec_input_from_string(s
);
1043 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard input name");
1045 if (mode
!= UNIT_CHECK
) {
1048 unit_write_drop_in_private_format(u
, mode
, name
, "StandardInput=%s\n", exec_input_to_string(p
));
1054 } else if (streq(name
, "StandardOutput")) {
1058 r
= sd_bus_message_read(message
, "s", &s
);
1062 p
= exec_output_from_string(s
);
1064 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard output name");
1066 if (mode
!= UNIT_CHECK
) {
1069 unit_write_drop_in_private_format(u
, mode
, name
, "StandardOutput=%s\n", exec_output_to_string(p
));
1074 } else if (streq(name
, "StandardError")) {
1078 r
= sd_bus_message_read(message
, "s", &s
);
1082 p
= exec_output_from_string(s
);
1084 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard error name");
1086 if (mode
!= UNIT_CHECK
) {
1089 unit_write_drop_in_private_format(u
, mode
, name
, "StandardError=%s\n", exec_output_to_string(p
));
1094 } else if (STR_IN_SET(name
,
1095 "IgnoreSIGPIPE", "TTYVHangup", "TTYReset",
1096 "PrivateTmp", "PrivateDevices", "PrivateNetwork",
1097 "NoNewPrivileges", "SyslogLevelPrefix")) {
1100 r
= sd_bus_message_read(message
, "b", &b
);
1104 if (mode
!= UNIT_CHECK
) {
1105 if (streq(name
, "IgnoreSIGPIPE"))
1106 c
->ignore_sigpipe
= b
;
1107 else if (streq(name
, "TTYVHangup"))
1109 else if (streq(name
, "TTYReset"))
1111 else if (streq(name
, "PrivateTmp"))
1113 else if (streq(name
, "PrivateDevices"))
1114 c
->private_devices
= b
;
1115 else if (streq(name
, "PrivateNetwork"))
1116 c
->private_network
= b
;
1117 else if (streq(name
, "NoNewPrivileges"))
1118 c
->no_new_privileges
= b
;
1119 else if (streq(name
, "SyslogLevelPrefix"))
1120 c
->syslog_level_prefix
= b
;
1122 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, yes_no(b
));
1127 } else if (streq(name
, "UtmpIdentifier")) {
1130 r
= sd_bus_message_read(message
, "s", &id
);
1134 if (mode
!= UNIT_CHECK
) {
1136 c
->utmp_id
= mfree(c
->utmp_id
);
1137 else if (free_and_strdup(&c
->utmp_id
, id
) < 0)
1140 unit_write_drop_in_private_format(u
, mode
, name
, "UtmpIdentifier=%s\n", strempty(id
));
1145 } else if (streq(name
, "UtmpMode")) {
1149 r
= sd_bus_message_read(message
, "s", &s
);
1153 m
= exec_utmp_mode_from_string(s
);
1155 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid utmp mode");
1157 if (mode
!= UNIT_CHECK
) {
1160 unit_write_drop_in_private_format(u
, mode
, name
, "UtmpMode=%s\n", exec_utmp_mode_to_string(m
));
1165 } else if (streq(name
, "PAMName")) {
1168 r
= sd_bus_message_read(message
, "s", &n
);
1172 if (mode
!= UNIT_CHECK
) {
1174 c
->pam_name
= mfree(c
->pam_name
);
1175 else if (free_and_strdup(&c
->pam_name
, n
) < 0)
1178 unit_write_drop_in_private_format(u
, mode
, name
, "PAMName=%s\n", strempty(n
));
1183 } else if (streq(name
, "Environment")) {
1185 _cleanup_strv_free_
char **l
= NULL
;
1187 r
= sd_bus_message_read_strv(message
, &l
);
1191 if (!strv_env_is_valid(l
))
1192 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid environment block.");
1194 if (mode
!= UNIT_CHECK
) {
1195 _cleanup_free_
char *joined
= NULL
;
1198 if (strv_length(l
) == 0) {
1199 c
->environment
= strv_free(c
->environment
);
1200 unit_write_drop_in_private_format(u
, mode
, name
, "Environment=\n");
1202 e
= strv_env_merge(2, c
->environment
, l
);
1206 strv_free(c
->environment
);
1209 joined
= strv_join_quoted(c
->environment
);
1213 unit_write_drop_in_private_format(u
, mode
, name
, "Environment=%s\n", joined
);
1219 } else if (streq(name
, "TimerSlackNSec")) {
1223 r
= sd_bus_message_read(message
, "t", &n
);
1227 if (mode
!= UNIT_CHECK
) {
1228 c
->timer_slack_nsec
= n
;
1229 unit_write_drop_in_private_format(u
, mode
, name
, "TimerSlackNSec=" NSEC_FMT
"\n", n
);
1234 } else if (streq(name
, "OOMScoreAdjust")) {
1237 r
= sd_bus_message_read(message
, "i", &oa
);
1241 if (!oom_score_adjust_is_valid(oa
))
1242 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "OOM score adjust value out of range");
1244 if (mode
!= UNIT_CHECK
) {
1245 c
->oom_score_adjust
= oa
;
1246 c
->oom_score_adjust_set
= true;
1247 unit_write_drop_in_private_format(u
, mode
, name
, "OOMScoreAdjust=%i\n", oa
);
1252 } else if (streq(name
, "EnvironmentFiles")) {
1254 _cleanup_free_
char *joined
= NULL
;
1255 _cleanup_fclose_
FILE *f
= NULL
;
1256 _cleanup_free_
char **l
= NULL
;
1260 r
= sd_bus_message_enter_container(message
, 'a', "(sb)");
1264 f
= open_memstream(&joined
, &size
);
1268 STRV_FOREACH(i
, c
->environment_files
)
1269 fprintf(f
, "EnvironmentFile=%s\n", *i
);
1271 while ((r
= sd_bus_message_enter_container(message
, 'r', "sb")) > 0) {
1275 r
= sd_bus_message_read(message
, "sb", &path
, &b
);
1279 r
= sd_bus_message_exit_container(message
);
1283 if (!isempty(path
) && !path_is_absolute(path
))
1284 return sd_bus_error_set_errnof(error
, EINVAL
, "Path %s is not absolute.", path
);
1286 if (mode
!= UNIT_CHECK
) {
1289 buf
= strjoin(b
? "-" : "", path
, NULL
);
1293 fprintf(f
, "EnvironmentFile=%s\n", buf
);
1295 r
= strv_consume(&l
, buf
);
1303 r
= sd_bus_message_exit_container(message
);
1307 r
= fflush_and_check(f
);
1311 if (mode
!= UNIT_CHECK
) {
1312 if (strv_isempty(l
)) {
1313 c
->environment_files
= strv_free(c
->environment_files
);
1314 unit_write_drop_in_private(u
, mode
, name
, "EnvironmentFile=\n");
1316 r
= strv_extend_strv(&c
->environment_files
, l
, true);
1320 unit_write_drop_in_private(u
, mode
, name
, joined
);
1326 } else if (streq(name
, "PassEnvironment")) {
1328 _cleanup_strv_free_
char **l
= NULL
;
1330 r
= sd_bus_message_read_strv(message
, &l
);
1334 if (!strv_env_name_is_valid(l
))
1335 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid PassEnvironment block.");
1337 if (mode
!= UNIT_CHECK
) {
1338 if (strv_isempty(l
)) {
1339 c
->pass_environment
= strv_free(c
->pass_environment
);
1340 unit_write_drop_in_private_format(u
, mode
, name
, "PassEnvironment=\n");
1342 _cleanup_free_
char *joined
= NULL
;
1344 r
= strv_extend_strv(&c
->pass_environment
, l
, true);
1348 joined
= strv_join_quoted(c
->pass_environment
);
1352 unit_write_drop_in_private_format(u
, mode
, name
, "PassEnvironment=%s\n", joined
);
1358 } else if (STR_IN_SET(name
, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories")) {
1360 _cleanup_strv_free_
char **l
= NULL
;
1364 r
= sd_bus_message_read_strv(message
, &l
);
1368 STRV_FOREACH(p
, l
) {
1370 if (!utf8_is_valid(*p
))
1371 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid %s", name
);
1373 offset
= **p
== '-';
1374 if (!path_is_absolute(*p
+ offset
))
1375 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid %s", name
);
1378 if (mode
!= UNIT_CHECK
) {
1379 _cleanup_free_
char *joined
= NULL
;
1381 if (streq(name
, "ReadWriteDirectories"))
1382 dirs
= &c
->read_write_dirs
;
1383 else if (streq(name
, "ReadOnlyDirectories"))
1384 dirs
= &c
->read_only_dirs
;
1385 else if (streq(name
, "InaccessibleDirectories"))
1386 dirs
= &c
->inaccessible_dirs
;
1388 if (strv_length(l
) == 0) {
1389 *dirs
= strv_free(*dirs
);
1390 unit_write_drop_in_private_format(u
, mode
, name
, "%s=\n", name
);
1392 r
= strv_extend_strv(dirs
, l
, true);
1397 joined
= strv_join_quoted(*dirs
);
1401 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, joined
);
1408 } else if (streq(name
, "ProtectSystem")) {
1412 r
= sd_bus_message_read(message
, "s", &s
);
1416 r
= parse_boolean(s
);
1418 ps
= PROTECT_SYSTEM_YES
;
1420 ps
= PROTECT_SYSTEM_NO
;
1422 ps
= protect_system_from_string(s
);
1424 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Failed to parse protect system value");
1427 if (mode
!= UNIT_CHECK
) {
1428 c
->protect_system
= ps
;
1429 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, s
);
1434 } else if (streq(name
, "ProtectHome")) {
1438 r
= sd_bus_message_read(message
, "s", &s
);
1442 r
= parse_boolean(s
);
1444 ph
= PROTECT_HOME_YES
;
1446 ph
= PROTECT_HOME_NO
;
1448 ph
= protect_home_from_string(s
);
1450 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Failed to parse protect home value");
1453 if (mode
!= UNIT_CHECK
) {
1454 c
->protect_home
= ph
;
1455 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, s
);
1460 } else if (streq(name
, "RuntimeDirectory")) {
1461 _cleanup_strv_free_
char **l
= NULL
;
1464 r
= sd_bus_message_read_strv(message
, &l
);
1468 STRV_FOREACH(p
, l
) {
1469 if (!filename_is_valid(*p
))
1470 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Runtime directory is not valid %s", *p
);
1473 if (mode
!= UNIT_CHECK
) {
1474 _cleanup_free_
char *joined
= NULL
;
1476 if (strv_isempty(l
)) {
1477 c
->runtime_directory
= strv_free(c
->runtime_directory
);
1478 unit_write_drop_in_private_format(u
, mode
, name
, "%s=\n", name
);
1480 r
= strv_extend_strv(&c
->runtime_directory
, l
, true);
1485 joined
= strv_join_quoted(c
->runtime_directory
);
1489 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, joined
);
1495 } else if (rlimit_from_string(name
) >= 0) {
1499 r
= sd_bus_message_read(message
, "t", &rl
);
1503 if (rl
== (uint64_t) -1)
1508 if ((uint64_t) x
!= rl
)
1512 if (mode
!= UNIT_CHECK
) {
1515 z
= rlimit_from_string(name
);
1517 if (!c
->rlimit
[z
]) {
1518 c
->rlimit
[z
] = new(struct rlimit
, 1);
1523 c
->rlimit
[z
]->rlim_cur
= c
->rlimit
[z
]->rlim_max
= x
;
1525 if (x
== RLIM_INFINITY
)
1526 unit_write_drop_in_private_format(u
, mode
, name
, "%s=infinity\n", name
);
1528 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%" PRIu64
"\n", name
, rl
);