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>
30 #include "capability-util.h"
31 #include "dbus-execute.h"
38 #include "namespace.h"
39 #include "parse-util.h"
40 #include "path-util.h"
41 #include "rlimit-util.h"
43 #include "seccomp-util.h"
48 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output
, exec_output
, ExecOutput
);
50 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input
, exec_input
, ExecInput
);
52 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_utmp_mode
, exec_utmp_mode
, ExecUtmpMode
);
54 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_home
, protect_home
, ProtectHome
);
55 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_system
, protect_system
, ProtectSystem
);
57 static int property_get_environment_files(
60 const char *interface
,
62 sd_bus_message
*reply
,
64 sd_bus_error
*error
) {
66 ExecContext
*c
= userdata
;
74 r
= sd_bus_message_open_container(reply
, 'a', "(sb)");
78 STRV_FOREACH(j
, c
->environment_files
) {
81 r
= sd_bus_message_append(reply
, "(sb)", fn
[0] == '-' ? fn
+ 1 : fn
, fn
[0] == '-');
86 return sd_bus_message_close_container(reply
);
89 static int property_get_oom_score_adjust(
92 const char *interface
,
94 sd_bus_message
*reply
,
96 sd_bus_error
*error
) {
99 ExecContext
*c
= userdata
;
106 if (c
->oom_score_adjust_set
)
107 n
= c
->oom_score_adjust
;
109 _cleanup_free_
char *t
= NULL
;
112 if (read_one_line_file("/proc/self/oom_score_adj", &t
) >= 0)
116 return sd_bus_message_append(reply
, "i", n
);
119 static int property_get_nice(
122 const char *interface
,
123 const char *property
,
124 sd_bus_message
*reply
,
126 sd_bus_error
*error
) {
129 ExecContext
*c
= userdata
;
140 n
= getpriority(PRIO_PROCESS
, 0);
145 return sd_bus_message_append(reply
, "i", n
);
148 static int property_get_ioprio(
151 const char *interface
,
152 const char *property
,
153 sd_bus_message
*reply
,
155 sd_bus_error
*error
) {
158 ExecContext
*c
= userdata
;
168 n
= ioprio_get(IOPRIO_WHO_PROCESS
, 0);
170 n
= IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE
, 4);
173 return sd_bus_message_append(reply
, "i", n
);
176 static int property_get_cpu_sched_policy(
179 const char *interface
,
180 const char *property
,
181 sd_bus_message
*reply
,
183 sd_bus_error
*error
) {
185 ExecContext
*c
= userdata
;
192 if (c
->cpu_sched_set
)
193 n
= c
->cpu_sched_policy
;
195 n
= sched_getscheduler(0);
200 return sd_bus_message_append(reply
, "i", n
);
203 static int property_get_cpu_sched_priority(
206 const char *interface
,
207 const char *property
,
208 sd_bus_message
*reply
,
210 sd_bus_error
*error
) {
212 ExecContext
*c
= userdata
;
219 if (c
->cpu_sched_set
)
220 n
= c
->cpu_sched_priority
;
222 struct sched_param p
= {};
224 if (sched_getparam(0, &p
) >= 0)
225 n
= p
.sched_priority
;
230 return sd_bus_message_append(reply
, "i", n
);
233 static int property_get_cpu_affinity(
236 const char *interface
,
237 const char *property
,
238 sd_bus_message
*reply
,
240 sd_bus_error
*error
) {
242 ExecContext
*c
= userdata
;
249 return sd_bus_message_append_array(reply
, 'y', c
->cpuset
, CPU_ALLOC_SIZE(c
->cpuset_ncpus
));
251 return sd_bus_message_append_array(reply
, 'y', NULL
, 0);
254 static int property_get_timer_slack_nsec(
257 const char *interface
,
258 const char *property
,
259 sd_bus_message
*reply
,
261 sd_bus_error
*error
) {
263 ExecContext
*c
= userdata
;
270 if (c
->timer_slack_nsec
!= NSEC_INFINITY
)
271 u
= (uint64_t) c
->timer_slack_nsec
;
273 u
= (uint64_t) prctl(PR_GET_TIMERSLACK
);
275 return sd_bus_message_append(reply
, "t", u
);
278 static int property_get_capability_bounding_set(
281 const char *interface
,
282 const char *property
,
283 sd_bus_message
*reply
,
285 sd_bus_error
*error
) {
287 ExecContext
*c
= userdata
;
293 /* We store this negated internally, to match the kernel, but
294 * we expose it normalized. */
295 return sd_bus_message_append(reply
, "t", ~c
->capability_bounding_set_drop
);
298 static int property_get_capabilities(
301 const char *interface
,
302 const char *property
,
303 sd_bus_message
*reply
,
305 sd_bus_error
*error
) {
307 ExecContext
*c
= userdata
;
308 _cleanup_cap_free_charp_
char *t
= NULL
;
316 s
= t
= cap_to_text(c
->capabilities
, NULL
);
323 return sd_bus_message_append(reply
, "s", s
);
326 static int property_get_syscall_filter(
329 const char *interface
,
330 const char *property
,
331 sd_bus_message
*reply
,
333 sd_bus_error
*error
) {
335 ExecContext
*c
= userdata
;
336 _cleanup_strv_free_
char **l
= NULL
;
348 r
= sd_bus_message_open_container(reply
, 'r', "bas");
352 r
= sd_bus_message_append(reply
, "b", c
->syscall_whitelist
);
357 SET_FOREACH(id
, c
->syscall_filter
, i
) {
360 name
= seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE
, PTR_TO_INT(id
) - 1);
364 r
= strv_consume(&l
, name
);
372 r
= sd_bus_message_append_strv(reply
, l
);
376 return sd_bus_message_close_container(reply
);
379 static int property_get_syscall_archs(
382 const char *interface
,
383 const char *property
,
384 sd_bus_message
*reply
,
386 sd_bus_error
*error
) {
388 ExecContext
*c
= userdata
;
389 _cleanup_strv_free_
char **l
= NULL
;
402 SET_FOREACH(id
, c
->syscall_archs
, i
) {
405 name
= seccomp_arch_to_string(PTR_TO_UINT32(id
) - 1);
409 r
= strv_extend(&l
, name
);
417 r
= sd_bus_message_append_strv(reply
, l
);
424 static int property_get_syscall_errno(
427 const char *interface
,
428 const char *property
,
429 sd_bus_message
*reply
,
431 sd_bus_error
*error
) {
433 ExecContext
*c
= userdata
;
439 return sd_bus_message_append(reply
, "i", (int32_t) c
->syscall_errno
);
442 static int property_get_selinux_context(
445 const char *interface
,
446 const char *property
,
447 sd_bus_message
*reply
,
449 sd_bus_error
*error
) {
451 ExecContext
*c
= userdata
;
457 return sd_bus_message_append(reply
, "(bs)", c
->selinux_context_ignore
, c
->selinux_context
);
460 static int property_get_apparmor_profile(
463 const char *interface
,
464 const char *property
,
465 sd_bus_message
*reply
,
467 sd_bus_error
*error
) {
469 ExecContext
*c
= userdata
;
475 return sd_bus_message_append(reply
, "(bs)", c
->apparmor_profile_ignore
, c
->apparmor_profile
);
478 static int property_get_smack_process_label(
481 const char *interface
,
482 const char *property
,
483 sd_bus_message
*reply
,
485 sd_bus_error
*error
) {
487 ExecContext
*c
= userdata
;
493 return sd_bus_message_append(reply
, "(bs)", c
->smack_process_label_ignore
, c
->smack_process_label
);
496 static int property_get_personality(
499 const char *interface
,
500 const char *property
,
501 sd_bus_message
*reply
,
503 sd_bus_error
*error
) {
505 ExecContext
*c
= userdata
;
511 return sd_bus_message_append(reply
, "s", personality_to_string(c
->personality
));
514 static int property_get_address_families(
517 const char *interface
,
518 const char *property
,
519 sd_bus_message
*reply
,
521 sd_bus_error
*error
) {
523 ExecContext
*c
= userdata
;
524 _cleanup_strv_free_
char **l
= NULL
;
533 r
= sd_bus_message_open_container(reply
, 'r', "bas");
537 r
= sd_bus_message_append(reply
, "b", c
->address_families_whitelist
);
541 SET_FOREACH(af
, c
->address_families
, i
) {
544 name
= af_to_name(PTR_TO_INT(af
));
548 r
= strv_extend(&l
, name
);
555 r
= sd_bus_message_append_strv(reply
, l
);
559 return sd_bus_message_close_container(reply
);
562 static int property_get_working_directory(
565 const char *interface
,
566 const char *property
,
567 sd_bus_message
*reply
,
569 sd_bus_error
*error
) {
571 ExecContext
*c
= userdata
;
578 if (c
->working_directory_home
)
581 wd
= c
->working_directory
;
583 if (c
->working_directory_missing_ok
)
584 wd
= strjoina("!", wd
);
586 return sd_bus_message_append(reply
, "s", wd
);
589 static int property_get_syslog_level(
592 const char *interface
,
593 const char *property
,
594 sd_bus_message
*reply
,
596 sd_bus_error
*error
) {
598 ExecContext
*c
= userdata
;
604 return sd_bus_message_append(reply
, "i", LOG_PRI(c
->syslog_priority
));
607 static int property_get_syslog_facility(
610 const char *interface
,
611 const char *property
,
612 sd_bus_message
*reply
,
614 sd_bus_error
*error
) {
616 ExecContext
*c
= userdata
;
622 return sd_bus_message_append(reply
, "i", LOG_FAC(c
->syslog_priority
));
625 const sd_bus_vtable bus_exec_vtable
[] = {
626 SD_BUS_VTABLE_START(0),
627 SD_BUS_PROPERTY("Environment", "as", NULL
, offsetof(ExecContext
, environment
), SD_BUS_VTABLE_PROPERTY_CONST
),
628 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
629 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode
, offsetof(ExecContext
, umask
), SD_BUS_VTABLE_PROPERTY_CONST
),
630 SD_BUS_PROPERTY("LimitCPU", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CPU
]), SD_BUS_VTABLE_PROPERTY_CONST
),
631 SD_BUS_PROPERTY("LimitFSIZE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_FSIZE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
632 SD_BUS_PROPERTY("LimitDATA", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_DATA
]), SD_BUS_VTABLE_PROPERTY_CONST
),
633 SD_BUS_PROPERTY("LimitSTACK", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_STACK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
634 SD_BUS_PROPERTY("LimitCORE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CORE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
635 SD_BUS_PROPERTY("LimitRSS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RSS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
636 SD_BUS_PROPERTY("LimitNOFILE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NOFILE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
637 SD_BUS_PROPERTY("LimitAS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_AS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
638 SD_BUS_PROPERTY("LimitNPROC", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NPROC
]), SD_BUS_VTABLE_PROPERTY_CONST
),
639 SD_BUS_PROPERTY("LimitMEMLOCK", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MEMLOCK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
640 SD_BUS_PROPERTY("LimitLOCKS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_LOCKS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
641 SD_BUS_PROPERTY("LimitSIGPENDING", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_SIGPENDING
]), SD_BUS_VTABLE_PROPERTY_CONST
),
642 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MSGQUEUE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
643 SD_BUS_PROPERTY("LimitNICE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NICE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
644 SD_BUS_PROPERTY("LimitRTPRIO", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTPRIO
]), SD_BUS_VTABLE_PROPERTY_CONST
),
645 SD_BUS_PROPERTY("LimitRTTIME", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTTIME
]), SD_BUS_VTABLE_PROPERTY_CONST
),
646 SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
647 SD_BUS_PROPERTY("RootDirectory", "s", NULL
, offsetof(ExecContext
, root_directory
), SD_BUS_VTABLE_PROPERTY_CONST
),
648 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
649 SD_BUS_PROPERTY("Nice", "i", property_get_nice
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
650 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
651 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
652 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
653 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
654 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
655 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool
, offsetof(ExecContext
, cpu_sched_reset_on_fork
), SD_BUS_VTABLE_PROPERTY_CONST
),
656 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool
, offsetof(ExecContext
, non_blocking
), SD_BUS_VTABLE_PROPERTY_CONST
),
657 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input
, offsetof(ExecContext
, std_input
), SD_BUS_VTABLE_PROPERTY_CONST
),
658 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output
, offsetof(ExecContext
, std_output
), SD_BUS_VTABLE_PROPERTY_CONST
),
659 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output
, offsetof(ExecContext
, std_error
), SD_BUS_VTABLE_PROPERTY_CONST
),
660 SD_BUS_PROPERTY("TTYPath", "s", NULL
, offsetof(ExecContext
, tty_path
), SD_BUS_VTABLE_PROPERTY_CONST
),
661 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_reset
), SD_BUS_VTABLE_PROPERTY_CONST
),
662 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_vhangup
), SD_BUS_VTABLE_PROPERTY_CONST
),
663 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_vt_disallocate
), SD_BUS_VTABLE_PROPERTY_CONST
),
664 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int
, offsetof(ExecContext
, syslog_priority
), SD_BUS_VTABLE_PROPERTY_CONST
),
665 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL
, offsetof(ExecContext
, syslog_identifier
), SD_BUS_VTABLE_PROPERTY_CONST
),
666 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool
, offsetof(ExecContext
, syslog_level_prefix
), SD_BUS_VTABLE_PROPERTY_CONST
),
667 SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
668 SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
669 SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
670 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int
, offsetof(ExecContext
, secure_bits
), SD_BUS_VTABLE_PROPERTY_CONST
),
671 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
672 SD_BUS_PROPERTY("User", "s", NULL
, offsetof(ExecContext
, user
), SD_BUS_VTABLE_PROPERTY_CONST
),
673 SD_BUS_PROPERTY("Group", "s", NULL
, offsetof(ExecContext
, group
), SD_BUS_VTABLE_PROPERTY_CONST
),
674 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL
, offsetof(ExecContext
, supplementary_groups
), SD_BUS_VTABLE_PROPERTY_CONST
),
675 SD_BUS_PROPERTY("PAMName", "s", NULL
, offsetof(ExecContext
, pam_name
), SD_BUS_VTABLE_PROPERTY_CONST
),
676 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL
, offsetof(ExecContext
, read_write_dirs
), SD_BUS_VTABLE_PROPERTY_CONST
),
677 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL
, offsetof(ExecContext
, read_only_dirs
), SD_BUS_VTABLE_PROPERTY_CONST
),
678 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL
, offsetof(ExecContext
, inaccessible_dirs
), SD_BUS_VTABLE_PROPERTY_CONST
),
679 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong
, offsetof(ExecContext
, mount_flags
), SD_BUS_VTABLE_PROPERTY_CONST
),
680 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool
, offsetof(ExecContext
, private_tmp
), SD_BUS_VTABLE_PROPERTY_CONST
),
681 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool
, offsetof(ExecContext
, private_network
), SD_BUS_VTABLE_PROPERTY_CONST
),
682 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool
, offsetof(ExecContext
, private_devices
), SD_BUS_VTABLE_PROPERTY_CONST
),
683 SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home
, offsetof(ExecContext
, protect_home
), SD_BUS_VTABLE_PROPERTY_CONST
),
684 SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system
, offsetof(ExecContext
, protect_system
), SD_BUS_VTABLE_PROPERTY_CONST
),
685 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool
, offsetof(ExecContext
, same_pgrp
), SD_BUS_VTABLE_PROPERTY_CONST
),
686 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL
, offsetof(ExecContext
, utmp_id
), SD_BUS_VTABLE_PROPERTY_CONST
),
687 SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode
, offsetof(ExecContext
, utmp_mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
688 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
689 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
690 SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
691 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool
, offsetof(ExecContext
, ignore_sigpipe
), SD_BUS_VTABLE_PROPERTY_CONST
),
692 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool
, offsetof(ExecContext
, no_new_privileges
), SD_BUS_VTABLE_PROPERTY_CONST
),
693 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
694 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
695 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
696 SD_BUS_PROPERTY("Personality", "s", property_get_personality
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
697 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
698 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode
, offsetof(ExecContext
, runtime_directory_mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
699 SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL
, offsetof(ExecContext
, runtime_directory
), SD_BUS_VTABLE_PROPERTY_CONST
),
703 static int append_exec_command(sd_bus_message
*reply
, ExecCommand
*c
) {
712 r
= sd_bus_message_open_container(reply
, 'r', "sasbttttuii");
716 r
= sd_bus_message_append(reply
, "s", c
->path
);
720 r
= sd_bus_message_append_strv(reply
, c
->argv
);
724 r
= sd_bus_message_append(reply
, "bttttuii",
726 c
->exec_status
.start_timestamp
.realtime
,
727 c
->exec_status
.start_timestamp
.monotonic
,
728 c
->exec_status
.exit_timestamp
.realtime
,
729 c
->exec_status
.exit_timestamp
.monotonic
,
730 (uint32_t) c
->exec_status
.pid
,
731 (int32_t) c
->exec_status
.code
,
732 (int32_t) c
->exec_status
.status
);
736 return sd_bus_message_close_container(reply
);
739 int bus_property_get_exec_command(
742 const char *interface
,
743 const char *property
,
744 sd_bus_message
*reply
,
746 sd_bus_error
*ret_error
) {
748 ExecCommand
*c
= (ExecCommand
*) userdata
;
754 r
= sd_bus_message_open_container(reply
, 'a', "(sasbttttuii)");
758 r
= append_exec_command(reply
, c
);
762 return sd_bus_message_close_container(reply
);
765 int bus_property_get_exec_command_list(
768 const char *interface
,
769 const char *property
,
770 sd_bus_message
*reply
,
772 sd_bus_error
*ret_error
) {
774 ExecCommand
*c
= *(ExecCommand
**) userdata
;
780 r
= sd_bus_message_open_container(reply
, 'a', "(sasbttttuii)");
784 LIST_FOREACH(command
, c
, c
) {
785 r
= append_exec_command(reply
, c
);
790 return sd_bus_message_close_container(reply
);
793 int bus_exec_context_set_transient_property(
797 sd_bus_message
*message
,
798 UnitSetPropertiesMode mode
,
799 sd_bus_error
*error
) {
808 if (streq(name
, "User")) {
811 r
= sd_bus_message_read(message
, "s", &uu
);
815 if (mode
!= UNIT_CHECK
) {
818 c
->user
= mfree(c
->user
);
830 unit_write_drop_in_private_format(u
, mode
, name
, "User=%s\n", uu
);
835 } else if (streq(name
, "Group")) {
838 r
= sd_bus_message_read(message
, "s", &gg
);
842 if (mode
!= UNIT_CHECK
) {
845 c
->group
= mfree(c
->group
);
857 unit_write_drop_in_private_format(u
, mode
, name
, "Group=%s\n", gg
);
861 } else if (streq(name
, "SyslogIdentifier")) {
864 r
= sd_bus_message_read(message
, "s", &id
);
868 if (mode
!= UNIT_CHECK
) {
871 c
->syslog_identifier
= mfree(c
->syslog_identifier
);
879 free(c
->syslog_identifier
);
880 c
->syslog_identifier
= t
;
883 unit_write_drop_in_private_format(u
, mode
, name
, "SyslogIdentifier=%s\n", id
);
887 } else if (streq(name
, "SyslogLevel")) {
890 r
= sd_bus_message_read(message
, "i", &level
);
894 if (!log_level_is_valid(level
))
895 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Log level value out of range");
897 if (mode
!= UNIT_CHECK
) {
898 c
->syslog_priority
= (c
->syslog_priority
& LOG_FACMASK
) | level
;
899 unit_write_drop_in_private_format(u
, mode
, name
, "SyslogLevel=%i\n", level
);
903 } else if (streq(name
, "SyslogFacility")) {
906 r
= sd_bus_message_read(message
, "i", &facility
);
910 if (!log_facility_unshifted_is_valid(facility
))
911 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Log facility value out of range");
913 if (mode
!= UNIT_CHECK
) {
914 c
->syslog_priority
= (facility
<< 3) | LOG_PRI(c
->syslog_priority
);
915 unit_write_drop_in_private_format(u
, mode
, name
, "SyslogFacility=%i\n", facility
);
919 } else if (streq(name
, "Nice")) {
922 r
= sd_bus_message_read(message
, "i", &n
);
926 if (n
< PRIO_MIN
|| n
>= PRIO_MAX
)
927 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Nice value out of range");
929 if (mode
!= UNIT_CHECK
) {
931 unit_write_drop_in_private_format(u
, mode
, name
, "Nice=%i\n", n
);
936 } else if (STR_IN_SET(name
, "TTYPath", "RootDirectory")) {
939 r
= sd_bus_message_read(message
, "s", &s
);
943 if (!path_is_absolute(s
))
944 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s takes an absolute path", name
);
946 if (mode
!= UNIT_CHECK
) {
947 if (streq(name
, "TTYPath"))
948 r
= free_and_strdup(&c
->tty_path
, s
);
950 assert(streq(name
, "RootDirectory"));
951 r
= free_and_strdup(&c
->root_directory
, s
);
956 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, s
);
961 } else if (streq(name
, "WorkingDirectory")) {
965 r
= sd_bus_message_read(message
, "s", &s
);
975 if (!streq(s
, "~") && !path_is_absolute(s
))
976 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "WorkingDirectory= expects an absolute path or '~'");
978 if (mode
!= UNIT_CHECK
) {
980 c
->working_directory
= mfree(c
->working_directory
);
981 c
->working_directory_home
= true;
983 r
= free_and_strdup(&c
->working_directory
, s
);
987 c
->working_directory_home
= false;
990 c
->working_directory_missing_ok
= missing_ok
;
991 unit_write_drop_in_private_format(u
, mode
, name
, "WorkingDirectory=%s%s", missing_ok
? "-" : "", s
);
996 } else if (streq(name
, "StandardInput")) {
1000 r
= sd_bus_message_read(message
, "s", &s
);
1004 p
= exec_input_from_string(s
);
1006 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard input name");
1008 if (mode
!= UNIT_CHECK
) {
1011 unit_write_drop_in_private_format(u
, mode
, name
, "StandardInput=%s\n", exec_input_to_string(p
));
1017 } else if (streq(name
, "StandardOutput")) {
1021 r
= sd_bus_message_read(message
, "s", &s
);
1025 p
= exec_output_from_string(s
);
1027 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard output name");
1029 if (mode
!= UNIT_CHECK
) {
1032 unit_write_drop_in_private_format(u
, mode
, name
, "StandardOutput=%s\n", exec_output_to_string(p
));
1037 } else if (streq(name
, "StandardError")) {
1041 r
= sd_bus_message_read(message
, "s", &s
);
1045 p
= exec_output_from_string(s
);
1047 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard error name");
1049 if (mode
!= UNIT_CHECK
) {
1052 unit_write_drop_in_private_format(u
, mode
, name
, "StandardError=%s\n", exec_output_to_string(p
));
1057 } else if (STR_IN_SET(name
,
1058 "IgnoreSIGPIPE", "TTYVHangup", "TTYReset",
1059 "PrivateTmp", "PrivateDevices", "PrivateNetwork",
1060 "NoNewPrivileges", "SyslogLevelPrefix")) {
1063 r
= sd_bus_message_read(message
, "b", &b
);
1067 if (mode
!= UNIT_CHECK
) {
1068 if (streq(name
, "IgnoreSIGPIPE"))
1069 c
->ignore_sigpipe
= b
;
1070 else if (streq(name
, "TTYVHangup"))
1072 else if (streq(name
, "TTYReset"))
1074 else if (streq(name
, "PrivateTmp"))
1076 else if (streq(name
, "PrivateDevices"))
1077 c
->private_devices
= b
;
1078 else if (streq(name
, "PrivateNetwork"))
1079 c
->private_network
= b
;
1080 else if (streq(name
, "NoNewPrivileges"))
1081 c
->no_new_privileges
= b
;
1082 else if (streq(name
, "SyslogLevelPrefix"))
1083 c
->syslog_level_prefix
= b
;
1085 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, yes_no(b
));
1090 } else if (streq(name
, "UtmpIdentifier")) {
1093 r
= sd_bus_message_read(message
, "s", &id
);
1097 if (mode
!= UNIT_CHECK
) {
1099 c
->utmp_id
= mfree(c
->utmp_id
);
1100 else if (free_and_strdup(&c
->utmp_id
, id
) < 0)
1103 unit_write_drop_in_private_format(u
, mode
, name
, "UtmpIdentifier=%s\n", strempty(id
));
1108 } else if (streq(name
, "UtmpMode")) {
1112 r
= sd_bus_message_read(message
, "s", &s
);
1116 m
= exec_utmp_mode_from_string(s
);
1118 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid utmp mode");
1120 if (mode
!= UNIT_CHECK
) {
1123 unit_write_drop_in_private_format(u
, mode
, name
, "UtmpMode=%s\n", exec_utmp_mode_to_string(m
));
1128 } else if (streq(name
, "PAMName")) {
1131 r
= sd_bus_message_read(message
, "s", &n
);
1135 if (mode
!= UNIT_CHECK
) {
1137 c
->pam_name
= mfree(c
->pam_name
);
1138 else if (free_and_strdup(&c
->pam_name
, n
) < 0)
1141 unit_write_drop_in_private_format(u
, mode
, name
, "PAMName=%s\n", strempty(n
));
1146 } else if (streq(name
, "Environment")) {
1148 _cleanup_strv_free_
char **l
= NULL
;
1150 r
= sd_bus_message_read_strv(message
, &l
);
1154 if (!strv_env_is_valid(l
))
1155 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid environment block.");
1157 if (mode
!= UNIT_CHECK
) {
1158 _cleanup_free_
char *joined
= NULL
;
1161 if (strv_length(l
) == 0) {
1162 c
->environment
= strv_free(c
->environment
);
1163 unit_write_drop_in_private_format(u
, mode
, name
, "Environment=\n");
1165 e
= strv_env_merge(2, c
->environment
, l
);
1169 strv_free(c
->environment
);
1172 joined
= strv_join_quoted(c
->environment
);
1176 unit_write_drop_in_private_format(u
, mode
, name
, "Environment=%s\n", joined
);
1182 } else if (streq(name
, "TimerSlackNSec")) {
1186 r
= sd_bus_message_read(message
, "t", &n
);
1190 if (mode
!= UNIT_CHECK
) {
1191 c
->timer_slack_nsec
= n
;
1192 unit_write_drop_in_private_format(u
, mode
, name
, "TimerSlackNSec=" NSEC_FMT
"\n", n
);
1197 } else if (streq(name
, "OOMScoreAdjust")) {
1200 r
= sd_bus_message_read(message
, "i", &oa
);
1204 if (!oom_score_adjust_is_valid(oa
))
1205 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "OOM score adjust value out of range");
1207 if (mode
!= UNIT_CHECK
) {
1208 c
->oom_score_adjust
= oa
;
1209 c
->oom_score_adjust_set
= true;
1210 unit_write_drop_in_private_format(u
, mode
, name
, "OOMScoreAdjust=%i\n", oa
);
1215 } else if (streq(name
, "EnvironmentFiles")) {
1217 _cleanup_free_
char *joined
= NULL
;
1218 _cleanup_fclose_
FILE *f
= NULL
;
1219 _cleanup_free_
char **l
= NULL
;
1223 r
= sd_bus_message_enter_container(message
, 'a', "(sb)");
1227 f
= open_memstream(&joined
, &size
);
1231 STRV_FOREACH(i
, c
->environment_files
)
1232 fprintf(f
, "EnvironmentFile=%s\n", *i
);
1234 while ((r
= sd_bus_message_enter_container(message
, 'r', "sb")) > 0) {
1238 r
= sd_bus_message_read(message
, "sb", &path
, &b
);
1242 r
= sd_bus_message_exit_container(message
);
1246 if (!isempty(path
) && !path_is_absolute(path
))
1247 return sd_bus_error_set_errnof(error
, EINVAL
, "Path %s is not absolute.", path
);
1249 if (mode
!= UNIT_CHECK
) {
1252 buf
= strjoin(b
? "-" : "", path
, NULL
);
1256 fprintf(f
, "EnvironmentFile=%s\n", buf
);
1258 r
= strv_consume(&l
, buf
);
1266 r
= sd_bus_message_exit_container(message
);
1270 r
= fflush_and_check(f
);
1274 if (mode
!= UNIT_CHECK
) {
1275 if (strv_isempty(l
)) {
1276 c
->environment_files
= strv_free(c
->environment_files
);
1277 unit_write_drop_in_private(u
, mode
, name
, "EnvironmentFile=\n");
1279 r
= strv_extend_strv(&c
->environment_files
, l
, true);
1283 unit_write_drop_in_private(u
, mode
, name
, joined
);
1289 } else if (STR_IN_SET(name
, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories")) {
1291 _cleanup_strv_free_
char **l
= NULL
;
1295 r
= sd_bus_message_read_strv(message
, &l
);
1299 STRV_FOREACH(p
, l
) {
1301 if (!utf8_is_valid(*p
))
1302 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid %s", name
);
1304 offset
= **p
== '-';
1305 if (!path_is_absolute(*p
+ offset
))
1306 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid %s", name
);
1309 if (mode
!= UNIT_CHECK
) {
1310 _cleanup_free_
char *joined
= NULL
;
1312 if (streq(name
, "ReadWriteDirectories"))
1313 dirs
= &c
->read_write_dirs
;
1314 else if (streq(name
, "ReadOnlyDirectories"))
1315 dirs
= &c
->read_only_dirs
;
1316 else if (streq(name
, "InaccessibleDirectories"))
1317 dirs
= &c
->inaccessible_dirs
;
1319 if (strv_length(l
) == 0) {
1320 *dirs
= strv_free(*dirs
);
1321 unit_write_drop_in_private_format(u
, mode
, name
, "%s=\n", name
);
1323 r
= strv_extend_strv(dirs
, l
, true);
1328 joined
= strv_join_quoted(*dirs
);
1332 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, joined
);
1339 } else if (streq(name
, "ProtectSystem")) {
1343 r
= sd_bus_message_read(message
, "s", &s
);
1347 r
= parse_boolean(s
);
1349 ps
= PROTECT_SYSTEM_YES
;
1351 ps
= PROTECT_SYSTEM_NO
;
1353 ps
= protect_system_from_string(s
);
1355 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Failed to parse protect system value");
1358 if (mode
!= UNIT_CHECK
) {
1359 c
->protect_system
= ps
;
1360 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, s
);
1365 } else if (streq(name
, "ProtectHome")) {
1369 r
= sd_bus_message_read(message
, "s", &s
);
1373 r
= parse_boolean(s
);
1375 ph
= PROTECT_HOME_YES
;
1377 ph
= PROTECT_HOME_NO
;
1379 ph
= protect_home_from_string(s
);
1381 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Failed to parse protect home value");
1384 if (mode
!= UNIT_CHECK
) {
1385 c
->protect_home
= ph
;
1386 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, s
);
1391 } else if (rlimit_from_string(name
) >= 0) {
1395 r
= sd_bus_message_read(message
, "t", &rl
);
1399 if (rl
== (uint64_t) -1)
1404 if ((uint64_t) x
!= rl
)
1408 if (mode
!= UNIT_CHECK
) {
1411 z
= rlimit_from_string(name
);
1413 if (!c
->rlimit
[z
]) {
1414 c
->rlimit
[z
] = new(struct rlimit
, 1);
1419 c
->rlimit
[z
]->rlim_cur
= c
->rlimit
[z
]->rlim_max
= x
;
1421 if (x
== RLIM_INFINITY
)
1422 unit_write_drop_in_private_format(u
, mode
, name
, "%s=infinity\n", name
);
1424 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%" PRIu64
"\n", name
, rl
);