Compare commits

..

17 Commits

Author SHA1 Message Date
Lennart Poettering 59a49b1bcd
Merge pull request #14090 from poettering/clonenewns-fix
make sure systemd-logind.service can start if unshare() is blocked
2019-11-20 17:27:56 +01:00
Lennart Poettering 168e131b8b update NEWS 2019-11-20 16:16:46 +01:00
Zbigniew Jędrzejewski-Szmek 8490fc7aef
Merge pull request #14036 from keszybz/systectl-add-logs-and-watchdogs
Systemctl add log-level, log-target, service-watchdogs commands
2019-11-20 16:15:09 +01:00
Zbigniew Jędrzejewski-Szmek 2d8898f564
Merge pull request #14074 from keszybz/rename-system-options
Rename system-options
2019-11-20 16:13:46 +01:00
Lennart Poettering 6d19b71876 core: don't insist on ProtectHostname= if unshare() is blocked
Previously we'd only skip ProtectHostname= if kernel support for
namespaces was lacking. With this change we also accept if unshare()
fails because it is blocked.
2019-11-20 12:49:06 +01:00
Lennart Poettering 4e67759960 core: be more lenient when checking whether sandboxing is necessary
In some containers unshare() is made unavailable entirely. Let's deal
with this that more gracefully and disable our sandboxing of services
then, so that we work in a container, under the assumption the container
manager is then responsible for sandboxing if we can't do it ourselves.

