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.h"
31 #include "dbus-execute.h"
38 #include "namespace.h"
39 #include "path-util.h"
44 #include "seccomp-util.h"
47 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output
, exec_output
, ExecOutput
);
49 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input
, exec_input
, ExecInput
);
51 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_utmp_mode
, exec_utmp_mode
, ExecUtmpMode
);
53 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_home
, protect_home
, ProtectHome
);
54 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_system
, protect_system
, ProtectSystem
);
56 static int property_get_environment_files(
59 const char *interface
,
61 sd_bus_message
*reply
,
63 sd_bus_error
*error
) {
65 ExecContext
*c
= userdata
;
73 r
= sd_bus_message_open_container(reply
, 'a', "(sb)");
77 STRV_FOREACH(j
, c
->environment_files
) {
80 r
= sd_bus_message_append(reply
, "(sb)", fn
[0] == '-' ? fn
+ 1 : fn
, fn
[0] == '-');
85 return sd_bus_message_close_container(reply
);
88 static int property_get_oom_score_adjust(
91 const char *interface
,
93 sd_bus_message
*reply
,
95 sd_bus_error
*error
) {
98 ExecContext
*c
= userdata
;
105 if (c
->oom_score_adjust_set
)
106 n
= c
->oom_score_adjust
;
108 _cleanup_free_
char *t
= NULL
;
111 if (read_one_line_file("/proc/self/oom_score_adj", &t
) >= 0)
115 return sd_bus_message_append(reply
, "i", n
);
118 static int property_get_nice(
121 const char *interface
,
122 const char *property
,
123 sd_bus_message
*reply
,
125 sd_bus_error
*error
) {
128 ExecContext
*c
= userdata
;
139 n
= getpriority(PRIO_PROCESS
, 0);
144 return sd_bus_message_append(reply
, "i", n
);
147 static int property_get_ioprio(
150 const char *interface
,
151 const char *property
,
152 sd_bus_message
*reply
,
154 sd_bus_error
*error
) {
157 ExecContext
*c
= userdata
;
167 n
= ioprio_get(IOPRIO_WHO_PROCESS
, 0);
169 n
= IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE
, 4);
172 return sd_bus_message_append(reply
, "i", n
);
175 static int property_get_cpu_sched_policy(
178 const char *interface
,
179 const char *property
,
180 sd_bus_message
*reply
,
182 sd_bus_error
*error
) {
184 ExecContext
*c
= userdata
;
191 if (c
->cpu_sched_set
)
192 n
= c
->cpu_sched_policy
;
194 n
= sched_getscheduler(0);
199 return sd_bus_message_append(reply
, "i", n
);
202 static int property_get_cpu_sched_priority(
205 const char *interface
,
206 const char *property
,
207 sd_bus_message
*reply
,
209 sd_bus_error
*error
) {
211 ExecContext
*c
= userdata
;
218 if (c
->cpu_sched_set
)
219 n
= c
->cpu_sched_priority
;
221 struct sched_param p
= {};
223 if (sched_getparam(0, &p
) >= 0)
224 n
= p
.sched_priority
;
229 return sd_bus_message_append(reply
, "i", n
);
232 static int property_get_cpu_affinity(
235 const char *interface
,
236 const char *property
,
237 sd_bus_message
*reply
,
239 sd_bus_error
*error
) {
241 ExecContext
*c
= userdata
;
248 return sd_bus_message_append_array(reply
, 'y', c
->cpuset
, CPU_ALLOC_SIZE(c
->cpuset_ncpus
));
250 return sd_bus_message_append_array(reply
, 'y', NULL
, 0);
253 static int property_get_timer_slack_nsec(
256 const char *interface
,
257 const char *property
,
258 sd_bus_message
*reply
,
260 sd_bus_error
*error
) {
262 ExecContext
*c
= userdata
;
269 if (c
->timer_slack_nsec
!= NSEC_INFINITY
)
270 u
= (uint64_t) c
->timer_slack_nsec
;
272 u
= (uint64_t) prctl(PR_GET_TIMERSLACK
);
274 return sd_bus_message_append(reply
, "t", u
);
277 static int property_get_capability_bounding_set(
280 const char *interface
,
281 const char *property
,
282 sd_bus_message
*reply
,
284 sd_bus_error
*error
) {
286 ExecContext
*c
= userdata
;
292 /* We store this negated internally, to match the kernel, but
293 * we expose it normalized. */
294 return sd_bus_message_append(reply
, "t", ~c
->capability_bounding_set_drop
);
297 static int property_get_capabilities(
300 const char *interface
,
301 const char *property
,
302 sd_bus_message
*reply
,
304 sd_bus_error
*error
) {
306 ExecContext
*c
= userdata
;
307 _cleanup_cap_free_charp_
char *t
= NULL
;
315 s
= t
= cap_to_text(c
->capabilities
, NULL
);
322 return sd_bus_message_append(reply
, "s", s
);
325 static int property_get_syscall_filter(
328 const char *interface
,
329 const char *property
,
330 sd_bus_message
*reply
,
332 sd_bus_error
*error
) {
334 ExecContext
*c
= userdata
;
335 _cleanup_strv_free_
char **l
= NULL
;
347 r
= sd_bus_message_open_container(reply
, 'r', "bas");
351 r
= sd_bus_message_append(reply
, "b", c
->syscall_whitelist
);
356 SET_FOREACH(id
, c
->syscall_filter
, i
) {
359 name
= seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE
, PTR_TO_INT(id
) - 1);
363 r
= strv_consume(&l
, name
);
371 r
= sd_bus_message_append_strv(reply
, l
);
375 return sd_bus_message_close_container(reply
);
378 static int property_get_syscall_archs(
381 const char *interface
,
382 const char *property
,
383 sd_bus_message
*reply
,
385 sd_bus_error
*error
) {
387 ExecContext
*c
= userdata
;
388 _cleanup_strv_free_
char **l
= NULL
;
401 SET_FOREACH(id
, c
->syscall_archs
, i
) {
404 name
= seccomp_arch_to_string(PTR_TO_UINT32(id
) - 1);
408 r
= strv_extend(&l
, name
);
416 r
= sd_bus_message_append_strv(reply
, l
);
423 static int property_get_syscall_errno(
426 const char *interface
,
427 const char *property
,
428 sd_bus_message
*reply
,
430 sd_bus_error
*error
) {
432 ExecContext
*c
= userdata
;
438 return sd_bus_message_append(reply
, "i", (int32_t) c
->syscall_errno
);
441 static int property_get_selinux_context(
444 const char *interface
,
445 const char *property
,
446 sd_bus_message
*reply
,
448 sd_bus_error
*error
) {
450 ExecContext
*c
= userdata
;
456 return sd_bus_message_append(reply
, "(bs)", c
->selinux_context_ignore
, c
->selinux_context
);
459 static int property_get_apparmor_profile(
462 const char *interface
,
463 const char *property
,
464 sd_bus_message
*reply
,
466 sd_bus_error
*error
) {
468 ExecContext
*c
= userdata
;
474 return sd_bus_message_append(reply
, "(bs)", c
->apparmor_profile_ignore
, c
->apparmor_profile
);
477 static int property_get_smack_process_label(
480 const char *interface
,
481 const char *property
,
482 sd_bus_message
*reply
,
484 sd_bus_error
*error
) {
486 ExecContext
*c
= userdata
;
492 return sd_bus_message_append(reply
, "(bs)", c
->smack_process_label_ignore
, c
->smack_process_label
);
495 static int property_get_personality(
498 const char *interface
,
499 const char *property
,
500 sd_bus_message
*reply
,
502 sd_bus_error
*error
) {
504 ExecContext
*c
= userdata
;
510 return sd_bus_message_append(reply
, "s", personality_to_string(c
->personality
));
513 static int property_get_address_families(
516 const char *interface
,
517 const char *property
,
518 sd_bus_message
*reply
,
520 sd_bus_error
*error
) {
522 ExecContext
*c
= userdata
;
523 _cleanup_strv_free_
char **l
= NULL
;
532 r
= sd_bus_message_open_container(reply
, 'r', "bas");
536 r
= sd_bus_message_append(reply
, "b", c
->address_families_whitelist
);
540 SET_FOREACH(af
, c
->address_families
, i
) {
543 name
= af_to_name(PTR_TO_INT(af
));
547 r
= strv_extend(&l
, name
);
554 r
= sd_bus_message_append_strv(reply
, l
);
558 return sd_bus_message_close_container(reply
);
561 static int property_get_working_directory(
564 const char *interface
,
565 const char *property
,
566 sd_bus_message
*reply
,
568 sd_bus_error
*error
) {
570 ExecContext
*c
= userdata
;
577 if (c
->working_directory_home
)
580 wd
= c
->working_directory
;
582 if (c
->working_directory_missing_ok
)
583 wd
= strjoina("!", wd
);
585 return sd_bus_message_append(reply
, "s", wd
);
588 static int property_get_syslog_level(
591 const char *interface
,
592 const char *property
,
593 sd_bus_message
*reply
,
595 sd_bus_error
*error
) {
597 ExecContext
*c
= userdata
;
603 return sd_bus_message_append(reply
, "i", LOG_PRI(c
->syslog_priority
));
606 static int property_get_syslog_facility(
609 const char *interface
,
610 const char *property
,
611 sd_bus_message
*reply
,
613 sd_bus_error
*error
) {
615 ExecContext
*c
= userdata
;
621 return sd_bus_message_append(reply
, "i", LOG_FAC(c
->syslog_priority
));
624 const sd_bus_vtable bus_exec_vtable
[] = {
625 SD_BUS_VTABLE_START(0),
626 SD_BUS_PROPERTY("Environment", "as", NULL
, offsetof(ExecContext
, environment
), SD_BUS_VTABLE_PROPERTY_CONST
),
627 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
628 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode
, offsetof(ExecContext
, umask
), SD_BUS_VTABLE_PROPERTY_CONST
),
629 SD_BUS_PROPERTY("LimitCPU", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CPU
]), SD_BUS_VTABLE_PROPERTY_CONST
),
630 SD_BUS_PROPERTY("LimitFSIZE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_FSIZE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
631 SD_BUS_PROPERTY("LimitDATA", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_DATA
]), SD_BUS_VTABLE_PROPERTY_CONST
),
632 SD_BUS_PROPERTY("LimitSTACK", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_STACK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
633 SD_BUS_PROPERTY("LimitCORE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CORE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
634 SD_BUS_PROPERTY("LimitRSS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RSS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
635 SD_BUS_PROPERTY("LimitNOFILE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NOFILE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
636 SD_BUS_PROPERTY("LimitAS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_AS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
637 SD_BUS_PROPERTY("LimitNPROC", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NPROC
]), SD_BUS_VTABLE_PROPERTY_CONST
),
638 SD_BUS_PROPERTY("LimitMEMLOCK", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MEMLOCK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
639 SD_BUS_PROPERTY("LimitLOCKS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_LOCKS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
640 SD_BUS_PROPERTY("LimitSIGPENDING", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_SIGPENDING
]), SD_BUS_VTABLE_PROPERTY_CONST
),
641 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MSGQUEUE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
642 SD_BUS_PROPERTY("LimitNICE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NICE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
643 SD_BUS_PROPERTY("LimitRTPRIO", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTPRIO
]), SD_BUS_VTABLE_PROPERTY_CONST
),
644 SD_BUS_PROPERTY("LimitRTTIME", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTTIME
]), SD_BUS_VTABLE_PROPERTY_CONST
),
645 SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
646 SD_BUS_PROPERTY("RootDirectory", "s", NULL
, offsetof(ExecContext
, root_directory
), SD_BUS_VTABLE_PROPERTY_CONST
),
647 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
648 SD_BUS_PROPERTY("Nice", "i", property_get_nice
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
649 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
650 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
651 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
652 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
653 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
654 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool
, offsetof(ExecContext
, cpu_sched_reset_on_fork
), SD_BUS_VTABLE_PROPERTY_CONST
),
655 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool
, offsetof(ExecContext
, non_blocking
), SD_BUS_VTABLE_PROPERTY_CONST
),
656 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input
, offsetof(ExecContext
, std_input
), SD_BUS_VTABLE_PROPERTY_CONST
),
657 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output
, offsetof(ExecContext
, std_output
), SD_BUS_VTABLE_PROPERTY_CONST
),
658 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output
, offsetof(ExecContext
, std_error
), SD_BUS_VTABLE_PROPERTY_CONST
),
659 SD_BUS_PROPERTY("TTYPath", "s", NULL
, offsetof(ExecContext
, tty_path
), SD_BUS_VTABLE_PROPERTY_CONST
),
660 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_reset
), SD_BUS_VTABLE_PROPERTY_CONST
),
661 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_vhangup
), SD_BUS_VTABLE_PROPERTY_CONST
),
662 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_vt_disallocate
), SD_BUS_VTABLE_PROPERTY_CONST
),
663 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int
, offsetof(ExecContext
, syslog_priority
), SD_BUS_VTABLE_PROPERTY_CONST
),
664 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL
, offsetof(ExecContext
, syslog_identifier
), SD_BUS_VTABLE_PROPERTY_CONST
),
665 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool
, offsetof(ExecContext
, syslog_level_prefix
), SD_BUS_VTABLE_PROPERTY_CONST
),
666 SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
667 SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
668 SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
669 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int
, offsetof(ExecContext
, secure_bits
), SD_BUS_VTABLE_PROPERTY_CONST
),
670 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
671 SD_BUS_PROPERTY("User", "s", NULL
, offsetof(ExecContext
, user
), SD_BUS_VTABLE_PROPERTY_CONST
),
672 SD_BUS_PROPERTY("Group", "s", NULL
, offsetof(ExecContext
, group
), SD_BUS_VTABLE_PROPERTY_CONST
),
673 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL
, offsetof(ExecContext
, supplementary_groups
), SD_BUS_VTABLE_PROPERTY_CONST
),
674 SD_BUS_PROPERTY("PAMName", "s", NULL
, offsetof(ExecContext
, pam_name
), SD_BUS_VTABLE_PROPERTY_CONST
),
675 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL
, offsetof(ExecContext
, read_write_dirs
), SD_BUS_VTABLE_PROPERTY_CONST
),
676 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL
, offsetof(ExecContext
, read_only_dirs
), SD_BUS_VTABLE_PROPERTY_CONST
),
677 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL
, offsetof(ExecContext
, inaccessible_dirs
), SD_BUS_VTABLE_PROPERTY_CONST
),
678 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong
, offsetof(ExecContext
, mount_flags
), SD_BUS_VTABLE_PROPERTY_CONST
),
679 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool
, offsetof(ExecContext
, private_tmp
), SD_BUS_VTABLE_PROPERTY_CONST
),
680 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool
, offsetof(ExecContext
, private_network
), SD_BUS_VTABLE_PROPERTY_CONST
),
681 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool
, offsetof(ExecContext
, private_devices
), SD_BUS_VTABLE_PROPERTY_CONST
),
682 SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home
, offsetof(ExecContext
, protect_home
), SD_BUS_VTABLE_PROPERTY_CONST
),
683 SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system
, offsetof(ExecContext
, protect_system
), SD_BUS_VTABLE_PROPERTY_CONST
),
684 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool
, offsetof(ExecContext
, same_pgrp
), SD_BUS_VTABLE_PROPERTY_CONST
),
685 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL
, offsetof(ExecContext
, utmp_id
), SD_BUS_VTABLE_PROPERTY_CONST
),
686 SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode
, offsetof(ExecContext
, utmp_mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
687 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
688 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
689 SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
690 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool
, offsetof(ExecContext
, ignore_sigpipe
), SD_BUS_VTABLE_PROPERTY_CONST
),
691 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool
, offsetof(ExecContext
, no_new_privileges
), SD_BUS_VTABLE_PROPERTY_CONST
),
692 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
693 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
694 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
695 SD_BUS_PROPERTY("Personality", "s", property_get_personality
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
696 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
697 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode
, offsetof(ExecContext
, runtime_directory_mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
698 SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL
, offsetof(ExecContext
, runtime_directory
), SD_BUS_VTABLE_PROPERTY_CONST
),
702 static int append_exec_command(sd_bus_message
*reply
, ExecCommand
*c
) {
711 r
= sd_bus_message_open_container(reply
, 'r', "sasbttttuii");
715 r
= sd_bus_message_append(reply
, "s", c
->path
);
719 r
= sd_bus_message_append_strv(reply
, c
->argv
);
723 r
= sd_bus_message_append(reply
, "bttttuii",
725 c
->exec_status
.start_timestamp
.realtime
,
726 c
->exec_status
.start_timestamp
.monotonic
,
727 c
->exec_status
.exit_timestamp
.realtime
,
728 c
->exec_status
.exit_timestamp
.monotonic
,
729 (uint32_t) c
->exec_status
.pid
,
730 (int32_t) c
->exec_status
.code
,
731 (int32_t) c
->exec_status
.status
);
735 return sd_bus_message_close_container(reply
);
738 int bus_property_get_exec_command(
741 const char *interface
,
742 const char *property
,
743 sd_bus_message
*reply
,
745 sd_bus_error
*ret_error
) {
747 ExecCommand
*c
= (ExecCommand
*) userdata
;
753 r
= sd_bus_message_open_container(reply
, 'a', "(sasbttttuii)");
757 r
= append_exec_command(reply
, c
);
761 return sd_bus_message_close_container(reply
);
764 int bus_property_get_exec_command_list(
767 const char *interface
,
768 const char *property
,
769 sd_bus_message
*reply
,
771 sd_bus_error
*ret_error
) {
773 ExecCommand
*c
= *(ExecCommand
**) userdata
;
779 r
= sd_bus_message_open_container(reply
, 'a', "(sasbttttuii)");
783 LIST_FOREACH(command
, c
, c
) {
784 r
= append_exec_command(reply
, c
);
789 return sd_bus_message_close_container(reply
);
792 int bus_exec_context_set_transient_property(
796 sd_bus_message
*message
,
797 UnitSetPropertiesMode mode
,
798 sd_bus_error
*error
) {
807 if (streq(name
, "User")) {
810 r
= sd_bus_message_read(message
, "s", &uu
);
814 if (mode
!= UNIT_CHECK
) {
817 c
->user
= mfree(c
->user
);
829 unit_write_drop_in_private_format(u
, mode
, name
, "User=%s\n", uu
);
834 } else if (streq(name
, "Group")) {
837 r
= sd_bus_message_read(message
, "s", &gg
);
841 if (mode
!= UNIT_CHECK
) {
844 c
->group
= mfree(c
->group
);
856 unit_write_drop_in_private_format(u
, mode
, name
, "Group=%s\n", gg
);
860 } else if (streq(name
, "SyslogIdentifier")) {
863 r
= sd_bus_message_read(message
, "s", &id
);
867 if (mode
!= UNIT_CHECK
) {
870 c
->syslog_identifier
= mfree(c
->syslog_identifier
);
878 free(c
->syslog_identifier
);
879 c
->syslog_identifier
= t
;
882 unit_write_drop_in_private_format(u
, mode
, name
, "SyslogIdentifier=%s\n", id
);
886 } else if (streq(name
, "SyslogLevel")) {
889 r
= sd_bus_message_read(message
, "i", &level
);
893 if (!log_level_is_valid(level
))
894 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Log level value out of range");
896 if (mode
!= UNIT_CHECK
) {
897 c
->syslog_priority
= (c
->syslog_priority
& LOG_FACMASK
) | level
;
898 unit_write_drop_in_private_format(u
, mode
, name
, "SyslogLevel=%i\n", level
);
902 } else if (streq(name
, "SyslogFacility")) {
905 r
= sd_bus_message_read(message
, "i", &facility
);
909 if (!log_facility_unshifted_is_valid(facility
))
910 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Log facility value out of range");
912 if (mode
!= UNIT_CHECK
) {
913 c
->syslog_priority
= (facility
<< 3) | LOG_PRI(c
->syslog_priority
);
914 unit_write_drop_in_private_format(u
, mode
, name
, "SyslogFacility=%i\n", facility
);
918 } else if (streq(name
, "Nice")) {
921 r
= sd_bus_message_read(message
, "i", &n
);
925 if (n
< PRIO_MIN
|| n
>= PRIO_MAX
)
926 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Nice value out of range");
928 if (mode
!= UNIT_CHECK
) {
930 unit_write_drop_in_private_format(u
, mode
, name
, "Nice=%i\n", n
);
935 } else if (STR_IN_SET(name
, "TTYPath", "RootDirectory")) {
938 r
= sd_bus_message_read(message
, "s", &s
);
942 if (!path_is_absolute(s
))
943 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s takes an absolute path", name
);
945 if (mode
!= UNIT_CHECK
) {
946 if (streq(name
, "TTYPath"))
947 r
= free_and_strdup(&c
->tty_path
, s
);
949 assert(streq(name
, "RootDirectory"));
950 r
= free_and_strdup(&c
->root_directory
, s
);
955 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, s
);
960 } else if (streq(name
, "WorkingDirectory")) {
964 r
= sd_bus_message_read(message
, "s", &s
);
974 if (!streq(s
, "~") && !path_is_absolute(s
))
975 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "WorkingDirectory= expects an absolute path or '~'");
977 if (mode
!= UNIT_CHECK
) {
979 c
->working_directory
= mfree(c
->working_directory
);
980 c
->working_directory_home
= true;
982 r
= free_and_strdup(&c
->working_directory
, s
);
986 c
->working_directory_home
= false;
989 c
->working_directory_missing_ok
= missing_ok
;
990 unit_write_drop_in_private_format(u
, mode
, name
, "WorkingDirectory=%s%s", missing_ok
? "-" : "", s
);
995 } else if (streq(name
, "StandardInput")) {
999 r
= sd_bus_message_read(message
, "s", &s
);
1003 p
= exec_input_from_string(s
);
1005 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard input name");
1007 if (mode
!= UNIT_CHECK
) {
1010 unit_write_drop_in_private_format(u
, mode
, name
, "StandardInput=%s\n", exec_input_to_string(p
));
1016 } else if (streq(name
, "StandardOutput")) {
1020 r
= sd_bus_message_read(message
, "s", &s
);
1024 p
= exec_output_from_string(s
);
1026 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard output name");
1028 if (mode
!= UNIT_CHECK
) {
1031 unit_write_drop_in_private_format(u
, mode
, name
, "StandardOutput=%s\n", exec_output_to_string(p
));
1036 } else if (streq(name
, "StandardError")) {
1040 r
= sd_bus_message_read(message
, "s", &s
);
1044 p
= exec_output_from_string(s
);
1046 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard error name");
1048 if (mode
!= UNIT_CHECK
) {
1051 unit_write_drop_in_private_format(u
, mode
, name
, "StandardError=%s\n", exec_output_to_string(p
));
1056 } else if (STR_IN_SET(name
,
1057 "IgnoreSIGPIPE", "TTYVHangup", "TTYReset",
1058 "PrivateTmp", "PrivateDevices", "PrivateNetwork",
1059 "NoNewPrivileges", "SyslogLevelPrefix")) {
1062 r
= sd_bus_message_read(message
, "b", &b
);
1066 if (mode
!= UNIT_CHECK
) {
1067 if (streq(name
, "IgnoreSIGPIPE"))
1068 c
->ignore_sigpipe
= b
;
1069 else if (streq(name
, "TTYVHangup"))
1071 else if (streq(name
, "TTYReset"))
1073 else if (streq(name
, "PrivateTmp"))
1075 else if (streq(name
, "PrivateDevices"))
1076 c
->private_devices
= b
;
1077 else if (streq(name
, "PrivateNetwork"))
1078 c
->private_network
= b
;
1079 else if (streq(name
, "NoNewPrivileges"))
1080 c
->no_new_privileges
= b
;
1081 else if (streq(name
, "SyslogLevelPrefix"))
1082 c
->syslog_level_prefix
= b
;
1084 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, yes_no(b
));
1089 } else if (streq(name
, "UtmpIdentifier")) {
1092 r
= sd_bus_message_read(message
, "s", &id
);
1096 if (mode
!= UNIT_CHECK
) {
1098 c
->utmp_id
= mfree(c
->utmp_id
);
1099 else if (free_and_strdup(&c
->utmp_id
, id
) < 0)
1102 unit_write_drop_in_private_format(u
, mode
, name
, "UtmpIdentifier=%s\n", strempty(id
));
1107 } else if (streq(name
, "UtmpMode")) {
1111 r
= sd_bus_message_read(message
, "s", &s
);
1115 m
= exec_utmp_mode_from_string(s
);
1117 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid utmp mode");
1119 if (mode
!= UNIT_CHECK
) {
1122 unit_write_drop_in_private_format(u
, mode
, name
, "UtmpMode=%s\n", exec_utmp_mode_to_string(m
));
1127 } else if (streq(name
, "PAMName")) {
1130 r
= sd_bus_message_read(message
, "s", &n
);
1134 if (mode
!= UNIT_CHECK
) {
1136 c
->pam_name
= mfree(c
->pam_name
);
1137 else if (free_and_strdup(&c
->pam_name
, n
) < 0)
1140 unit_write_drop_in_private_format(u
, mode
, name
, "PAMName=%s\n", strempty(n
));
1145 } else if (streq(name
, "Environment")) {
1147 _cleanup_strv_free_
char **l
= NULL
;
1149 r
= sd_bus_message_read_strv(message
, &l
);
1153 if (!strv_env_is_valid(l
))
1154 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid environment block.");
1156 if (mode
!= UNIT_CHECK
) {
1157 _cleanup_free_
char *joined
= NULL
;
1160 if (strv_length(l
) == 0) {
1161 c
->environment
= strv_free(c
->environment
);
1162 unit_write_drop_in_private_format(u
, mode
, name
, "Environment=\n");
1164 e
= strv_env_merge(2, c
->environment
, l
);
1168 strv_free(c
->environment
);
1171 joined
= strv_join_quoted(c
->environment
);
1175 unit_write_drop_in_private_format(u
, mode
, name
, "Environment=%s\n", joined
);
1181 } else if (streq(name
, "TimerSlackNSec")) {
1185 r
= sd_bus_message_read(message
, "t", &n
);
1189 if (mode
!= UNIT_CHECK
) {
1190 c
->timer_slack_nsec
= n
;
1191 unit_write_drop_in_private_format(u
, mode
, name
, "TimerSlackNSec=" NSEC_FMT
"\n", n
);
1196 } else if (streq(name
, "OOMScoreAdjust")) {
1199 r
= sd_bus_message_read(message
, "i", &oa
);
1203 if (!oom_score_adjust_is_valid(oa
))
1204 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "OOM score adjust value out of range");
1206 if (mode
!= UNIT_CHECK
) {
1207 c
->oom_score_adjust
= oa
;
1208 c
->oom_score_adjust_set
= true;
1209 unit_write_drop_in_private_format(u
, mode
, name
, "OOMScoreAdjust=%i\n", oa
);
1214 } else if (streq(name
, "EnvironmentFiles")) {
1216 _cleanup_free_
char *joined
= NULL
;
1217 _cleanup_fclose_
FILE *f
= NULL
;
1218 _cleanup_free_
char **l
= NULL
;
1222 r
= sd_bus_message_enter_container(message
, 'a', "(sb)");
1226 f
= open_memstream(&joined
, &size
);
1230 STRV_FOREACH(i
, c
->environment_files
)
1231 fprintf(f
, "EnvironmentFile=%s\n", *i
);
1233 while ((r
= sd_bus_message_enter_container(message
, 'r', "sb")) > 0) {
1237 r
= sd_bus_message_read(message
, "sb", &path
, &b
);
1241 r
= sd_bus_message_exit_container(message
);
1245 if (!isempty(path
) && !path_is_absolute(path
))
1246 return sd_bus_error_set_errnof(error
, EINVAL
, "Path %s is not absolute.", path
);
1248 if (mode
!= UNIT_CHECK
) {
1251 buf
= strjoin(b
? "-" : "", path
, NULL
);
1255 fprintf(f
, "EnvironmentFile=%s\n", buf
);
1257 r
= strv_consume(&l
, buf
);
1265 r
= sd_bus_message_exit_container(message
);
1269 r
= fflush_and_check(f
);
1273 if (mode
!= UNIT_CHECK
) {
1274 if (strv_isempty(l
)) {
1275 c
->environment_files
= strv_free(c
->environment_files
);
1276 unit_write_drop_in_private(u
, mode
, name
, "EnvironmentFile=\n");
1278 r
= strv_extend_strv(&c
->environment_files
, l
, true);
1282 unit_write_drop_in_private(u
, mode
, name
, joined
);
1288 } else if (STR_IN_SET(name
, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories")) {
1290 _cleanup_strv_free_
char **l
= NULL
;
1294 r
= sd_bus_message_read_strv(message
, &l
);
1298 STRV_FOREACH(p
, l
) {
1300 if (!utf8_is_valid(*p
))
1301 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid %s", name
);
1303 offset
= **p
== '-';
1304 if (!path_is_absolute(*p
+ offset
))
1305 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid %s", name
);
1308 if (mode
!= UNIT_CHECK
) {
1309 _cleanup_free_
char *joined
= NULL
;
1311 if (streq(name
, "ReadWriteDirectories"))
1312 dirs
= &c
->read_write_dirs
;
1313 else if (streq(name
, "ReadOnlyDirectories"))
1314 dirs
= &c
->read_only_dirs
;
1315 else if (streq(name
, "InaccessibleDirectories"))
1316 dirs
= &c
->inaccessible_dirs
;
1318 if (strv_length(l
) == 0) {
1319 *dirs
= strv_free(*dirs
);
1320 unit_write_drop_in_private_format(u
, mode
, name
, "%s=\n", name
);
1322 r
= strv_extend_strv(dirs
, l
, true);
1327 joined
= strv_join_quoted(*dirs
);
1331 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, joined
);
1338 } else if (streq(name
, "ProtectSystem")) {
1342 r
= sd_bus_message_read(message
, "s", &s
);
1346 r
= parse_boolean(s
);
1348 ps
= PROTECT_SYSTEM_YES
;
1350 ps
= PROTECT_SYSTEM_NO
;
1352 ps
= protect_system_from_string(s
);
1354 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Failed to parse protect system value");
1357 if (mode
!= UNIT_CHECK
) {
1358 c
->protect_system
= ps
;
1359 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, s
);
1364 } else if (rlimit_from_string(name
) >= 0) {
1368 r
= sd_bus_message_read(message
, "t", &rl
);
1372 if (rl
== (uint64_t) -1)
1377 if ((uint64_t) x
!= rl
)
1381 if (mode
!= UNIT_CHECK
) {
1384 z
= rlimit_from_string(name
);
1386 if (!c
->rlimit
[z
]) {
1387 c
->rlimit
[z
] = new(struct rlimit
, 1);
1392 c
->rlimit
[z
]->rlim_cur
= c
->rlimit
[z
]->rlim_max
= x
;
1394 if (x
== RLIM_INFINITY
)
1395 unit_write_drop_in_private_format(u
, mode
, name
, "%s=infinity\n", name
);
1397 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%" PRIu64
"\n", name
, rl
);