Compare commits

..

No commits in common. "59a49b1bcd88389f1d61516f6ea9793676e68009" and "b82e818f5cc919187630bce88fc5d5ded0f51d23" have entirely different histories.

16 changed files with 266 additions and 437 deletions

17
NEWS
View File

@ -19,7 +19,7 @@ CHANGES WITH 244 in spe:
SystemdOptions. This may be used to configure systemd behaviour when SystemdOptions. This may be used to configure systemd behaviour when
modifying the kernel command line is inconvenient, but configuration modifying the kernel command line is inconvenient, but configuration
on disk is read too late, for example for the options related to on disk is read too late, for example for the options related to
cgroup hierarchy setup. 'bootctl systemd-efi-options' may be used to cgroup hierarchy setup. 'bootctl system-options' may be used to
set the EFI variable. set the EFI variable.
* systemd will now disable printk ratelimits in early boot. This should * systemd will now disable printk ratelimits in early boot. This should
@ -187,19 +187,6 @@ CHANGES WITH 244 in spe:
used by the user service manager. The default is again to use the same used by the user service manager. The default is again to use the same
path as the system manager. path as the system manager.
* The systemd-id128 tool gained a new switch "-u" (or "--uuid") for
outputting the 128bit IDs in UUID format (i.e. in the "canonical
representation").
* Service units gained a new sandboxing option ProtectKernelLogs= which
makes sure the program cannot get direct access to the kernel log
buffer anymore, i.e. the syslog() system call (not to be confused
with the API of the same name in libc, which is not affected), the
/proc/kmsg and /dev/kmsg nodes and the CAP_SYSLOG capability are made
inaccessible to the service. It's recommended to enable this setting
for all services that should not be able to read from or write to the
kernel log buffer, which are probably almost all.
CHANGES WITH 243: CHANGES WITH 243:
* This release enables unprivileged programs (i.e. requiring neither * This release enables unprivileged programs (i.e. requiring neither
@ -518,7 +505,7 @@ CHANGES WITH 243:
* SuccessExitStatus=, RestartPreventExitStatus=, and * SuccessExitStatus=, RestartPreventExitStatus=, and
RestartForceExitStatus= now accept exit status names (e.g. "DATAERR" RestartForceExitStatus= now accept exit status names (e.g. "DATAERR"
is equivalent to "65"). Those exit status name mappings may be is equivalent to "65"). Those exit status name mappings may be
displayed with the systemd-analyze exit-status verb describe above. displayed with the sytemd-analyze exit-status verb describe above.
* systemd-logind now exposes a per-session SetBrightness() bus call, * systemd-logind now exposes a per-session SetBrightness() bus call,
which may be used to securely change the brightness of a kernel which may be used to securely change the brightness of a kernel

View File

@ -47,8 +47,8 @@ All tools:
* `$SYSTEMD_CRYPTTAB` — if set, use this path instead of /etc/crypttab. Only * `$SYSTEMD_CRYPTTAB` — if set, use this path instead of /etc/crypttab. Only
useful for debugging. Currently only supported by systemd-cryptsetup-generator. useful for debugging. Currently only supported by systemd-cryptsetup-generator.
* `$SYSTEMD_EFI_OPTIONS` — if set, used instead of the string in the * `$SYSTEMD_EFI_OPTIONS` — if set, used instead of the string in SystemdOptions
SystemdOptions EFI variable. Analogous to `$SYSTEMD_PROC_CMDLINE`. EFI variable. Analogous to `$SYSTEMD_PROC_CMDLINE`.
* `$SYSTEMD_IN_INITRD` — takes a boolean. If set, overrides initrd detection. * `$SYSTEMD_IN_INITRD` — takes a boolean. If set, overrides initrd detection.
This is useful for debugging and testing initrd-only programs in the main This is useful for debugging and testing initrd-only programs in the main

View File

@ -102,7 +102,7 @@
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><option>systemd-efi-options</option> <optional><replaceable>VALUE</replaceable></optional></term> <term><option>system-options</option> <optional><replaceable>VALUE</replaceable></optional></term>
<listitem><para>When called without the optional argument, prints the current value of the <listitem><para>When called without the optional argument, prints the current value of the
<literal>SystemdOptions</literal> EFI variable. When called with an argument, sets the <literal>SystemdOptions</literal> EFI variable. When called with an argument, sets the

View File

@ -1032,7 +1032,7 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
</refsect2> </refsect2>
<refsect2> <refsect2>
<title>Manager State Commands</title> <title>Manager Lifecycle Commands</title>
<variablelist> <variablelist>
<varlistentry> <varlistentry>
@ -1051,7 +1051,6 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
<command>reload</command> command.</para> <command>reload</command> command.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><command>daemon-reexec</command></term> <term><command>daemon-reexec</command></term>
@ -1066,39 +1065,6 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><command>log-level</command> [<replaceable>LEVEL</replaceable>]</term>
<listitem><para>If no argument is given, print the current log level of the manager. If an
optional argument <replaceable>LEVEL</replaceable> is provided, then the command changes the
current log level of the manager to <replaceable>LEVEL</replaceable> (accepts the same values as
<option>--log-level=</option> described in
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>).
</para></listitem>
</varlistentry>
<varlistentry>
<term><command>log-target</command> [<replaceable>TARGET</replaceable>]</term>
<listitem><para>If no argument is given, print the current log target of the manager. If an
optional argument <replaceable>TARGET</replaceable> is provided, then the command changes the
current log target of the manager to <replaceable>TARGET</replaceable> (accepts the same values as
<option>--log-target=</option>, described in
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>).
</para></listitem>
</varlistentry>
<varlistentry>
<term><command>service-watchdogs</command> [yes|no]</term>
<listitem><para>If no argument is given, print the current state of service runtime watchdogs of
the manager. If an optional boolean argument is provided, then globally enables or disables the
service runtime watchdogs (<option>WatchdogSec=</option>) and emergency actions (e.g.
<option>OnFailure=</option> or <option>StartLimitAction=</option>); see
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
The hardware watchdog is not affected by this setting.</para></listitem>
</varlistentry>
</variablelist> </variablelist>
</refsect2> </refsect2>

View File

@ -39,6 +39,25 @@
<arg choice="opt" rep="repeat"><replaceable>UNIT</replaceable></arg> <arg choice="opt" rep="repeat"><replaceable>UNIT</replaceable></arg>
</cmdsynopsis> </cmdsynopsis>
<cmdsynopsis>
<command>systemd-analyze</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
<arg choice="plain">log-level</arg>
<arg choice="opt"><replaceable>LEVEL</replaceable></arg>
</cmdsynopsis>
<cmdsynopsis>
<command>systemd-analyze</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
<arg choice="plain">log-target</arg>
<arg choice="opt"><replaceable>TARGET</replaceable></arg>
</cmdsynopsis>
<cmdsynopsis>
<command>systemd-analyze</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
<arg choice="plain">service-watchdogs</arg>
<arg choice="opt"><replaceable>BOOL</replaceable></arg>
</cmdsynopsis>
<cmdsynopsis> <cmdsynopsis>
<command>systemd-analyze</command> <command>systemd-analyze</command>
<arg choice="opt" rep="repeat">OPTIONS</arg> <arg choice="opt" rep="repeat">OPTIONS</arg>
@ -222,6 +241,37 @@ multi-user.target @47.820s
</example> </example>
</refsect2> </refsect2>
<refsect2>
<title><command>systemd-analyze log-level [<replaceable>LEVEL</replaceable>]</command></title>
<para><command>systemd-analyze log-level</command> prints the current log level of the
<command>systemd</command> daemon. If an optional argument <replaceable>LEVEL</replaceable> is
provided, then the command changes the current log level of the <command>systemd</command> daemon to
<replaceable>LEVEL</replaceable> (accepts the same values as <option>--log-level=</option> described in
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>).</para>
</refsect2>
<refsect2>
<title><command>systemd-analyze log-target [<replaceable>TARGET</replaceable>]</command></title>
<para><command>systemd-analyze log-target</command> prints the current log target of the
<command>systemd</command> daemon. If an optional argument <replaceable>TARGET</replaceable> is
provided, then the command changes the current log target of the <command>systemd</command> daemon to
<replaceable>TARGET</replaceable> (accepts the same values as <option>--log-target=</option>, described
in <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>).</para>
</refsect2>
<refsect2>
<title><command>systemd-analyze service-watchdogs [yes|no]</command></title>
<para><command>systemd-analyze service-watchdogs</command> prints the current state of service runtime
watchdogs of the <command>systemd</command> daemon. If an optional boolean argument is provided, then
globally enables or disables the service runtime watchdogs (<option>WatchdogSec=</option>) and
emergency actions (e.g. <option>OnFailure=</option> or <option>StartLimitAction=</option>); see
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
The hardware watchdog is not affected by this setting.</para>
</refsect2>
<refsect2> <refsect2>
<title><command>systemd-analyze dump</command></title> <title><command>systemd-analyze dump</command></title>

View File

@ -2166,8 +2166,8 @@ static int service_watchdogs(int argc, char *argv[], void *userdata) {
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to create bus connection: %m"); return log_error_errno(r, "Failed to create bus connection: %m");
/* get ServiceWatchdogs */
if (argc == 1) { if (argc == 1) {
/* get ServiceWatchdogs */
r = sd_bus_get_property_trivial( r = sd_bus_get_property_trivial(
bus, bus,
"org.freedesktop.systemd1", "org.freedesktop.systemd1",
@ -2182,25 +2182,28 @@ static int service_watchdogs(int argc, char *argv[], void *userdata) {
printf("%s\n", yes_no(!!b)); printf("%s\n", yes_no(!!b));
} else { return 0;
/* set ServiceWatchdogs */
b = parse_boolean(argv[1]);
if (b < 0)
return log_error_errno(b, "Failed to parse service-watchdogs argument: %m");
r = sd_bus_set_property(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"ServiceWatchdogs",
&error,
"b",
b);
if (r < 0)
return log_error_errno(r, "Failed to set service-watchdog state: %s", bus_error_message(&error, r));
} }
/* set ServiceWatchdogs */
b = parse_boolean(argv[1]);
if (b < 0) {
log_error("Failed to parse service-watchdogs argument.");
return -EINVAL;
}
r = sd_bus_set_property(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"ServiceWatchdogs",
&error,
"b",
b);
if (r < 0)
return log_error_errno(r, "Failed to set service-watchdog state: %s", bus_error_message(&error, r));
return 0; return 0;
} }
@ -2243,11 +2246,13 @@ static int help(int argc, char *argv[], void *userdata) {
printf("%s [OPTIONS...] COMMAND ...\n\n" printf("%s [OPTIONS...] COMMAND ...\n\n"
"%sProfile systemd, show unit dependencies, check unit files.%s\n" "%sProfile systemd, show unit dependencies, check unit files.%s\n"
"\nCommands:\n" "\nCommands:\n"
" [time] Print time required to boot the machine\n" " time Print time spent in the kernel\n"
" blame Print list of running units ordered by time to init\n" " blame Print list of running units ordered by time to init\n"
" critical-chain [UNIT...] Print a tree of the time critical chain of units\n" " critical-chain [UNIT...] Print a tree of the time critical chain of units\n"
" plot Output SVG graphic showing service initialization\n" " plot Output SVG graphic showing service initialization\n"
" dot [UNIT...] Output dependency graph in %s format\n" " dot [UNIT...] Output dependency graph in %s format\n"
" log-level [LEVEL] Get/set logging threshold for manager\n"
" log-target [TARGET] Get/set logging target for manager\n"
" dump Output state serialization of service manager\n" " dump Output state serialization of service manager\n"
" cat-config Show configuration file and drop-ins\n" " cat-config Show configuration file and drop-ins\n"
" unit-files List files and symlinks for units\n" " unit-files List files and symlinks for units\n"
@ -2256,6 +2261,7 @@ static int help(int argc, char *argv[], void *userdata) {
" syscall-filter [NAME...] Print list of syscalls in seccomp filter\n" " syscall-filter [NAME...] Print list of syscalls in seccomp filter\n"
" condition CONDITION... Evaluate conditions and asserts\n" " condition CONDITION... Evaluate conditions and asserts\n"
" verify FILE... Check unit files for correctness\n" " verify FILE... Check unit files for correctness\n"
" service-watchdogs [BOOL] Get/set service watchdog state\n"
" calendar SPEC... Validate repetitive calendar time events\n" " calendar SPEC... Validate repetitive calendar time events\n"
" timestamp TIMESTAMP... Validate a timestamp\n" " timestamp TIMESTAMP... Validate a timestamp\n"
" timespan SPAN... Validate a time span\n" " timespan SPAN... Validate a time span\n"
@ -2476,14 +2482,13 @@ static int run(int argc, char *argv[]) {
{ "critical-chain", VERB_ANY, VERB_ANY, 0, analyze_critical_chain }, { "critical-chain", VERB_ANY, VERB_ANY, 0, analyze_critical_chain },
{ "plot", VERB_ANY, 1, 0, analyze_plot }, { "plot", VERB_ANY, 1, 0, analyze_plot },
{ "dot", VERB_ANY, VERB_ANY, 0, dot }, { "dot", VERB_ANY, VERB_ANY, 0, dot },
/* The following seven verbs are deprecated */
{ "log-level", VERB_ANY, 2, 0, get_or_set_log_level }, { "log-level", VERB_ANY, 2, 0, get_or_set_log_level },
{ "log-target", VERB_ANY, 2, 0, get_or_set_log_target }, { "log-target", VERB_ANY, 2, 0, get_or_set_log_target },
/* The following four verbs are deprecated aliases */
{ "set-log-level", 2, 2, 0, set_log_level }, { "set-log-level", 2, 2, 0, set_log_level },
{ "get-log-level", VERB_ANY, 1, 0, get_log_level }, { "get-log-level", VERB_ANY, 1, 0, get_log_level },
{ "set-log-target", 2, 2, 0, set_log_target }, { "set-log-target", 2, 2, 0, set_log_target },
{ "get-log-target", VERB_ANY, 1, 0, get_log_target }, { "get-log-target", VERB_ANY, 1, 0, get_log_target },
{ "service-watchdogs", VERB_ANY, 2, 0, service_watchdogs },
{ "dump", VERB_ANY, 1, 0, dump }, { "dump", VERB_ANY, 1, 0, dump },
{ "cat-config", 2, VERB_ANY, 0, cat_config }, { "cat-config", 2, VERB_ANY, 0, cat_config },
{ "unit-files", VERB_ANY, VERB_ANY, 0, do_unit_files }, { "unit-files", VERB_ANY, VERB_ANY, 0, do_unit_files },
@ -2495,6 +2500,7 @@ static int run(int argc, char *argv[]) {
{ "calendar", 2, VERB_ANY, 0, test_calendar }, { "calendar", 2, VERB_ANY, 0, test_calendar },
{ "timestamp", 2, VERB_ANY, 0, test_timestamp }, { "timestamp", 2, VERB_ANY, 0, test_timestamp },
{ "timespan", 2, VERB_ANY, 0, dump_timespan }, { "timespan", 2, VERB_ANY, 0, dump_timespan },
{ "service-watchdogs", VERB_ANY, 2, 0, service_watchdogs },
{ "security", VERB_ANY, VERB_ANY, 0, do_security }, { "security", VERB_ANY, VERB_ANY, 0, do_security },
{} {}
}; };

View File

@ -220,7 +220,7 @@ int efi_set_variable_string(sd_id128_t vendor, const char *name, const char *v)
return efi_set_variable(vendor, name, u16, (char16_strlen(u16) + 1) * sizeof(char16_t)); return efi_set_variable(vendor, name, u16, (char16_strlen(u16) + 1) * sizeof(char16_t));
} }
int systemd_efi_options_variable(char **line) { int efi_systemd_options_variable(char **line) {
const char *e; const char *e;
int r; int r;

View File

@ -28,7 +28,7 @@ int efi_get_variable_string(sd_id128_t vendor, const char *name, char **p);
int efi_set_variable(sd_id128_t vendor, const char *name, const void *value, size_t size); int efi_set_variable(sd_id128_t vendor, const char *name, const void *value, size_t size);
int efi_set_variable_string(sd_id128_t vendor, const char *name, const char *p); int efi_set_variable_string(sd_id128_t vendor, const char *name, const char *p);
int systemd_efi_options_variable(char **line); int efi_systemd_options_variable(char **line);
#else #else
@ -52,7 +52,7 @@ static inline int efi_set_variable_string(sd_id128_t vendor, const char *name, c
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline int systemd_efi_options_variable(char **line) { static inline int efi_systemd_options_variable(char **line) {
return -ENODATA; return -ENODATA;
} }

View File

@ -94,10 +94,3 @@ static inline bool ERRNO_IS_NOT_SUPPORTED(int r) {
ENOTTY, ENOTTY,
ENOSYS); ENOSYS);
} }
/* Two different errors for access problems */
static inline bool ERRNO_IS_PRIVILEGE(int r) {
return IN_SET(abs(r),
EACCES,
EPERM);
}

View File

@ -119,7 +119,7 @@ int proc_cmdline_parse(proc_cmdline_parse_t parse_item, void *data, ProcCmdlineF
/* We parse the EFI variable first, because later settings have higher priority. */ /* We parse the EFI variable first, because later settings have higher priority. */
r = systemd_efi_options_variable(&line); r = efi_systemd_options_variable(&line);
if (r < 0 && r != -ENODATA) if (r < 0 && r != -ENODATA)
log_debug_errno(r, "Failed to get SystemdOptions EFI variable, ignoring: %m"); log_debug_errno(r, "Failed to get SystemdOptions EFI variable, ignoring: %m");
@ -250,7 +250,7 @@ int proc_cmdline_get_key(const char *key, ProcCmdlineFlags flags, char **ret_val
return r; return r;
line = mfree(line); line = mfree(line);
r = systemd_efi_options_variable(&line); r = efi_systemd_options_variable(&line);
if (r == -ENODATA) if (r == -ENODATA)
return false; /* Not found */ return false; /* Not found */
if (r < 0) if (r < 0)

View File

@ -1033,19 +1033,19 @@ static int help(int argc, char *argv[], void *userdata) {
return log_oom(); return log_oom();
printf("%s [OPTIONS...] COMMAND ...\n" printf("%s [OPTIONS...] COMMAND ...\n"
"\n%sInstall/update/remove the systemd-boot EFI boot manager and list/select entries.%s\n" "\n%sInstall, update or remove the systemd-boot EFI boot manager.%s\n"
"\nBoot Loader Commands:\n" "\nBoot Loader Commands:\n"
" status Show status of installed systemd-boot and EFI variables\n" " status Show status of installed systemd-boot and EFI variables\n"
" install Install systemd-boot to the ESP and EFI variables\n" " install Install systemd-boot to the ESP and EFI variables\n"
" update Update systemd-boot in the ESP and EFI variables\n" " update Update systemd-boot in the ESP and EFI variables\n"
" remove Remove systemd-boot from the ESP and EFI variables\n" " remove Remove systemd-boot from the ESP and EFI variables\n"
" is-installed Test whether systemd-boot is installed in the ESP\n" " is-installed Test whether systemd-boot is installed in the ESP\n"
" random-seed Initialize random seed in ESP and EFI variables\n" " random-seed Initialize random seed in ESP and EFI variables\n"
" systemd-efi-options Query or set system options string in EFI variable\n" " system-options Query or set system options string in EFI variable\n"
"\nBoot Loader Entries Commands:\n" "\nBoot Loader Entries Commands:\n"
" list List boot loader entries\n" " list List boot loader entries\n"
" set-default ID Set default boot loader entry\n" " set-default ID Set default boot loader entry\n"
" set-oneshot ID Set default boot loader entry, for next boot only\n" " set-oneshot ID Set default boot loader entry, for next boot only\n"
"\nOptions:\n" "\nOptions:\n"
" -h --help Show this help\n" " -h --help Show this help\n"
" --version Print version\n" " --version Print version\n"
@ -1716,17 +1716,17 @@ static int verb_random_seed(int argc, char *argv[], void *userdata) {
return 0; return 0;
} }
static int verb_systemd_efi_options(int argc, char *argv[], void *userdata) { static int verb_system_options(int argc, char *argv[], void *userdata) {
int r; int r;
if (argc == 1) { if (argc == 1) {
_cleanup_free_ char *line = NULL; _cleanup_free_ char *line = NULL;
r = systemd_efi_options_variable(&line); r = efi_systemd_options_variable(&line);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to query SystemdOptions EFI variable: %m"); return log_error_errno(r, "Failed to query SystemdOptions EFI variable: %m");
puts(line); printf("SystemdOptions: %s\n", line);
} else { } else {
r = efi_set_variable_string(EFI_VENDOR_SYSTEMD, "SystemdOptions", argv[1]); r = efi_set_variable_string(EFI_VENDOR_SYSTEMD, "SystemdOptions", argv[1]);
@ -1739,17 +1739,17 @@ static int verb_systemd_efi_options(int argc, char *argv[], void *userdata) {
static int bootctl_main(int argc, char *argv[]) { static int bootctl_main(int argc, char *argv[]) {
static const Verb verbs[] = { static const Verb verbs[] = {
{ "help", VERB_ANY, VERB_ANY, 0, help }, { "help", VERB_ANY, VERB_ANY, 0, help },
{ "status", VERB_ANY, 1, VERB_DEFAULT, verb_status }, { "status", VERB_ANY, 1, VERB_DEFAULT, verb_status },
{ "install", VERB_ANY, 1, 0, verb_install }, { "install", VERB_ANY, 1, 0, verb_install },
{ "update", VERB_ANY, 1, 0, verb_install }, { "update", VERB_ANY, 1, 0, verb_install },
{ "remove", VERB_ANY, 1, 0, verb_remove }, { "remove", VERB_ANY, 1, 0, verb_remove },
{ "is-installed", VERB_ANY, 1, 0, verb_is_installed }, { "is-installed", VERB_ANY, 1, 0, verb_is_installed },
{ "list", VERB_ANY, 1, 0, verb_list }, { "list", VERB_ANY, 1, 0, verb_list },
{ "set-default", 2, 2, 0, verb_set_default }, { "set-default", 2, 2, 0, verb_set_default },
{ "set-oneshot", 2, 2, 0, verb_set_default }, { "set-oneshot", 2, 2, 0, verb_set_default },
{ "random-seed", VERB_ANY, 1, 0, verb_random_seed }, { "random-seed", VERB_ANY, 1, 0, verb_random_seed },
{ "systemd-efi-options", VERB_ANY, 2, 0, verb_systemd_efi_options }, { "system-options", VERB_ANY, 2, 0, verb_system_options },
{} {}
}; };

View File

@ -2459,40 +2459,6 @@ finish:
return r; return r;
} }
static bool insist_on_sandboxing(
const ExecContext *context,
const char *root_dir,
const char *root_image,
const BindMount *bind_mounts,
size_t n_bind_mounts) {
size_t i;
assert(context);
assert(n_bind_mounts == 0 || bind_mounts);
/* Checks whether we need to insist on fs namespacing. i.e. whether we have settings configured that
* would alter the view on the file system beyond making things read-only or invisble, i.e. would
* rearrange stuff in a way we cannot ignore gracefully. */
if (context->n_temporary_filesystems > 0)
return true;
if (root_dir || root_image)
return true;
if (context->dynamic_user)
return true;
/* If there are any bind mounts set that don't map back onto themselves, fs namespacing becomes
* essential. */
for (i = 0; i < n_bind_mounts; i++)
if (!path_equal(bind_mounts[i].source, bind_mounts[i].destination))
return true;
return false;
}
static int apply_mount_namespace( static int apply_mount_namespace(
const Unit *u, const Unit *u,
const ExecCommand *command, const ExecCommand *command,
@ -2579,28 +2545,28 @@ static int apply_mount_namespace(
DISSECT_IMAGE_DISCARD_ON_LOOP, DISSECT_IMAGE_DISCARD_ON_LOOP,
error_path); error_path);
bind_mount_free_many(bind_mounts, n_bind_mounts);
/* If we couldn't set up the namespace this is probably due to a missing capability. setup_namespace() reports /* If we couldn't set up the namespace this is probably due to a missing capability. setup_namespace() reports
* that with a special, recognizable error ENOANO. In this case, silently proceed, but only if exclusively * that with a special, recognizable error ENOANO. In this case, silently proceed, but only if exclusively
* sandboxing options were used, i.e. nothing such as RootDirectory= or BindMount= that would result in a * sandboxing options were used, i.e. nothing such as RootDirectory= or BindMount= that would result in a
* completely different execution environment. */ * completely different execution environment. */
if (r == -ENOANO) { if (r == -ENOANO) {
if (insist_on_sandboxing( if (n_bind_mounts == 0 &&
context, context->n_temporary_filesystems == 0 &&
root_dir, root_image, !root_dir && !root_image &&
bind_mounts, !context->dynamic_user) {
n_bind_mounts)) {
log_unit_debug(u, "Failed to set up namespace, and refusing to continue since the selected namespacing options alter mount environment non-trivially.\n"
"Bind mounts: %zu, temporary filesystems: %zu, root directory: %s, root image: %s, dynamic user: %s",
n_bind_mounts, context->n_temporary_filesystems, yes_no(root_dir), yes_no(root_image), yes_no(context->dynamic_user));
r = -EOPNOTSUPP;
} else {
log_unit_debug(u, "Failed to set up namespace, assuming containerized execution and ignoring."); log_unit_debug(u, "Failed to set up namespace, assuming containerized execution and ignoring.");
r = 0; return 0;
} }
log_unit_debug(u, "Failed to set up namespace, and refusing to continue since the selected namespacing options alter mount environment non-trivially.\n"
"Bind mounts: %zu, temporary filesystems: %zu, root directory: %s, root image: %s, dynamic user: %s",
n_bind_mounts, context->n_temporary_filesystems, yes_no(root_dir), yes_no(root_image), yes_no(context->dynamic_user));
return -EOPNOTSUPP;
} }
bind_mount_free_many(bind_mounts, n_bind_mounts);
return r; return r;
} }
@ -3448,12 +3414,8 @@ static int exec_child(
if (context->protect_hostname) { if (context->protect_hostname) {
if (ns_type_supported(NAMESPACE_UTS)) { if (ns_type_supported(NAMESPACE_UTS)) {
if (unshare(CLONE_NEWUTS) < 0) { if (unshare(CLONE_NEWUTS) < 0) {
if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno)) { *exit_status = EXIT_NAMESPACE;
*exit_status = EXIT_NAMESPACE; return log_unit_error_errno(unit, errno, "Failed to set up UTS namespacing: %m");
return log_unit_error_errno(unit, errno, "Failed to set up UTS namespacing: %m");
}
log_unit_warning(unit, "ProtectHostname=yes is configured, but UTS namespace setup is prohibited (container manager?), ignoring namespace setup.");
} }
} else } else
log_unit_warning(unit, "ProtectHostname=yes is configured, but the kernel does not support UTS namespaces, ignoring namespace setup."); log_unit_warning(unit, "ProtectHostname=yes is configured, but the kernel does not support UTS namespaces, ignoring namespace setup.");

View File

@ -501,14 +501,18 @@ fail:
static bool path_check_good(Path *p, bool initial) { static bool path_check_good(Path *p, bool initial) {
PathSpec *s; PathSpec *s;
bool good = false;
assert(p); assert(p);
LIST_FOREACH(spec, s, p->specs) LIST_FOREACH(spec, s, p->specs) {
if (path_spec_check_good(s, initial)) good = path_spec_check_good(s, initial);
return true;
return false; if (good)
break;
}
return good;
} }
static void path_enter_waiting(Path *p, bool initial, bool recheck) { static void path_enter_waiting(Path *p, bool initial, bool recheck) {

View File

@ -12,7 +12,7 @@
#include "verbs.h" #include "verbs.h"
static Id128PrettyPrintMode arg_mode = ID128_PRINT_ID128; static Id128PrettyPrintMode arg_mode = ID128_PRINT_ID128;
static sd_id128_t arg_app = {}; static sd_id128_t arg_app = SD_ID128_NULL;
static int verb_new(int argc, char **argv, void *userdata) { static int verb_new(int argc, char **argv, void *userdata) {
return id128_print_new(arg_mode); return id128_print_new(arg_mode);

View File

@ -6343,145 +6343,6 @@ static int switch_root(int argc, char *argv[], void *userdata) {
return 0; return 0;
} }
static int log_level(int argc, char *argv[], void *userdata) {
sd_bus *bus;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
return r;
if (argc == 1) {
_cleanup_free_ char *level = NULL;
r = sd_bus_get_property_string(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"LogLevel",
&error,
&level);
if (r < 0)
return log_error_errno(r, "Failed to get log level: %s", bus_error_message(&error, r));
puts(level);
} else {
assert(argc == 2);
r = sd_bus_set_property(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"LogLevel",
&error,
"s",
argv[1]);
if (r < 0)
return log_error_errno(r, "Failed to set log level: %s", bus_error_message(&error, r));
}
return 0;
}
static int log_target(int argc, char *argv[], void *userdata) {
sd_bus *bus;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
return r;
if (argc == 1) {
_cleanup_free_ char *target = NULL;
r = sd_bus_get_property_string(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"LogTarget",
&error,
&target);
if (r < 0)
return log_error_errno(r, "Failed to get log target: %s", bus_error_message(&error, r));
puts(target);
} else {
assert(argc == 2);
r = sd_bus_set_property(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"LogTarget",
&error,
"s",
argv[1]);
if (r < 0)
return log_error_errno(r, "Failed to set log target: %s", bus_error_message(&error, r));
}
return 0;
}
static int service_watchdogs(int argc, char *argv[], void *userdata) {
sd_bus *bus;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int b, r;
assert(argv);
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
return r;
if (argc == 1) {
/* get ServiceWatchdogs */
r = sd_bus_get_property_trivial(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"ServiceWatchdogs",
&error,
'b',
&b);
if (r < 0)
return log_error_errno(r, "Failed to get service-watchdog state: %s", bus_error_message(&error, r));
printf("%s\n", yes_no(!!b));
} else {
/* set ServiceWatchdogs */
assert(argc == 2);
b = parse_boolean(argv[1]);
if (b < 0)
return log_error_errno(b, "Failed to parse service-watchdogs argument: %m");
r = sd_bus_set_property(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"ServiceWatchdogs",
&error,
"b",
b);
if (r < 0)
return log_error_errno(r, "Failed to set service-watchdog state: %s", bus_error_message(&error, r));
}
return 0;
}
static int set_environment(int argc, char *argv[], void *userdata) { static int set_environment(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
@ -7866,7 +7727,7 @@ static int systemctl_help(void) {
" units\n" " units\n"
" list-dependencies [UNIT] Recursively show units which are required\n" " list-dependencies [UNIT] Recursively show units which are required\n"
" or wanted by this unit or by which this\n" " or wanted by this unit or by which this\n"
" unit is required or wanted" " unit is required or wanted\n"
"\n%3$sUnit File Commands:%4$s\n" "\n%3$sUnit File Commands:%4$s\n"
" list-unit-files [PATTERN...] List installed unit files\n" " list-unit-files [PATTERN...] List installed unit files\n"
" enable [UNIT...|PATH...] Enable one or more unit files\n" " enable [UNIT...|PATH...] Enable one or more unit files\n"
@ -7891,7 +7752,7 @@ static int systemctl_help(void) {
" get-default Get the name of the default target\n" " get-default Get the name of the default target\n"
" set-default TARGET Set the default target\n" " set-default TARGET Set the default target\n"
"\n%3$sMachine Commands:%4$s\n" "\n%3$sMachine Commands:%4$s\n"
" list-machines [PATTERN...] List local containers and host\n" " list-machines [PATTERN...] List local containers and host\n\n"
"\n%3$sJob Commands:%4$s\n" "\n%3$sJob Commands:%4$s\n"
" list-jobs [PATTERN...] List jobs\n" " list-jobs [PATTERN...] List jobs\n"
" cancel [JOB...] Cancel all, one, or more jobs\n" " cancel [JOB...] Cancel all, one, or more jobs\n"
@ -7899,13 +7760,10 @@ static int systemctl_help(void) {
" show-environment Dump environment\n" " show-environment Dump environment\n"
" set-environment VARIABLE=VALUE... Set one or more environment variables\n" " set-environment VARIABLE=VALUE... Set one or more environment variables\n"
" unset-environment VARIABLE... Unset one or more environment variables\n" " unset-environment VARIABLE... Unset one or more environment variables\n"
" import-environment [VARIABLE...] Import all or some environment variables\n" " import-environment [VARIABLE...] Import all or some environment variables\n\n"
"\n%3$sManager State Commands:%4$s\n" "\n%3$sManager Lifecycle Commands:%4$s\n"
" daemon-reload Reload systemd manager configuration\n" " daemon-reload Reload systemd manager configuration\n"
" daemon-reexec Reexecute systemd manager\n" " daemon-reexec Reexecute systemd manager\n"
" log-level [LEVEL] Get/set logging threshold for manager\n"
" log-target [TARGET] Get/set logging target for manager\n"
" service-watchdogs [BOOL] Get/set service watchdog state\n"
"\n%3$sSystem Commands:%4$s\n" "\n%3$sSystem Commands:%4$s\n"
" is-system-running Check whether system is fully running\n" " is-system-running Check whether system is fully running\n"
" default Enter system default mode\n" " default Enter system default mode\n"
@ -7921,63 +7779,68 @@ static int systemctl_help(void) {
" hibernate Hibernate the system\n" " hibernate Hibernate the system\n"
" hybrid-sleep Hibernate and suspend the system\n" " hybrid-sleep Hibernate and suspend the system\n"
" suspend-then-hibernate Suspend the system, wake after a period of\n" " suspend-then-hibernate Suspend the system, wake after a period of\n"
" time, and hibernate" " time and put it into hibernate\n"
"\n%3$sOptions:%4$s\n" "\n%3$sOptions:%4$s\n"
" -h --help Show this help\n" " -h --help Show this help\n"
" --version Show package version\n" " --version Show package version\n"
" --system Connect to system manager\n" " --system Connect to system manager\n"
" --user Connect to user service manager\n" " --user Connect to user service manager\n"
" -H --host=[USER@]HOST Operate on remote host\n" " -H --host=[USER@]HOST\n"
" -M --machine=CONTAINER Operate on a local container\n" " Operate on remote host\n"
" -t --type=TYPE List units of a particular type\n" " -M --machine=CONTAINER\n"
" --state=STATE List units with particular LOAD or SUB or ACTIVE state\n" " Operate on local container\n"
" --failed Shorcut for --state=failed\n" " -t --type=TYPE List units of a particular type\n"
" -p --property=NAME Show only properties by this name\n" " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
" -a --all Show all properties/all units currently in memory,\n" " --failed Shorcut for --state=failed\n"
" including dead/empty ones. To list all units installed\n" " -p --property=NAME Show only properties by this name\n"
" on the system, use 'list-unit-files' instead.\n" " -a --all Show all properties/all units currently in memory,\n"
" -l --full Don't ellipsize unit names on output\n" " including dead/empty ones. To list all units installed on\n"
" -r --recursive Show unit list of host and local containers\n" " the system, use the 'list-unit-files' command instead.\n"
" --reverse Show reverse dependencies with 'list-dependencies'\n" " -l --full Don't ellipsize unit names on output\n"
" --job-mode=MODE Specify how to deal with already queued jobs, when\n" " -r --recursive Show unit list of host and local containers\n"
" queueing a new job\n" " --reverse Show reverse dependencies with 'list-dependencies'\n"
" -T --show-transaction When enqueuing a unit job, show full transaction\n" " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
" --show-types When showing sockets, explicitly show their type\n" " queueing a new job\n"
" --value When showing properties, only print the value\n" " -T --show-transaction\n"
" -i --ignore-inhibitors When shutting down or sleeping, ignore inhibitors\n" " When enqueuing a unit job, show full transaction\n"
" --kill-who=WHO Whom to send signal to\n" " --show-types When showing sockets, explicitly show their type\n"
" -s --signal=SIGNAL Which signal to send\n" " --value When showing properties, only print the value\n"
" --what=RESOURCES Which types of resources to remove\n" " -i --ignore-inhibitors\n"
" --now Start or stop unit after enabling or disabling it\n" " When shutting down or sleeping, ignore inhibitors\n"
" --dry-run Only print what would be done\n" " --kill-who=WHO Who to send signal to\n"
" -q --quiet Suppress output\n" " -s --signal=SIGNAL Which signal to send\n"
" --wait For (re)start, wait until service stopped again\n" " --what=RESOURCES Which types of resources to remove\n"
" For is-system-running, wait until startup is completed\n" " --now Start or stop unit in addition to enabling or disabling it\n"
" --no-block Do not wait until operation finished\n" " --dry-run Only print what would be done\n"
" --no-wall Don't send wall message before halt/power-off/reboot\n" " -q --quiet Suppress output\n"
" --no-reload Don't reload daemon after en-/dis-abling unit files\n" " --wait For (re)start, wait until service stopped again\n"
" --no-legend Do not print a legend (column headers and hints)\n" " For is-system-running, wait until startup is completed\n"
" --no-pager Do not pipe output into a pager\n" " --no-block Do not wait until operation finished\n"
" --no-ask-password Do not ask for system passwords\n" " --no-wall Don't send wall message before halt/power-off/reboot\n"
" --global Enable/disable/mask unit files globally\n" " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
" --runtime Enable/disable/mask unit files temporarily until next\n" " --no-legend Do not print a legend (column headers and hints)\n"
" reboot\n" " --no-pager Do not pipe output into a pager\n"
" -f --force When enabling unit files, override existing symlinks\n" " --no-ask-password\n"
" When shutting down, execute action immediately\n" " Do not ask for system passwords\n"
" --preset-mode= Apply only enable, only disable, or all presets\n" " --global Enable/disable/mask unit files globally\n"
" --root=PATH Enable/disable/mask unit files in the specified root\n" " --runtime Enable/disable/mask unit files temporarily until next\n"
" directory\n" " reboot\n"
" -n --lines=INTEGER Number of journal entries to show\n" " -f --force When enabling unit files, override existing symlinks\n"
" -o --output=STRING Change journal output mode (short, short-precise,\n" " When shutting down, execute action immediately\n"
" --preset-mode= Apply only enable, only disable, or all presets\n"
" --root=PATH Enable/disable/mask unit files in the specified root\n"
" directory\n"
" -n --lines=INTEGER Number of journal entries to show\n"
" -o --output=STRING Change journal output mode (short, short-precise,\n"
" short-iso, short-iso-precise, short-full,\n" " short-iso, short-iso-precise, short-full,\n"
" short-monotonic, short-unix,\n" " short-monotonic, short-unix,\n"
" verbose, export, json, json-pretty, json-sse, cat)\n" " verbose, export, json, json-pretty, json-sse, cat)\n"
" --firmware-setup Tell the firmware to show the setup menu on next boot\n" " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
" --boot-loader-menu=TIME\n" " --boot-loader-menu=TIME\n"
" Boot into boot loader menu on next boot\n" " Boot into boot loader menu on next boot\n"
" --boot-loader-entry=NAME\n" " --boot-loader-entry=NAME\n"
" Boot into a specific boot loader entry on next boot\n" " Boot into a specific boot loader entry on next boot\n"
" --plain Print unit dependencies as a list instead of a tree\n" " --plain Print unit dependencies as a list instead of a tree\n"
"\nSee the %2$s for details.\n" "\nSee the %2$s for details.\n"
, program_invocation_short_name , program_invocation_short_name
, link , link
@ -9092,76 +8955,73 @@ _pure_ static int action_to_runlevel(void) {
static int systemctl_main(int argc, char *argv[]) { static int systemctl_main(int argc, char *argv[]) {
static const Verb verbs[] = { static const Verb verbs[] = {
{ "list-units", VERB_ANY, VERB_ANY, VERB_DEFAULT|VERB_ONLINE_ONLY, list_units }, { "list-units", VERB_ANY, VERB_ANY, VERB_DEFAULT|VERB_ONLINE_ONLY, list_units },
{ "list-unit-files", VERB_ANY, VERB_ANY, 0, list_unit_files }, { "list-unit-files", VERB_ANY, VERB_ANY, 0, list_unit_files },
{ "list-sockets", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, list_sockets }, { "list-sockets", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, list_sockets },
{ "list-timers", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, list_timers }, { "list-timers", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, list_timers },
{ "list-jobs", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, list_jobs }, { "list-jobs", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, list_jobs },
{ "list-machines", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, list_machines }, { "list-machines", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, list_machines },
{ "clear-jobs", VERB_ANY, 1, VERB_ONLINE_ONLY, trivial_method }, { "clear-jobs", VERB_ANY, 1, VERB_ONLINE_ONLY, trivial_method },
{ "cancel", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, cancel_job }, { "cancel", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, cancel_job },
{ "start", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, { "start", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
{ "stop", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, { "stop", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
{ "condstop", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with ALTLinux */ { "condstop", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with ALTLinux */
{ "reload", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, { "reload", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
{ "restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, { "restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
{ "try-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, { "try-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
{ "reload-or-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, { "reload-or-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
{ "reload-or-try-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with old systemctl <= 228 */ { "reload-or-try-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with old systemctl <= 228 */
{ "try-reload-or-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, { "try-reload-or-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
{ "force-reload", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with SysV */ { "force-reload", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with SysV */
{ "condreload", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with ALTLinux */ { "condreload", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with ALTLinux */
{ "condrestart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with RH */ { "condrestart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with RH */
{ "isolate", 2, 2, VERB_ONLINE_ONLY, start_unit }, { "isolate", 2, 2, VERB_ONLINE_ONLY, start_unit },
{ "kill", 2, VERB_ANY, VERB_ONLINE_ONLY, kill_unit }, { "kill", 2, VERB_ANY, VERB_ONLINE_ONLY, kill_unit },
{ "clean", 2, VERB_ANY, VERB_ONLINE_ONLY, clean_unit }, { "clean", 2, VERB_ANY, VERB_ONLINE_ONLY, clean_unit },
{ "is-active", 2, VERB_ANY, VERB_ONLINE_ONLY, check_unit_active }, { "is-active", 2, VERB_ANY, VERB_ONLINE_ONLY, check_unit_active },
{ "check", 2, VERB_ANY, VERB_ONLINE_ONLY, check_unit_active }, /* deprecated alias of is-active */ { "check", 2, VERB_ANY, VERB_ONLINE_ONLY, check_unit_active }, /* deprecated alias of is-active */
{ "is-failed", 2, VERB_ANY, VERB_ONLINE_ONLY, check_unit_failed }, { "is-failed", 2, VERB_ANY, VERB_ONLINE_ONLY, check_unit_failed },
{ "show", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, show }, { "show", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, show },
{ "cat", 2, VERB_ANY, VERB_ONLINE_ONLY, cat }, { "cat", 2, VERB_ANY, VERB_ONLINE_ONLY, cat },
{ "status", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, show }, { "status", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, show },
{ "help", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, show }, { "help", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, show },
{ "daemon-reload", VERB_ANY, 1, VERB_ONLINE_ONLY, daemon_reload }, { "daemon-reload", VERB_ANY, 1, VERB_ONLINE_ONLY, daemon_reload },
{ "daemon-reexec", VERB_ANY, 1, VERB_ONLINE_ONLY, daemon_reload }, { "daemon-reexec", VERB_ANY, 1, VERB_ONLINE_ONLY, daemon_reload },
{ "log-level", VERB_ANY, 2, 0, log_level }, { "show-environment", VERB_ANY, 1, VERB_ONLINE_ONLY, show_environment },
{ "log-target", VERB_ANY, 2, 0, log_target }, { "set-environment", 2, VERB_ANY, VERB_ONLINE_ONLY, set_environment },
{ "service-watchdogs", VERB_ANY, 2, 0, service_watchdogs }, { "unset-environment", 2, VERB_ANY, VERB_ONLINE_ONLY, set_environment },
{ "show-environment", VERB_ANY, 1, VERB_ONLINE_ONLY, show_environment }, { "import-environment", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, import_environment },
{ "set-environment", 2, VERB_ANY, VERB_ONLINE_ONLY, set_environment }, { "halt", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
{ "unset-environment", 2, VERB_ANY, VERB_ONLINE_ONLY, set_environment }, { "poweroff", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
{ "import-environment", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, import_environment }, { "reboot", VERB_ANY, 2, VERB_ONLINE_ONLY, start_system_special },
{ "halt", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, { "kexec", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
{ "poweroff", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, { "suspend", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
{ "reboot", VERB_ANY, 2, VERB_ONLINE_ONLY, start_system_special }, { "hibernate", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
{ "kexec", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, { "hybrid-sleep", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
{ "suspend", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, { "suspend-then-hibernate",VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
{ "hibernate", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, { "default", VERB_ANY, 1, VERB_ONLINE_ONLY, start_special },
{ "hybrid-sleep", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, { "rescue", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
{ "suspend-then-hibernate",VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, { "emergency", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
{ "default", VERB_ANY, 1, VERB_ONLINE_ONLY, start_special }, { "exit", VERB_ANY, 2, VERB_ONLINE_ONLY, start_special },
{ "rescue", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, { "reset-failed", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, reset_failed },
{ "emergency", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, { "enable", 2, VERB_ANY, 0, enable_unit },
{ "exit", VERB_ANY, 2, VERB_ONLINE_ONLY, start_special }, { "disable", 2, VERB_ANY, 0, enable_unit },
{ "reset-failed", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, reset_failed }, { "is-enabled", 2, VERB_ANY, 0, unit_is_enabled },
{ "enable", 2, VERB_ANY, 0, enable_unit }, { "reenable", 2, VERB_ANY, 0, enable_unit },
{ "disable", 2, VERB_ANY, 0, enable_unit }, { "preset", 2, VERB_ANY, 0, enable_unit },
{ "is-enabled", 2, VERB_ANY, 0, unit_is_enabled }, { "preset-all", VERB_ANY, 1, 0, preset_all },
{ "reenable", 2, VERB_ANY, 0, enable_unit }, { "mask", 2, VERB_ANY, 0, enable_unit },
{ "preset", 2, VERB_ANY, 0, enable_unit }, { "unmask", 2, VERB_ANY, 0, enable_unit },
{ "preset-all", VERB_ANY, 1, 0, preset_all }, { "link", 2, VERB_ANY, 0, enable_unit },
{ "mask", 2, VERB_ANY, 0, enable_unit }, { "revert", 2, VERB_ANY, 0, enable_unit },
{ "unmask", 2, VERB_ANY, 0, enable_unit }, { "switch-root", 2, VERB_ANY, VERB_ONLINE_ONLY, switch_root },
{ "link", 2, VERB_ANY, 0, enable_unit }, { "list-dependencies", VERB_ANY, 2, VERB_ONLINE_ONLY, list_dependencies },
{ "revert", 2, VERB_ANY, 0, enable_unit }, { "set-default", 2, 2, 0, set_default },
{ "switch-root", 2, VERB_ANY, VERB_ONLINE_ONLY, switch_root }, { "get-default", VERB_ANY, 1, 0, get_default },
{ "list-dependencies", VERB_ANY, 2, VERB_ONLINE_ONLY, list_dependencies }, { "set-property", 3, VERB_ANY, VERB_ONLINE_ONLY, set_property },
{ "set-default", 2, 2, 0, set_default }, { "is-system-running", VERB_ANY, 1, 0, is_system_running },
{ "get-default", VERB_ANY, 1, 0, get_default }, { "add-wants", 3, VERB_ANY, 0, add_dependency },
{ "set-property", 3, VERB_ANY, VERB_ONLINE_ONLY, set_property }, { "add-requires", 3, VERB_ANY, 0, add_dependency },
{ "is-system-running", VERB_ANY, 1, 0, is_system_running }, { "edit", 2, VERB_ANY, VERB_ONLINE_ONLY, edit },
{ "add-wants", 3, VERB_ANY, 0, add_dependency },
{ "add-requires", 3, VERB_ANY, 0, add_dependency },
{ "edit", 2, VERB_ANY, VERB_ONLINE_ONLY, edit },
{} {}
}; };

View File

@ -3,6 +3,7 @@ Description=Test for ReadOnlyPaths=
[Service] [Service]
ReadOnlyPaths=/etc -/i-dont-exist /usr ReadOnlyPaths=/etc -/i-dont-exist /usr
BindPaths=/etc:/tmp/etc2 # From 6c47cd7d3bf35c8158a0737f34fe2c5dc95e72d6, RuntimeDirectory= implies BindPaths=.
RuntimeDirectory=foo
ExecStart=/bin/sh -x -c 'test ! -w /etc && test ! -w /usr && test ! -e /i-dont-exist && test -w /var' ExecStart=/bin/sh -x -c 'test ! -w /etc && test ! -w /usr && test ! -e /i-dont-exist && test -w /var'
Type=oneshot Type=oneshot