Previously, we'd insist on sandboxing as soon as any form of BindPath=
is used. With this change we only insist on it if we have a setting like
that where source and destination differ, i.e. there's a mapping
established that actually rearranges things, and thus would result in
systematically different behaviour if skipped (as opposed to mappings
that just make stuff read-only/writable that otherwise arent').

(Let's also update a test that intended to test for this behaviour with
a more specific configuration that still triggers the behaviour with
this change in place)

Fixes: #13955

(For testing purposes unshare() can easily be blocked with
systemd-nspawn --system-call-filter=~unshare.)
2019-11-20 12:30:04 +01:00
Lennart Poettering e884e00071 errno-util: add ERRNO_IS_PRIVILEGE() helper 2019-11-20 12:29:54 +01:00
Anita Zhang 206a29b2e1 id128: fix initializer element is not constant
Was getting:

  ../src/id128/id128.c:15:1: error: initializer element is not constant
   static sd_id128_t arg_app = SD_ID128_NULL;
    ^
when building on CentOS 7.

Other parts of the code initialize `static sd_id128_t` to {} and this
was the original setting before a19fdd66c2 anyways.
2019-11-20 10:59:25 +01:00
Zbigniew Jędrzejewski-Szmek 2536752dda Rename "system-options" to "systemd-efi-options"
This makes the naming more consistent: we now have
bootctl systemd-efi-options,
$SYSTEMD_EFI_OPTIONS
and the SystemdOptions EFI variable.

(SystemdEFIOptions would be redundant, because it is only used in the context
of efivars, and users don't interact with that name directly.)

bootctl is adjusted to use 2sp indentation, similarly to systemctl and other
programs.

Remove the prefix with the old name from 'bootctl systemd-efi-options' output,
since it's redundant and we don't want the old name anyway.
2019-11-18 20:20:58 +01:00
Zbigniew Jędrzejewski-Szmek cc560ac064 NEWS: fix antique typo 2019-11-18 20:20:58 +01:00
Zbigniew Jędrzejewski-Szmek b289de2b06 bootctl: update --help text 2019-11-18 20:20:58 +01:00
Zbigniew Jędrzejewski-Szmek 93e63b2a35 core/path: minor simplification 2019-11-18 20:18:34 +01:00
Zbigniew Jędrzejewski-Szmek 4d985a317a systemctl: whitespace optimization of --help
Move the explanation of options three columns to the right: then almost
all options fit and we do not need to break lines so often.

When a multi-line explanation precedes a section break, i.e. there is a
half-line on the right side, do not use an empty space. This saves a line,
and actually looks visually better because the text is still clearly
separated, but we don't get the big vertical white space.
2019-11-18 16:41:13 +01:00
Zbigniew Jędrzejewski-Szmek 26e1e97345 analyze: deprecate the commands moved to systemctl
This just removes the commands from --help and the man pages, everything works
as before.
2019-11-18 16:28:38 +01:00
Zbigniew Jędrzejewski-Szmek 6ab863190d systemctl: add service-watchdogs command
The rationale is the same as for log-level/log-target: this controls the behaviour
of the manager, and belongs in systemctl.
2019-11-18 16:28:38 +01:00
Zbigniew Jędrzejewski-Szmek 6962cf2e2a analyze: adjust the description of the default verb 2019-11-18 16:27:15 +01:00
Zbigniew Jędrzejewski-Szmek 38fcb7f766 systemctl: add log-level and log-target commands
This copies the commands log-level and log-target (to query and set the current
settings) from systemd-analyze to systemctl, essentially reverting
a65615ca5d. Controllling the log level settings
of the manager is basic functionality, that should be available even if
systemd-analyze (which is more of an analysis tool) is not installed. This is
like dmesg and journalctl, which should be available even if a debugger and
more advanced tools to analyze the kernel are not available. (Note that dmesg
is used to control the log level too, not just to browse the kernel logs.)

I chose to copy&paste the methods from analyze.c to the new location. There
isn't enough code to share, because acquire_bus() in both places has a
different signature despite the same name, so the only part that is common
is the invocation of sd_bus_set_property().
2019-11-18 16:26:17 +01:00
16 changed files with 436 additions and 265 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 system-options' may be used to cgroup hierarchy setup. 'bootctl systemd-efi-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,6 +187,19 @@ 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
@ -505,7 +518,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 sytemd-analyze exit-status verb describe above. displayed with the systemd-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 SystemdOptions * `$SYSTEMD_EFI_OPTIONS` — if set, used instead of the string in the
EFI variable. Analogous to `$SYSTEMD_PROC_CMDLINE`. SystemdOptions 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>system-options</option> <optional><replaceable>VALUE</replaceable></optional></term> <term><option>systemd-efi-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 Lifecycle Commands</title> <title>Manager State Commands</title>
<variablelist> <variablelist>
<varlistentry> <varlistentry>
@ -1051,6 +1051,7 @@ 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>
@ -1065,6 +1066,39 @@ 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,25 +39,6 @@
<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>
@ -241,37 +222,6 @@ 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,28 +2182,25 @@ static int service_watchdogs(int argc, char *argv[], void *userdata) {
printf("%s\n", yes_no(!!b)); printf("%s\n", yes_no(!!b));
return 0; } else {
} /* set ServiceWatchdogs */
b = parse_boolean(argv[1]);
if (b < 0)
return log_error_errno(b, "Failed to parse service-watchdogs argument: %m");
/* set ServiceWatchdogs */ r = sd_bus_set_property(
b = parse_boolean(argv[1]); bus,
if (b < 0) { "org.freedesktop.systemd1",
log_error("Failed to parse service-watchdogs argument."); "/org/freedesktop/systemd1",
return -EINVAL; "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));
} }
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;
} }
@ -2246,13 +2243,11 @@ 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 spent in the kernel\n" " [time] Print time required to boot the machine\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"
@ -2261,7 +2256,6 @@ 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"
@ -2482,13 +2476,14 @@ 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 },
@ -2500,7 +2495,6 @@ 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 efi_systemd_options_variable(char **line) { int systemd_efi_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 efi_systemd_options_variable(char **line); int systemd_efi_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 efi_systemd_options_variable(char **line) { static inline int systemd_efi_options_variable(char **line) {
return -ENODATA; return -ENODATA;
} }

View File

@ -94,3 +94,10 @@ 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 = efi_systemd_options_variable(&line); r = systemd_efi_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 = efi_systemd_options_variable(&line); r = systemd_efi_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 or remove the systemd-boot EFI boot manager.%s\n" "\n%sInstall/update/remove the systemd-boot EFI boot manager and list/select entries.%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"
" system-options Query or set system options string in EFI variable\n" " systemd-efi-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_system_options(int argc, char *argv[], void *userdata) { static int verb_systemd_efi_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 = efi_systemd_options_variable(&line); r = systemd_efi_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");
printf("SystemdOptions: %s\n", line); puts(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_system_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 },
{ "system-options", VERB_ANY, 2, 0, verb_system_options }, { "systemd-efi-options", VERB_ANY, 2, 0, verb_systemd_efi_options },
{} {}
}; };

View File

@ -2459,6 +2459,40 @@ 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,
@ -2545,28 +2579,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 (n_bind_mounts == 0 && if (insist_on_sandboxing(
context->n_temporary_filesystems == 0 && context,
!root_dir && !root_image && root_dir, root_image,
!context->dynamic_user) { bind_mounts,
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.");
return 0; r = 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;
} }
@ -3414,8 +3448,12 @@ 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) {
*exit_status = EXIT_NAMESPACE; if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno)) {
return log_unit_error_errno(unit, errno, "Failed to set up UTS namespacing: %m"); *exit_status = EXIT_NAMESPACE;
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,18 +501,14 @@ 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)
good = path_spec_check_good(s, initial); if (path_spec_check_good(s, initial))
return true;
if (good) return false;
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 = SD_ID128_NULL; static sd_id128_t arg_app = {};
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,6 +6343,145 @@ 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;
@ -7727,7 +7866,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\n" " unit is required or wanted"
"\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"
@ -7752,7 +7891,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\n" " list-machines [PATTERN...] List local containers and host\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"
@ -7760,10 +7899,13 @@ 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\n" " import-environment [VARIABLE...] Import all or some environment variables\n"
"\n%3$sManager Lifecycle Commands:%4$s\n" "\n%3$sManager State 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"
@ -7779,68 +7921,63 @@ 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 put it into hibernate\n" " time, and hibernate"
"\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\n" " -H --host=[USER@]HOST Operate on remote host\n"
" Operate on remote host\n" " -M --machine=CONTAINER Operate on a local container\n"
" -M --machine=CONTAINER\n" " -t --type=TYPE List units of a particular type\n"
" Operate on local container\n" " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
" -t --type=TYPE List units of a particular type\n" " --failed Shorcut for --state=failed\n"
" --state=STATE List units with particular LOAD or SUB or ACTIVE state\n" " -p --property=NAME Show only properties by this name\n"
" --failed Shorcut for --state=failed\n" " -a --all Show all properties/all units currently in memory,\n"
" -p --property=NAME Show only properties by this name\n" " including dead/empty ones. To list all units installed\n"
" -a --all Show all properties/all units currently in memory,\n" " on the system, use 'list-unit-files' instead.\n"
" including dead/empty ones. To list all units installed on\n" " -l --full Don't ellipsize unit names on output\n"
" the system, use the 'list-unit-files' command instead.\n" " -r --recursive Show unit list of host and local containers\n"
" -l --full Don't ellipsize unit names on output\n" " --reverse Show reverse dependencies with 'list-dependencies'\n"
" -r --recursive Show unit list of host and local containers\n" " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
" --reverse Show reverse dependencies with 'list-dependencies'\n" " queueing a new job\n"
" --job-mode=MODE Specify how to deal with already queued jobs, when\n" " -T --show-transaction When enqueuing a unit job, show full transaction\n"
" queueing a new job\n" " --show-types When showing sockets, explicitly show their type\n"
" -T --show-transaction\n" " --value When showing properties, only print the value\n"
" When enqueuing a unit job, show full transaction\n" " -i --ignore-inhibitors When shutting down or sleeping, ignore inhibitors\n"
" --show-types When showing sockets, explicitly show their type\n" " --kill-who=WHO Whom to send signal to\n"
" --value When showing properties, only print the value\n" " -s --signal=SIGNAL Which signal to send\n"
" -i --ignore-inhibitors\n" " --what=RESOURCES Which types of resources to remove\n"
" When shutting down or sleeping, ignore inhibitors\n" " --now Start or stop unit after enabling or disabling it\n"
" --kill-who=WHO Who to send signal to\n" " --dry-run Only print what would be done\n"
" -s --signal=SIGNAL Which signal to send\n" " -q --quiet Suppress output\n"
" --what=RESOURCES Which types of resources to remove\n" " --wait For (re)start, wait until service stopped again\n"
" --now Start or stop unit in addition to enabling or disabling it\n" " For is-system-running, wait until startup is completed\n"
" --dry-run Only print what would be done\n" " --no-block Do not wait until operation finished\n"
" -q --quiet Suppress output\n" " --no-wall Don't send wall message before halt/power-off/reboot\n"
" --wait For (re)start, wait until service stopped again\n" " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
" For is-system-running, wait until startup is completed\n" " --no-legend Do not print a legend (column headers and hints)\n"
" --no-block Do not wait until operation finished\n" " --no-pager Do not pipe output into a pager\n"
" --no-wall Don't send wall message before halt/power-off/reboot\n" " --no-ask-password Do not ask for system passwords\n"
" --no-reload Don't reload daemon after en-/dis-abling unit files\n" " --global Enable/disable/mask unit files globally\n"
" --no-legend Do not print a legend (column headers and hints)\n" " --runtime Enable/disable/mask unit files temporarily until next\n"
" --no-pager Do not pipe output into a pager\n" " reboot\n"
" --no-ask-password\n" " -f --force When enabling unit files, override existing symlinks\n"
" Do not ask for system passwords\n" " When shutting down, execute action immediately\n"
" --global Enable/disable/mask unit files globally\n" " --preset-mode= Apply only enable, only disable, or all presets\n"
" --runtime Enable/disable/mask unit files temporarily until next\n" " --root=PATH Enable/disable/mask unit files in the specified root\n"
" reboot\n" " directory\n"
" -f --force When enabling unit files, override existing symlinks\n" " -n --lines=INTEGER Number of journal entries to show\n"
" When shutting down, execute action immediately\n" " -o --output=STRING Change journal output mode (short, short-precise,\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
@ -8955,73 +9092,76 @@ _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 },
{ "show-environment", VERB_ANY, 1, VERB_ONLINE_ONLY, show_environment }, { "log-level", VERB_ANY, 2, 0, log_level },
{ "set-environment", 2, VERB_ANY, VERB_ONLINE_ONLY, set_environment }, { "log-target", VERB_ANY, 2, 0, log_target },
{ "unset-environment", 2, VERB_ANY, VERB_ONLINE_ONLY, set_environment }, { "service-watchdogs", VERB_ANY, 2, 0, service_watchdogs },
{ "import-environment", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, import_environment }, { "show-environment", VERB_ANY, 1, VERB_ONLINE_ONLY, show_environment },
{ "halt", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, { "set-environment", 2, VERB_ANY, VERB_ONLINE_ONLY, set_environment },
{ "poweroff", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, { "unset-environment", 2, VERB_ANY, VERB_ONLINE_ONLY, set_environment },
{ "reboot", VERB_ANY, 2, VERB_ONLINE_ONLY, start_system_special }, { "import-environment", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, import_environment },
{ "kexec", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, { "halt", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
{ "suspend", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, { "poweroff", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
{ "hibernate", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, { "reboot", VERB_ANY, 2, VERB_ONLINE_ONLY, start_system_special },
{ "hybrid-sleep", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, { "kexec", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
{ "suspend-then-hibernate",VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, { "suspend", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
{ "default", VERB_ANY, 1, VERB_ONLINE_ONLY, start_special }, { "hibernate", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
{ "rescue", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, { "hybrid-sleep", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
{ "emergency", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, { "suspend-then-hibernate",VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
{ "exit", VERB_ANY, 2, VERB_ONLINE_ONLY, start_special }, { "default", VERB_ANY, 1, VERB_ONLINE_ONLY, start_special },
{ "reset-failed", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, reset_failed }, { "rescue", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
{ "enable", 2, VERB_ANY, 0, enable_unit }, { "emergency", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
{ "disable", 2, VERB_ANY, 0, enable_unit }, { "exit", VERB_ANY, 2, VERB_ONLINE_ONLY, start_special },
{ "is-enabled", 2, VERB_ANY, 0, unit_is_enabled }, { "reset-failed", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, reset_failed },
{ "reenable", 2, VERB_ANY, 0, enable_unit }, { "enable", 2, VERB_ANY, 0, enable_unit },
{ "preset", 2, VERB_ANY, 0, enable_unit }, { "disable", 2, VERB_ANY, 0, enable_unit },
{ "preset-all", VERB_ANY, 1, 0, preset_all }, { "is-enabled", 2, VERB_ANY, 0, unit_is_enabled },
{ "mask", 2, VERB_ANY, 0, enable_unit }, { "reenable", 2, VERB_ANY, 0, enable_unit },
{ "unmask", 2, VERB_ANY, 0, enable_unit }, { "preset", 2, VERB_ANY, 0, enable_unit },
{ "link", 2, VERB_ANY, 0, enable_unit }, { "preset-all", VERB_ANY, 1, 0, preset_all },
{ "revert", 2, VERB_ANY, 0, enable_unit }, { "mask", 2, VERB_ANY, 0, enable_unit },
{ "switch-root", 2, VERB_ANY, VERB_ONLINE_ONLY, switch_root }, { "unmask", 2, VERB_ANY, 0, enable_unit },
{ "list-dependencies", VERB_ANY, 2, VERB_ONLINE_ONLY, list_dependencies }, { "link", 2, VERB_ANY, 0, enable_unit },
{ "set-default", 2, 2, 0, set_default }, { "revert", 2, VERB_ANY, 0, enable_unit },
{ "get-default", VERB_ANY, 1, 0, get_default }, { "switch-root", 2, VERB_ANY, VERB_ONLINE_ONLY, switch_root },
{ "set-property", 3, VERB_ANY, VERB_ONLINE_ONLY, set_property }, { "list-dependencies", VERB_ANY, 2, VERB_ONLINE_ONLY, list_dependencies },
{ "is-system-running", VERB_ANY, 1, 0, is_system_running }, { "set-default", 2, 2, 0, set_default },
{ "add-wants", 3, VERB_ANY, 0, add_dependency }, { "get-default", VERB_ANY, 1, 0, get_default },
{ "add-requires", 3, VERB_ANY, 0, add_dependency }, { "set-property", 3, VERB_ANY, VERB_ONLINE_ONLY, set_property },
{ "edit", 2, VERB_ANY, VERB_ONLINE_ONLY, edit }, { "is-system-running", VERB_ANY, 1, 0, is_system_running },
{ "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,7 +3,6 @@ Description=Test for ReadOnlyPaths=
[Service] [Service]
ReadOnlyPaths=/etc -/i-dont-exist /usr ReadOnlyPaths=/etc -/i-dont-exist /usr
# From 6c47cd7d3bf35c8158a0737f34fe2c5dc95e72d6, RuntimeDirectory= implies BindPaths=. BindPaths=/etc:/tmp/etc2
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