Compare commits

..

16 Commits

Author SHA1 Message Date
Zbigniew Jędrzejewski-Szmek a7ddeea15d
Merge pull request #17067 from keszybz/rc-local-path
Expose the path to rc.local in the man page
2020-09-16 22:59:53 +02:00
Lennart Poettering eb5e26112e
Merge pull request #17076 from poettering/dissect-cleanup
minor cleanups to the dissector code
2020-09-16 18:42:12 +02:00
Topi Miettinen f593965161 test-execute: kill Waldo and Quux
Retire /var/lib{,/private}/{quux,waldo} after they have served their purpose.
2020-09-17 00:06:02 +09:00
Yu Watanabe 6234712ec6
Merge pull request #17066 from keszybz/allow-loopback-addresses
Allow loopback addresses
2020-09-17 00:02:08 +09:00
Lennart Poettering c796b91d2b
Merge pull request #16675 from topimiettinen/exec-syscall-error-action
SystemCallFilter, SystemCallErrorAction error actions kill and log
2020-09-16 17:01:44 +02:00
Zbigniew Jędrzejewski-Szmek c882b71457 man: reorder autogenerated dbus api lists
3e5f04bf64 was trying to do the right thing, but
the resulting list does not match the autogenerated order (which is the same as
the order in vtable definition). I assume the addition was done manually. Fix
the order so that dbus-docs-fresh test is not unhappy.
2020-09-17 00:01:20 +09:00
Lennart Poettering aa088f62d1 gpt: move GPT_LINUX_GENERIC definition next to the user GPT partition types
No code changes, just some reordering.
2020-09-16 16:31:16 +02:00
Lennart Poettering 569a0e42ec dissect: introduce PartitionDesignator as real type 2020-09-16 16:14:01 +02:00
Lennart Poettering f5215bc8d3 dissect: rename mount_options_from_part() → mount_options_from_designator()
After all, it actually takes a designator argument, not a partition
index or so.
2020-09-15 22:23:22 +02:00
Zbigniew Jędrzejewski-Szmek c2ee27a5e7 man: substitute path to rc.local in the man page
Different systems use different paths for it and users are confused when the
man page has a path different than the one on the local system.

https://bugzilla.redhat.com/show_bug.cgi?id=1876905
2020-09-15 17:57:28 +02:00
Lennart Poettering 80dd1125c8 test: remove test-dissect-image
It does pretty much exactly what systemd-dissect does and is a manual
test, hence let's remove it as redundant code.
2020-09-15 17:53:32 +02:00
Zbigniew Jędrzejewski-Szmek 452d2dfd52 meson: RC_LOCAL_SCRIPT_PATH_START to RC_LOCAL_PATH
RC_LOCAL_SCRIPT_PATH_START and RC_LOCAL_SCRIPT_PATH_STOP were was originally
added in the conversion to meson based on the autotools name. In
4450894653 RC_LOCAL_SCRIPT_PATH_STOP was dropped.
We don't need to use such a long name.
2020-09-15 17:44:26 +02:00
Zbigniew Jędrzejewski-Szmek 7e5f1d4b3f socket-proxy: allow localhost addresses
With this change, only manager_connect() in timesync.d uses AI_ADDRCONFIG. There
we are connecting to a remove server, so the flag is appropriate.
2020-09-15 16:45:39 +02:00
Zbigniew Jędrzejewski-Szmek d0e5db44d9 sd-bus: allow localhost addresses
By settings AI_ADDRCONFIG in hints we cannot for example resolve "localhost"
when the local machine only has a loopback interface. This seems like an
unnecessary restriction, drop it.

Inspired by https://bugzilla.redhat.com/show_bug.cgi?id=1839007.
2020-09-15 16:45:03 +02:00
Topi Miettinen 9df2cdd8ec exec: SystemCallLog= directive
With new directive SystemCallLog= it's possible to list system calls to be
logged. This can be used for auditing or temporarily when constructing system
call filters.

---
v5: drop intermediary, update HASHMAP_FOREACH_KEY() use
v4: skip useless debug messages, actually parse directive
v3: don't declare unused variables with old libseccomp
v2: fix build without seccomp or old libseccomp
2020-09-15 12:54:17 +03:00
Topi Miettinen 005bfaf118 exec: Add kill action to system call filters
Define explicit action "kill" for SystemCallErrorNumber=.

In addition to errno code, allow specifying "kill" as action for
SystemCallFilter=.

---
v7: seccomp_parse_errno_or_action() returns -EINVAL if !HAVE_SECCOMP
v6: use streq_ptr(), let errno_to_name() handle bad values, kill processes,
 init syscall_errno
v5: actually use seccomp_errno_or_action_to_string(), don't fail bus unit
parsing without seccomp
v4: fix build without seccomp
v3: drop log action
v2: action -> number
2020-09-15 12:54:17 +03:00
34 changed files with 461 additions and 158 deletions

3
TODO
View File

@ -561,6 +561,9 @@ Features:
* sd-bus: add vtable flag, that may be used to request client creds implicitly * sd-bus: add vtable flag, that may be used to request client creds implicitly
and asynchronously before dispatching the operation and asynchronously before dispatching the operation
* sd-bus: parse addresses given in sd_bus_set_addresses immediately and not
only when used. Add unit tests.
* make use of ethtool veth peer info in machined, for automatically finding out * make use of ethtool veth peer info in machined, for automatically finding out
host-side interface pointing to the container. host-side interface pointing to the container.

View File

@ -156,6 +156,7 @@ All execution-related settings are available for transient units.
✓ SystemCallFilter= ✓ SystemCallFilter=
✓ SystemCallArchitectures= ✓ SystemCallArchitectures=
✓ SystemCallErrorNumber= ✓ SystemCallErrorNumber=
✓ SystemCallLog=
✓ MemoryDenyWriteExecute= ✓ MemoryDenyWriteExecute=
✓ RestrictNamespaces= ✓ RestrictNamespaces=
✓ RestrictRealtime= ✓ RestrictRealtime=

View File

@ -10,3 +10,4 @@
<!ENTITY MEMORY_ACCOUNTING_DEFAULT @MEMORY_ACCOUNTING_DEFAULT_YES_NO@> <!ENTITY MEMORY_ACCOUNTING_DEFAULT @MEMORY_ACCOUNTING_DEFAULT_YES_NO@>
<!ENTITY KILL_USER_PROCESSES @KILL_USER_PROCESSES_YES_NO@> <!ENTITY KILL_USER_PROCESSES @KILL_USER_PROCESSES_YES_NO@>
<!ENTITY DEBUGTTY @DEBUGTTY@> <!ENTITY DEBUGTTY @DEBUGTTY@>
<!ENTITY RC_LOCAL_PATH @RC_LOCAL_PATH@>

View File

@ -123,7 +123,7 @@ node /org/freedesktop/LogControl1 {
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>, <citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry project='man-pages'><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry> <citerefentry project="man-pages"><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para> </para>
</refsect1> </refsect1>
</refentry> </refentry>

View File

@ -3904,6 +3904,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b Accept = ...; readonly b Accept = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b FlushPending = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b Writable = ...; readonly b Writable = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b KeepAlive = ...; readonly b KeepAlive = ...;
@ -3976,8 +3978,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false") @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u NRefused = ...; readonly u NRefused = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false") @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u FlushPending = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s FileDescriptorName = '...'; readonly s FileDescriptorName = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SocketProtocol = ...; readonly i SocketProtocol = ...;
@ -4985,6 +4985,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<variablelist class="dbus-property" generated="True" extra-ref="Accept"/> <variablelist class="dbus-property" generated="True" extra-ref="Accept"/>
<variablelist class="dbus-property" generated="True" extra-ref="FlushPending"/>
<variablelist class="dbus-property" generated="True" extra-ref="Writable"/> <variablelist class="dbus-property" generated="True" extra-ref="Writable"/>
<variablelist class="dbus-property" generated="True" extra-ref="KeepAlive"/> <variablelist class="dbus-property" generated="True" extra-ref="KeepAlive"/>
@ -5059,8 +5061,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<variablelist class="dbus-property" generated="True" extra-ref="NRefused"/> <variablelist class="dbus-property" generated="True" extra-ref="NRefused"/>
<variablelist class="dbus-property" generated="True" extra-ref="FlushPending"/>
<variablelist class="dbus-property" generated="True" extra-ref="FileDescriptorName"/> <variablelist class="dbus-property" generated="True" extra-ref="FileDescriptorName"/>
<variablelist class="dbus-property" generated="True" extra-ref="SocketProtocol"/> <variablelist class="dbus-property" generated="True" extra-ref="SocketProtocol"/>

View File

@ -1,8 +1,11 @@
<?xml version="1.0"?> <?xml version='1.0'?>
<!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
<!ENTITY % entities SYSTEM "custom-entities.ent" >
%entities;
]>
<!-- SPDX-License-Identifier: LGPL-2.1+ --> <!-- SPDX-License-Identifier: LGPL-2.1+ -->
<refentry id="systemd-rc-local-generator" conditional='HAVE_SYSV_COMPAT'> <refentry id="systemd-rc-local-generator" conditional='HAVE_SYSV_COMPAT'>
<refentryinfo> <refentryinfo>
<title>systemd-rc-local-generator</title> <title>systemd-rc-local-generator</title>
@ -16,7 +19,7 @@
<refnamediv> <refnamediv>
<refname>systemd-rc-local-generator</refname> <refname>systemd-rc-local-generator</refname>
<refpurpose>Compatibility generator for starting <filename>/etc/rc.local</filename> during boot</refpurpose> <refpurpose>Compatibility generator for starting <filename>&RC_LOCAL_PATH;</filename> during boot</refpurpose>
</refnamediv> </refnamediv>
<refsynopsisdiv> <refsynopsisdiv>
@ -27,17 +30,17 @@
<title>Description</title> <title>Description</title>
<para><filename>systemd-rc-local-generator</filename> is a generator that checks whether <para><filename>systemd-rc-local-generator</filename> is a generator that checks whether
<filename>/etc/rc.local</filename> exists and is executable, and if it is pulls the <filename>&RC_LOCAL_PATH;</filename> exists and is executable, and if it is pulls the
<filename>rc-local.service</filename> unit into the boot process. This unit is responsible for running this script <filename>rc-local.service</filename> unit into the boot process. This unit is responsible for running
during late boot. Note that the script will be run with slightly different semantics than the original System V this script during late boot. Note that the script will be run with slightly different semantics than the
version, which was run "last" in the boot process, which is a concept that does not translate to systemd. The original System V version, which was run "last" in the boot process, which is a concept that does not
script is run after <filename>network.target</filename>, but in parallel with most other regular system translate to systemd. The script is run after <filename>network.target</filename>, but in parallel with
services.</para> most other regular system services.</para>
<para>Support for <filename>/etc/rc.local</filename> is provided <para>Support for <filename>&RC_LOCAL_PATH;</filename> is provided for compatibility with specific System
for compatibility with specific System V systems only. However, it is strongly recommended to avoid making use of V systems only. However, it is strongly recommended to avoid making use of this script today, and instead
this script today, and instead provide proper unit files with appropriate dependencies for any scripts to run provide proper unit files with appropriate dependencies for any scripts to run during the boot process.
during the boot process.</para> Note that the path to the script is set a compile time and varies between distributions.</para>
<para><filename>systemd-rc-local-generator</filename> implements <para><filename>systemd-rc-local-generator</filename> implements
<citerefentry><refentrytitle>systemd.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para> <citerefentry><refentrytitle>systemd.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>

View File

@ -1888,7 +1888,8 @@ RestrictNamespaces=~cgroup net</programlisting>
<constant>EACCES</constant> or <constant>EUCLEAN</constant> (see <citerefentry <constant>EACCES</constant> or <constant>EUCLEAN</constant> (see <citerefentry
project='man-pages'><refentrytitle>errno</refentrytitle><manvolnum>3</manvolnum></citerefentry> for a project='man-pages'><refentrytitle>errno</refentrytitle><manvolnum>3</manvolnum></citerefentry> for a
full list). This value will be returned when a deny-listed system call is triggered, instead of full list). This value will be returned when a deny-listed system call is triggered, instead of
terminating the processes immediately. This value takes precedence over the one given in terminating the processes immediately. Special setting <literal>kill</literal> can be used to
explicitly specify killing. This value takes precedence over the one given in
<varname>SystemCallErrorNumber=</varname>, see below. If running in user mode, or in system mode, <varname>SystemCallErrorNumber=</varname>, see below. If running in user mode, or in system mode,
but without the <constant>CAP_SYS_ADMIN</constant> capability (e.g. setting but without the <constant>CAP_SYS_ADMIN</constant> capability (e.g. setting
<varname>User=nobody</varname>), <varname>NoNewPrivileges=yes</varname> is implied. This feature <varname>User=nobody</varname>), <varname>NoNewPrivileges=yes</varname> is implied. This feature
@ -2098,8 +2099,9 @@ SystemCallErrorNumber=EPERM</programlisting>
return when the system call filter configured with <varname>SystemCallFilter=</varname> is triggered, return when the system call filter configured with <varname>SystemCallFilter=</varname> is triggered,
instead of terminating the process immediately. See <citerefentry instead of terminating the process immediately. See <citerefentry
project='man-pages'><refentrytitle>errno</refentrytitle><manvolnum>3</manvolnum></citerefentry> for a project='man-pages'><refentrytitle>errno</refentrytitle><manvolnum>3</manvolnum></citerefentry> for a
full list of error codes. When this setting is not used, or when the empty string is assigned, the full list of error codes. When this setting is not used, or when the empty string or the special
process will be terminated immediately when the filter is triggered.</para></listitem> setting <literal>kill</literal> is assigned, the process will be terminated immediately when the
filter is triggered.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
@ -2134,6 +2136,21 @@ SystemCallErrorNumber=EPERM</programlisting>
details.</para></listitem> details.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>SystemCallLog=</varname></term>
<listitem><para>Takes a space-separated list of system call names. If this setting is used, all
system calls executed by the unit processes for the listed ones will be logged. If the first
character of the list is <literal>~</literal>, the effect is inverted: all system calls except the
listed system calls will be logged. If running in user mode, or in system mode, but without the
<constant>CAP_SYS_ADMIN</constant> capability (e.g. setting <varname>User=nobody</varname>),
<varname>NoNewPrivileges=yes</varname> is implied. This feature makes use of the Secure Computing
Mode 2 interfaces of the kernel ('seccomp filtering') and is useful for auditing or setting up a
minimal sandboxing environment. This option may be specified more than once, in which case the filter
masks are merged. If the empty string is assigned, the filter is reset, all prior assignments will
have no effect. This does not affect commands prefixed with <literal>+</literal>.</para></listitem>
</varlistentry>
</variablelist> </variablelist>
</refsect1> </refsect1>

View File

@ -212,7 +212,7 @@ conf.set_quoted('SYSTEM_CONFIG_UNIT_DIR', join_paths(pkgsysc
conf.set_quoted('SYSTEM_DATA_UNIT_PATH', systemunitdir) conf.set_quoted('SYSTEM_DATA_UNIT_PATH', systemunitdir)
conf.set_quoted('SYSTEM_SYSVINIT_PATH', sysvinit_path) conf.set_quoted('SYSTEM_SYSVINIT_PATH', sysvinit_path)
conf.set_quoted('SYSTEM_SYSVRCND_PATH', sysvrcnd_path) conf.set_quoted('SYSTEM_SYSVRCND_PATH', sysvrcnd_path)
conf.set_quoted('RC_LOCAL_SCRIPT_PATH_START', get_option('rc-local')) conf.set_quoted('RC_LOCAL_PATH', get_option('rc-local'))
conf.set('ANSI_OK_COLOR', 'ANSI_' + get_option('ok-color').underscorify().to_upper()) conf.set('ANSI_OK_COLOR', 'ANSI_' + get_option('ok-color').underscorify().to_upper())
@ -299,7 +299,7 @@ substs.set('CERTIFICATEROOT', get_option('certif
substs.set('RANDOM_SEED', join_paths(randomseeddir, 'random-seed')) substs.set('RANDOM_SEED', join_paths(randomseeddir, 'random-seed'))
substs.set('SYSTEM_SYSVINIT_PATH', sysvinit_path) substs.set('SYSTEM_SYSVINIT_PATH', sysvinit_path)
substs.set('SYSTEM_SYSVRCND_PATH', sysvrcnd_path) substs.set('SYSTEM_SYSVRCND_PATH', sysvrcnd_path)
substs.set('RC_LOCAL_SCRIPT_PATH_START', get_option('rc-local')) substs.set('RC_LOCAL_PATH', get_option('rc-local'))
substs.set('MEMORY_ACCOUNTING_DEFAULT', memory_accounting_default ? 'yes' : 'no') substs.set('MEMORY_ACCOUNTING_DEFAULT', memory_accounting_default ? 'yes' : 'no')
substs.set('STATUS_UNIT_FORMAT_DEFAULT', status_unit_format_default) substs.set('STATUS_UNIT_FORMAT_DEFAULT', status_unit_format_default)
substs.set('HIGH_RLIMIT_NOFILE', conf.get('HIGH_RLIMIT_NOFILE')) substs.set('HIGH_RLIMIT_NOFILE', conf.get('HIGH_RLIMIT_NOFILE'))

View File

@ -16,6 +16,9 @@
#include "missing_network.h" #include "missing_network.h"
#include "parse-util.h" #include "parse-util.h"
#include "process-util.h" #include "process-util.h"
#if HAVE_SECCOMP
#include "seccomp-util.h"
#endif
#include "stat-util.h" #include "stat-util.h"
#include "string-util.h" #include "string-util.h"
#include "strv.h" #include "strv.h"
@ -314,6 +317,7 @@ int parse_errno(const char *t) {
return e; return e;
} }
#if HAVE_SECCOMP
int parse_syscall_and_errno(const char *in, char **name, int *error) { int parse_syscall_and_errno(const char *in, char **name, int *error) {
_cleanup_free_ char *n = NULL; _cleanup_free_ char *n = NULL;
char *p; char *p;
@ -332,7 +336,7 @@ int parse_syscall_and_errno(const char *in, char **name, int *error) {
p = strchr(in, ':'); p = strchr(in, ':');
if (p) { if (p) {
e = parse_errno(p + 1); e = seccomp_parse_errno_or_action(p + 1);
if (e < 0) if (e < 0)
return e; return e;
@ -351,6 +355,7 @@ int parse_syscall_and_errno(const char *in, char **name, int *error) {
return 0; return 0;
} }
#endif
static const char *mangle_base(const char *s, unsigned *base) { static const char *mangle_base(const char *s, unsigned *base) {
const char *k; const char *k;

View File

@ -19,7 +19,9 @@ int parse_mtu(int family, const char *s, uint32_t *ret);
int parse_size(const char *t, uint64_t base, uint64_t *size); int parse_size(const char *t, uint64_t base, uint64_t *size);
int parse_range(const char *t, unsigned *lower, unsigned *upper); int parse_range(const char *t, unsigned *lower, unsigned *upper);
int parse_errno(const char *t); int parse_errno(const char *t);
#if HAVE_SECCOMP
int parse_syscall_and_errno(const char *in, char **name, int *error); int parse_syscall_and_errno(const char *in, char **name, int *error);
#endif
#define SAFE_ATO_REFUSE_PLUS_MINUS (1U << 30) #define SAFE_ATO_REFUSE_PLUS_MINUS (1U << 30)
#define SAFE_ATO_REFUSE_LEADING_ZERO (1U << 29) #define SAFE_ATO_REFUSE_LEADING_ZERO (1U << 29)

View File

@ -387,7 +387,7 @@ static int property_get_syscall_filter(
continue; continue;
if (num >= 0) { if (num >= 0) {
e = errno_to_name(num); e = seccomp_errno_or_action_to_string(num);
if (e) { if (e) {
s = strjoin(name, ":", e); s = strjoin(name, ":", e);
if (!s) if (!s)
@ -415,6 +415,58 @@ static int property_get_syscall_filter(
return sd_bus_message_close_container(reply); return sd_bus_message_close_container(reply);
} }
static int property_get_syscall_log(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
ExecContext *c = userdata;
_cleanup_strv_free_ char **l = NULL;
int r;
#if HAVE_SECCOMP
void *id, *val;
#endif
assert(bus);
assert(reply);
assert(c);
r = sd_bus_message_open_container(reply, 'r', "bas");
if (r < 0)
return r;
r = sd_bus_message_append(reply, "b", c->syscall_log_allow_list);
if (r < 0)
return r;
#if HAVE_SECCOMP
HASHMAP_FOREACH_KEY(val, id, c->syscall_log) {
char *name = NULL;
name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
if (!name)
continue;
r = strv_consume(&l, name);
if (r < 0)
return r;
}
#endif
strv_sort(l);
r = sd_bus_message_append_strv(reply, l);
if (r < 0)
return r;
return sd_bus_message_close_container(reply);
}
static int property_get_syscall_archs( static int property_get_syscall_archs(
sd_bus *bus, sd_bus *bus,
const char *path, const char *path,
@ -1068,6 +1120,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SystemCallErrorNumber", "i", bus_property_get_int, offsetof(ExecContext, syscall_errno), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SystemCallErrorNumber", "i", bus_property_get_int, offsetof(ExecContext, syscall_errno), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SystemCallLog", "(bas)", property_get_syscall_log, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Personality", "s", property_get_personality, offsetof(ExecContext, personality), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Personality", "s", property_get_personality, offsetof(ExecContext, personality), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("LockPersonality", "b", bus_property_get_bool, offsetof(ExecContext, lock_personality), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LockPersonality", "b", bus_property_get_bool, offsetof(ExecContext, lock_personality), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST),
@ -1424,7 +1477,7 @@ static const char* mount_propagation_flags_to_string_with_check(unsigned long n)
static BUS_DEFINE_SET_TRANSIENT(nsec, "t", uint64_t, nsec_t, NSEC_FMT); static BUS_DEFINE_SET_TRANSIENT(nsec, "t", uint64_t, nsec_t, NSEC_FMT);
static BUS_DEFINE_SET_TRANSIENT_IS_VALID(log_level, "i", int32_t, int, "%" PRIi32, log_level_is_valid); static BUS_DEFINE_SET_TRANSIENT_IS_VALID(log_level, "i", int32_t, int, "%" PRIi32, log_level_is_valid);
#if HAVE_SECCOMP #if HAVE_SECCOMP
static BUS_DEFINE_SET_TRANSIENT_IS_VALID(errno, "i", int32_t, int, "%" PRIi32, errno_is_valid); static BUS_DEFINE_SET_TRANSIENT_IS_VALID(errno, "i", int32_t, int, "%" PRIi32, seccomp_errno_or_action_is_valid);
#endif #endif
static BUS_DEFINE_SET_TRANSIENT_PARSE(std_input, ExecInput, exec_input_from_string); static BUS_DEFINE_SET_TRANSIENT_PARSE(std_input, ExecInput, exec_input_from_string);
static BUS_DEFINE_SET_TRANSIENT_PARSE(std_output, ExecOutput, exec_output_from_string); static BUS_DEFINE_SET_TRANSIENT_PARSE(std_output, ExecOutput, exec_output_from_string);
@ -1460,7 +1513,7 @@ static int read_mount_options(sd_bus_message *message, sd_bus_error *error, Moun
while ((r = sd_bus_message_read(message, "(ss)", &partition, &mount_options)) > 0) { while ((r = sd_bus_message_read(message, "(ss)", &partition, &mount_options)) > 0) {
_cleanup_free_ char *previous = NULL, *escaped = NULL; _cleanup_free_ char *previous = NULL, *escaped = NULL;
_cleanup_free_ MountOptions *o = NULL; _cleanup_free_ MountOptions *o = NULL;
int partition_designator; PartitionDesignator partition_designator;
if (chars_intersect(mount_options, WHITESPACE)) if (chars_intersect(mount_options, WHITESPACE))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
@ -2230,6 +2283,76 @@ int bus_exec_context_set_transient_property(
return 1; return 1;
} else if (streq(name, "SystemCallLog")) {
int allow_list;
_cleanup_strv_free_ char **l = NULL;
r = sd_bus_message_enter_container(message, 'r', "bas");
if (r < 0)
return r;
r = sd_bus_message_read(message, "b", &allow_list);
if (r < 0)
return r;
r = sd_bus_message_read_strv(message, &l);
if (r < 0)
return r;
r = sd_bus_message_exit_container(message);
if (r < 0)
return r;
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *joined = NULL;
SeccompParseFlags invert_flag = allow_list ? 0 : SECCOMP_PARSE_INVERT;
char **s;
if (strv_isempty(l)) {
c->syscall_log_allow_list = false;
c->syscall_log = hashmap_free(c->syscall_log);
unit_write_settingf(u, flags, name, "SystemCallLog=");
return 1;
}
if (!c->syscall_log) {
c->syscall_log = hashmap_new(NULL);
if (!c->syscall_log)
return log_oom();
c->syscall_log_allow_list = allow_list;
}
STRV_FOREACH(s, l) {
_cleanup_free_ char *n = NULL;
int e;
r = parse_syscall_and_errno(*s, &n, &e);
if (r < 0)
return r;
r = seccomp_parse_syscall_filter(n,
0, /* errno not used */
c->syscall_log,
SECCOMP_PARSE_LOG | SECCOMP_PARSE_PERMISSIVE |
invert_flag |
(c->syscall_log_allow_list ? SECCOMP_PARSE_ALLOW_LIST : 0),
u->id,
NULL, 0);
if (r < 0)
return r;
}
joined = strv_join(l, " ");
if (!joined)
return -ENOMEM;
unit_write_settingf(u, flags, name, "SystemCallLog=%s%s", allow_list ? "" : "~", joined);
}
return 1;
} else if (streq(name, "SystemCallArchitectures")) { } else if (streq(name, "SystemCallArchitectures")) {
_cleanup_strv_free_ char **l = NULL; _cleanup_strv_free_ char **l = NULL;

View File

@ -1407,6 +1407,13 @@ static bool context_has_syscall_filters(const ExecContext *c) {
!hashmap_isempty(c->syscall_filter); !hashmap_isempty(c->syscall_filter);
} }
static bool context_has_syscall_logs(const ExecContext *c) {
assert(c);
return c->syscall_log_allow_list ||
!hashmap_isempty(c->syscall_log);
}
static bool context_has_no_new_privileges(const ExecContext *c) { static bool context_has_no_new_privileges(const ExecContext *c) {
assert(c); assert(c);
@ -1428,6 +1435,7 @@ static bool context_has_no_new_privileges(const ExecContext *c) {
c->protect_kernel_logs || c->protect_kernel_logs ||
c->private_devices || c->private_devices ||
context_has_syscall_filters(c) || context_has_syscall_filters(c) ||
context_has_syscall_logs(c) ||
!set_isempty(c->syscall_archs) || !set_isempty(c->syscall_archs) ||
c->lock_personality || c->lock_personality ||
c->protect_hostname; c->protect_hostname;
@ -1465,7 +1473,7 @@ static int apply_syscall_filter(const Unit* u, const ExecContext *c, bool needs_
if (skip_seccomp_unavailable(u, "SystemCallFilter=")) if (skip_seccomp_unavailable(u, "SystemCallFilter="))
return 0; return 0;
negative_action = c->syscall_errno == 0 ? scmp_act_kill_process() : SCMP_ACT_ERRNO(c->syscall_errno); negative_action = c->syscall_errno == SECCOMP_ERROR_NUMBER_KILL ? scmp_act_kill_process() : SCMP_ACT_ERRNO(c->syscall_errno);
if (c->syscall_allow_list) { if (c->syscall_allow_list) {
default_action = negative_action; default_action = negative_action;
@ -1484,6 +1492,39 @@ static int apply_syscall_filter(const Unit* u, const ExecContext *c, bool needs_
return seccomp_load_syscall_filter_set_raw(default_action, c->syscall_filter, action, false); return seccomp_load_syscall_filter_set_raw(default_action, c->syscall_filter, action, false);
} }
static int apply_syscall_log(const Unit* u, const ExecContext *c) {
#ifdef SCMP_ACT_LOG
uint32_t default_action, action;
#endif
assert(u);
assert(c);
if (!context_has_syscall_logs(c))
return 0;
#ifdef SCMP_ACT_LOG
if (skip_seccomp_unavailable(u, "SystemCallLog="))
return 0;
if (c->syscall_log_allow_list) {
/* Log nothing but the ones listed */
default_action = SCMP_ACT_ALLOW;
action = SCMP_ACT_LOG;
} else {
/* Log everything but the ones listed */
default_action = SCMP_ACT_LOG;
action = SCMP_ACT_ALLOW;
}
return seccomp_load_syscall_filter_set_raw(default_action, c->syscall_log, action, false);
#else
/* old libseccomp */
log_unit_debug(u, "SECCOMP feature SCMP_ACT_LOG not available, skipping SystemCallLog=");
return 0;
#endif
}
static int apply_syscall_archs(const Unit *u, const ExecContext *c) { static int apply_syscall_archs(const Unit *u, const ExecContext *c) {
assert(u); assert(u);
assert(c); assert(c);
@ -4438,6 +4479,12 @@ static int exec_child(
return log_unit_error_errno(unit, r, "Failed to lock personalities: %m"); return log_unit_error_errno(unit, r, "Failed to lock personalities: %m");
} }
r = apply_syscall_log(unit, context);
if (r < 0) {
*exit_status = EXIT_SECCOMP;
return log_unit_error_errno(unit, r, "Failed to apply system call log filters: %m");
}
/* This really should remain the last step before the execve(), to make sure our own code is unaffected /* This really should remain the last step before the execve(), to make sure our own code is unaffected
* by the filter as little as possible. */ * by the filter as little as possible. */
r = apply_syscall_filter(unit, context, needs_ambient_hack); r = apply_syscall_filter(unit, context, needs_ambient_hack);
@ -4675,6 +4722,9 @@ void exec_context_init(ExecContext *c) {
assert_cc(NAMESPACE_FLAGS_INITIAL != NAMESPACE_FLAGS_ALL); assert_cc(NAMESPACE_FLAGS_INITIAL != NAMESPACE_FLAGS_ALL);
c->restrict_namespaces = NAMESPACE_FLAGS_INITIAL; c->restrict_namespaces = NAMESPACE_FLAGS_INITIAL;
c->log_level_max = -1; c->log_level_max = -1;
#if HAVE_SECCOMP
c->syscall_errno = SECCOMP_ERROR_NUMBER_KILL;
#endif
numa_policy_reset(&c->numa_policy); numa_policy_reset(&c->numa_policy);
} }
@ -5474,7 +5524,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
fputs(strna(name), f); fputs(strna(name), f);
if (num >= 0) { if (num >= 0) {
errno_name = errno_to_name(num); errno_name = seccomp_errno_or_action_to_string(num);
if (errno_name) if (errno_name)
fprintf(f, ":%s", errno_name); fprintf(f, ":%s", errno_name);
else else
@ -5517,15 +5567,20 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
prefix, c->network_namespace_path); prefix, c->network_namespace_path);
if (c->syscall_errno > 0) { if (c->syscall_errno > 0) {
#if HAVE_SECCOMP
const char *errno_name; const char *errno_name;
#endif
fprintf(f, "%sSystemCallErrorNumber: ", prefix); fprintf(f, "%sSystemCallErrorNumber: ", prefix);
errno_name = errno_to_name(c->syscall_errno); #if HAVE_SECCOMP
errno_name = seccomp_errno_or_action_to_string(c->syscall_errno);
if (errno_name) if (errno_name)
fprintf(f, "%s\n", errno_name); fputs(errno_name, f);
else else
fprintf(f, "%d\n", c->syscall_errno); fprintf(f, "%d", c->syscall_errno);
#endif
fputc('\n', f);
} }
for (size_t i = 0; i < c->n_mount_images; i++) { for (size_t i = 0; i < c->n_mount_images; i++) {

View File

@ -302,6 +302,9 @@ struct ExecContext {
int syscall_errno; int syscall_errno;
bool syscall_allow_list:1; bool syscall_allow_list:1;
Hashmap *syscall_log;
bool syscall_log_allow_list:1; /* Log listed system calls */
bool address_families_allow_list:1; bool address_families_allow_list:1;
Set *address_families; Set *address_families;

View File

@ -79,6 +79,7 @@ m4_ifdef(`HAVE_SECCOMP',
`$1.SystemCallFilter, config_parse_syscall_filter, 0, offsetof($1, exec_context) `$1.SystemCallFilter, config_parse_syscall_filter, 0, offsetof($1, exec_context)
$1.SystemCallArchitectures, config_parse_syscall_archs, 0, offsetof($1, exec_context.syscall_archs) $1.SystemCallArchitectures, config_parse_syscall_archs, 0, offsetof($1, exec_context.syscall_archs)
$1.SystemCallErrorNumber, config_parse_syscall_errno, 0, offsetof($1, exec_context) $1.SystemCallErrorNumber, config_parse_syscall_errno, 0, offsetof($1, exec_context)
$1.SystemCallLog, config_parse_syscall_log, 0, offsetof($1, exec_context)
$1.MemoryDenyWriteExecute, config_parse_bool, 0, offsetof($1, exec_context.memory_deny_write_execute) $1.MemoryDenyWriteExecute, config_parse_bool, 0, offsetof($1, exec_context.memory_deny_write_execute)
$1.RestrictNamespaces, config_parse_restrict_namespaces, 0, offsetof($1, exec_context) $1.RestrictNamespaces, config_parse_restrict_namespaces, 0, offsetof($1, exec_context)
$1.RestrictRealtime, config_parse_bool, 0, offsetof($1, exec_context.restrict_realtime) $1.RestrictRealtime, config_parse_bool, 0, offsetof($1, exec_context.restrict_realtime)
@ -88,6 +89,7 @@ $1.LockPersonality, config_parse_bool, 0,
`$1.SystemCallFilter, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 `$1.SystemCallFilter, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
$1.SystemCallArchitectures, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 $1.SystemCallArchitectures, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
$1.SystemCallErrorNumber, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 $1.SystemCallErrorNumber, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
$1.SystemCallLog, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
$1.MemoryDenyWriteExecute, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 $1.MemoryDenyWriteExecute, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
$1.RestrictNamespaces, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 $1.RestrictNamespaces, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
$1.RestrictRealtime, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 $1.RestrictRealtime, config_parse_warn_compat, DISABLED_CONFIGURATION, 0

View File

@ -1483,7 +1483,7 @@ int config_parse_root_image_options(
MountOptions *o = NULL; MountOptions *o = NULL;
_cleanup_free_ char *mount_options_resolved = NULL; _cleanup_free_ char *mount_options_resolved = NULL;
const char *mount_options = NULL, *partition = "root"; const char *mount_options = NULL, *partition = "root";
int partition_designator; PartitionDesignator partition_designator;
/* Format is either 'root:foo' or 'foo' (root is implied) */ /* Format is either 'root:foo' or 'foo' (root is implied) */
if (!isempty(*second)) { if (!isempty(*second)) {
@ -3197,6 +3197,86 @@ int config_parse_syscall_filter(
} }
} }
int config_parse_syscall_log(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
ExecContext *c = data;
_unused_ const Unit *u = userdata;
bool invert = false;
const char *p;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(u);
if (isempty(rvalue)) {
/* Empty assignment resets the list */
c->syscall_log = hashmap_free(c->syscall_log);
c->syscall_log_allow_list = false;
return 0;
}
if (rvalue[0] == '~') {
invert = true;
rvalue++;
}
if (!c->syscall_log) {
c->syscall_log = hashmap_new(NULL);
if (!c->syscall_log)
return log_oom();
if (invert)
/* Log everything but the ones listed */
c->syscall_log_allow_list = false;
else
/* Log nothing but the ones listed */
c->syscall_log_allow_list = true;
}
p = rvalue;
for (;;) {
_cleanup_free_ char *word = NULL, *name = NULL;
int num;
r = extract_first_word(&p, &word, NULL, 0);
if (r == 0)
return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
return 0;
}
r = parse_syscall_and_errno(word, &name, &num);
if (r < 0 || num >= 0) { /* errno code not allowed */
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse syscall, ignoring: %s", word);
continue;
}
r = seccomp_parse_syscall_filter(
name, 0, c->syscall_log,
SECCOMP_PARSE_LOG|SECCOMP_PARSE_PERMISSIVE|
(invert ? SECCOMP_PARSE_INVERT : 0)|
(c->syscall_log_allow_list ? SECCOMP_PARSE_ALLOW_LIST : 0),
unit, filename, line);
if (r < 0)
return r;
}
}
int config_parse_syscall_archs( int config_parse_syscall_archs(
const char *unit, const char *unit,
const char *filename, const char *filename,
@ -3264,9 +3344,9 @@ int config_parse_syscall_errno(
assert(lvalue); assert(lvalue);
assert(rvalue); assert(rvalue);
if (isempty(rvalue)) { if (isempty(rvalue) || streq(rvalue, "kill")) {
/* Empty assignment resets to KILL */ /* Empty assignment resets to KILL */
c->syscall_errno = 0; c->syscall_errno = SECCOMP_ERROR_NUMBER_KILL;
return 0; return 0;
} }
@ -4866,7 +4946,7 @@ int config_parse_mount_images(
for (;;) { for (;;) {
_cleanup_free_ char *partition = NULL, *mount_options = NULL, *mount_options_resolved = NULL; _cleanup_free_ char *partition = NULL, *mount_options = NULL, *mount_options_resolved = NULL;
MountOptions *o = NULL; MountOptions *o = NULL;
int partition_designator; PartitionDesignator partition_designator;
r = extract_many_words(&q, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, &partition, &mount_options, NULL); r = extract_many_words(&q, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, &partition, &mount_options, NULL);
if (r == -ENOMEM) if (r == -ENOMEM)
@ -5444,6 +5524,7 @@ void unit_dump_config_items(FILE *f) {
{ config_parse_syscall_filter, "SYSCALLS" }, { config_parse_syscall_filter, "SYSCALLS" },
{ config_parse_syscall_archs, "ARCHS" }, { config_parse_syscall_archs, "ARCHS" },
{ config_parse_syscall_errno, "ERRNO" }, { config_parse_syscall_errno, "ERRNO" },
{ config_parse_syscall_log, "SYSCALLS" },
{ config_parse_address_families, "FAMILIES" }, { config_parse_address_families, "FAMILIES" },
{ config_parse_restrict_namespaces, "NAMESPACES" }, { config_parse_restrict_namespaces, "NAMESPACES" },
#endif #endif

View File

@ -65,6 +65,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_unit_requires_mounts_for);
CONFIG_PARSER_PROTOTYPE(config_parse_syscall_filter); CONFIG_PARSER_PROTOTYPE(config_parse_syscall_filter);
CONFIG_PARSER_PROTOTYPE(config_parse_syscall_archs); CONFIG_PARSER_PROTOTYPE(config_parse_syscall_archs);
CONFIG_PARSER_PROTOTYPE(config_parse_syscall_errno); CONFIG_PARSER_PROTOTYPE(config_parse_syscall_errno);
CONFIG_PARSER_PROTOTYPE(config_parse_syscall_log);
CONFIG_PARSER_PROTOTYPE(config_parse_environ); CONFIG_PARSER_PROTOTYPE(config_parse_environ);
CONFIG_PARSER_PROTOTYPE(config_parse_pass_environ); CONFIG_PARSER_PROTOTYPE(config_parse_pass_environ);
CONFIG_PARSER_PROTOTYPE(config_parse_unset_environ); CONFIG_PARSER_PROTOTYPE(config_parse_unset_environ);

View File

@ -456,7 +456,7 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) {
(void) table_set_empty_string(t, "-"); (void) table_set_empty_string(t, "-");
(void) table_set_align_percent(t, table_get_cell(t, 0, 7), 100); (void) table_set_align_percent(t, table_get_cell(t, 0, 7), 100);
for (unsigned i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) { for (PartitionDesignator i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) {
DissectedPartition *p = m->partitions + i; DissectedPartition *p = m->partitions + i;
if (!p->found) if (!p->found)

View File

@ -782,7 +782,6 @@ static int parse_tcp_address(sd_bus *b, const char **p, char **guid) {
int r; int r;
struct addrinfo *result, hints = { struct addrinfo *result, hints = {
.ai_socktype = SOCK_STREAM, .ai_socktype = SOCK_STREAM,
.ai_flags = AI_ADDRCONFIG,
}; };
assert(b); assert(b);

View File

@ -59,7 +59,7 @@ static int run(const char *dest, const char *dest_early, const char *dest_late)
assert_se(arg_dest = dest); assert_se(arg_dest = dest);
if (check_executable(RC_LOCAL_SCRIPT_PATH_START) >= 0) { if (check_executable(RC_LOCAL_PATH) >= 0) {
log_debug("Automatically adding rc-local.service."); log_debug("Automatically adding rc-local.service.");
r = add_symlink("rc-local.service", "multi-user.target"); r = add_symlink("rc-local.service", "multi-user.target");

View File

@ -30,6 +30,9 @@
#include "path-util.h" #include "path-util.h"
#include "process-util.h" #include "process-util.h"
#include "rlimit-util.h" #include "rlimit-util.h"
#if HAVE_SECCOMP
#include "seccomp-util.h"
#endif
#include "securebits-util.h" #include "securebits-util.h"
#include "signal-util.h" #include "signal-util.h"
#include "socket-util.h" #include "socket-util.h"
@ -107,7 +110,10 @@ DEFINE_BUS_APPEND_PARSE("i", ioprio_class_from_string);
DEFINE_BUS_APPEND_PARSE("i", ip_tos_from_string); DEFINE_BUS_APPEND_PARSE("i", ip_tos_from_string);
DEFINE_BUS_APPEND_PARSE("i", log_facility_unshifted_from_string); DEFINE_BUS_APPEND_PARSE("i", log_facility_unshifted_from_string);
DEFINE_BUS_APPEND_PARSE("i", log_level_from_string); DEFINE_BUS_APPEND_PARSE("i", log_level_from_string);
DEFINE_BUS_APPEND_PARSE("i", parse_errno); #if !HAVE_SECCOMP
static inline int seccomp_parse_errno_or_action(const char *eq) { return -EINVAL; }
#endif
DEFINE_BUS_APPEND_PARSE("i", seccomp_parse_errno_or_action);
DEFINE_BUS_APPEND_PARSE("i", sched_policy_from_string); DEFINE_BUS_APPEND_PARSE("i", sched_policy_from_string);
DEFINE_BUS_APPEND_PARSE("i", secure_bits_from_string); DEFINE_BUS_APPEND_PARSE("i", secure_bits_from_string);
DEFINE_BUS_APPEND_PARSE("i", signal_from_string); DEFINE_BUS_APPEND_PARSE("i", signal_from_string);
@ -927,7 +933,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
return bus_append_parse_nice(m, field, eq); return bus_append_parse_nice(m, field, eq);
if (streq(field, "SystemCallErrorNumber")) if (streq(field, "SystemCallErrorNumber"))
return bus_append_parse_errno(m, field, eq); return bus_append_seccomp_parse_errno_or_action(m, field, eq);
if (streq(field, "IOSchedulingClass")) if (streq(field, "IOSchedulingClass"))
return bus_append_ioprio_class_from_string(m, field, eq); return bus_append_ioprio_class_from_string(m, field, eq);
@ -1293,7 +1299,8 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
} }
if (STR_IN_SET(field, "RestrictAddressFamilies", if (STR_IN_SET(field, "RestrictAddressFamilies",
"SystemCallFilter")) { "SystemCallFilter",
"SystemCallLog")) {
int allow_list = 1; int allow_list = 1;
const char *p = eq; const char *p = eq;

View File

@ -325,7 +325,6 @@ int dissect_image(
int r, generic_nr; int r, generic_nr;
struct stat st; struct stat st;
sd_device *q; sd_device *q;
unsigned i;
assert(fd >= 0); assert(fd >= 0);
assert(ret); assert(ret);
@ -420,7 +419,7 @@ int dissect_image(
m->verity = root_hash && verity_data; m->verity = root_hash && verity_data;
m->can_verity = !!verity_data; m->can_verity = !!verity_data;
options = mount_options_from_part(mount_options, PARTITION_ROOT); options = mount_options_from_designator(mount_options, PARTITION_ROOT);
if (options) { if (options) {
o = strdup(options); o = strdup(options);
if (!o) if (!o)
@ -504,7 +503,8 @@ int dissect_image(
continue; continue;
if (is_gpt) { if (is_gpt) {
int designator = _PARTITION_DESIGNATOR_INVALID, architecture = _ARCHITECTURE_INVALID; PartitionDesignator designator = _PARTITION_DESIGNATOR_INVALID;
int architecture = _ARCHITECTURE_INVALID;
const char *stype, *sid, *fstype = NULL; const char *stype, *sid, *fstype = NULL;
sd_id128_t type_id, id; sd_id128_t type_id, id;
bool rw = true; bool rw = true;
@ -716,7 +716,7 @@ int dissect_image(
if (!n) if (!n)
return -ENOMEM; return -ENOMEM;
options = mount_options_from_part(mount_options, designator); options = mount_options_from_designator(mount_options, designator);
if (options) { if (options) {
o = strdup(options); o = strdup(options);
if (!o) if (!o)
@ -773,7 +773,7 @@ int dissect_image(
if (!n) if (!n)
return -ENOMEM; return -ENOMEM;
options = mount_options_from_part(mount_options, PARTITION_XBOOTLDR); options = mount_options_from_designator(mount_options, PARTITION_XBOOTLDR);
if (options) { if (options) {
o = strdup(options); o = strdup(options);
if (!o) if (!o)
@ -827,7 +827,7 @@ int dissect_image(
if (multiple_generic) if (multiple_generic)
return -ENOTUNIQ; return -ENOTUNIQ;
options = mount_options_from_part(mount_options, PARTITION_ROOT); options = mount_options_from_designator(mount_options, PARTITION_ROOT);
if (options) { if (options) {
o = strdup(options); o = strdup(options);
if (!o) if (!o)
@ -866,7 +866,7 @@ int dissect_image(
b = NULL; b = NULL;
/* Fill in file system types if we don't know them yet. */ /* Fill in file system types if we don't know them yet. */
for (i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) { for (PartitionDesignator i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) {
DissectedPartition *p = m->partitions + i; DissectedPartition *p = m->partitions + i;
if (!p->found) if (!p->found)
@ -894,12 +894,10 @@ int dissect_image(
} }
DissectedImage* dissected_image_unref(DissectedImage *m) { DissectedImage* dissected_image_unref(DissectedImage *m) {
unsigned i;
if (!m) if (!m)
return NULL; return NULL;
for (i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) { for (PartitionDesignator i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) {
free(m->partitions[i].fstype); free(m->partitions[i].fstype);
free(m->partitions[i].node); free(m->partitions[i].node);
free(m->partitions[i].decrypted_fstype); free(m->partitions[i].decrypted_fstype);
@ -1557,7 +1555,6 @@ int dissected_image_decrypt(
#if HAVE_LIBCRYPTSETUP #if HAVE_LIBCRYPTSETUP
_cleanup_(decrypted_image_unrefp) DecryptedImage *d = NULL; _cleanup_(decrypted_image_unrefp) DecryptedImage *d = NULL;
unsigned i;
int r; int r;
#endif #endif
@ -1585,7 +1582,7 @@ int dissected_image_decrypt(
if (!d) if (!d)
return -ENOMEM; return -ENOMEM;
for (i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) { for (PartitionDesignator i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) {
DissectedPartition *p = m->partitions + i; DissectedPartition *p = m->partitions + i;
int k; int k;
@ -2039,14 +2036,14 @@ int dissect_image_and_warn(
} }
} }
bool dissected_image_can_do_verity(const DissectedImage *image, unsigned partition_designator) { bool dissected_image_can_do_verity(const DissectedImage *image, PartitionDesignator partition_designator) {
if (image->single_file_system) if (image->single_file_system)
return partition_designator == PARTITION_ROOT && image->can_verity; return partition_designator == PARTITION_ROOT && image->can_verity;
return PARTITION_VERITY_OF(partition_designator) >= 0; return PARTITION_VERITY_OF(partition_designator) >= 0;
} }
bool dissected_image_has_verity(const DissectedImage *image, unsigned partition_designator) { bool dissected_image_has_verity(const DissectedImage *image, PartitionDesignator partition_designator) {
int k; int k;
if (image->single_file_system) if (image->single_file_system)
@ -2068,10 +2065,10 @@ MountOptions* mount_options_free_all(MountOptions *options) {
return NULL; return NULL;
} }
const char* mount_options_from_part(const MountOptions *options, int designator) { const char* mount_options_from_designator(const MountOptions *options, PartitionDesignator designator) {
MountOptions *m; const MountOptions *m;
LIST_FOREACH(mount_options, m, (MountOptions *)options) LIST_FOREACH(mount_options, m, options)
if (designator == m->partition_designator && !isempty(m->options)) if (designator == m->partition_designator && !isempty(m->options))
return m->options; return m->options;
@ -2164,4 +2161,4 @@ static const char *const partition_designator_table[] = {
[PARTITION_VAR] = "var", [PARTITION_VAR] = "var",
}; };
DEFINE_STRING_TABLE_LOOKUP(partition_designator, int); DEFINE_STRING_TABLE_LOOKUP(partition_designator, PartitionDesignator);

View File

@ -27,7 +27,7 @@ struct DissectedPartition {
char *mount_options; char *mount_options;
}; };
enum { typedef enum PartitionDesignator {
PARTITION_ROOT, PARTITION_ROOT,
PARTITION_ROOT_SECONDARY, /* Secondary architecture */ PARTITION_ROOT_SECONDARY, /* Secondary architecture */
PARTITION_HOME, PARTITION_HOME,
@ -41,9 +41,9 @@ enum {
PARTITION_VAR, PARTITION_VAR,
_PARTITION_DESIGNATOR_MAX, _PARTITION_DESIGNATOR_MAX,
_PARTITION_DESIGNATOR_INVALID = -1 _PARTITION_DESIGNATOR_INVALID = -1
}; } PartitionDesignator;
static inline int PARTITION_VERITY_OF(int p) { static inline PartitionDesignator PARTITION_VERITY_OF(PartitionDesignator p) {
if (p == PARTITION_ROOT) if (p == PARTITION_ROOT)
return PARTITION_ROOT_VERITY; return PARTITION_ROOT_VERITY;
if (p == PARTITION_ROOT_SECONDARY) if (p == PARTITION_ROOT_SECONDARY)
@ -87,14 +87,14 @@ struct DissectedImage {
}; };
struct MountOptions { struct MountOptions {
int partition_designator; PartitionDesignator partition_designator;
char *options; char *options;
LIST_FIELDS(MountOptions, mount_options); LIST_FIELDS(MountOptions, mount_options);
}; };
MountOptions* mount_options_free_all(MountOptions *options); MountOptions* mount_options_free_all(MountOptions *options);
DEFINE_TRIVIAL_CLEANUP_FUNC(MountOptions*, mount_options_free_all); DEFINE_TRIVIAL_CLEANUP_FUNC(MountOptions*, mount_options_free_all);
const char* mount_options_from_part(const MountOptions *options, int designator); const char* mount_options_from_designator(const MountOptions *options, PartitionDesignator designator);
int probe_filesystem(const char *node, char **ret_fstype); int probe_filesystem(const char *node, char **ret_fstype);
int dissect_image(int fd, const void *root_hash, size_t root_hash_size, const char *verity_data, const MountOptions *mount_options, DissectImageFlags flags, DissectedImage **ret); int dissect_image(int fd, const void *root_hash, size_t root_hash_size, const char *verity_data, const MountOptions *mount_options, DissectImageFlags flags, DissectedImage **ret);
@ -114,11 +114,11 @@ DecryptedImage* decrypted_image_unref(DecryptedImage *p);
DEFINE_TRIVIAL_CLEANUP_FUNC(DecryptedImage*, decrypted_image_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(DecryptedImage*, decrypted_image_unref);
int decrypted_image_relinquish(DecryptedImage *d); int decrypted_image_relinquish(DecryptedImage *d);
const char* partition_designator_to_string(int i) _const_; const char* partition_designator_to_string(PartitionDesignator d) _const_;
int partition_designator_from_string(const char *name) _pure_; PartitionDesignator partition_designator_from_string(const char *name) _pure_;
int verity_metadata_load(const char *image, const char *root_hash_path, void **ret_roothash, size_t *ret_roothash_size, char **ret_verity_data, char **ret_roothashsig); int verity_metadata_load(const char *image, const char *root_hash_path, void **ret_roothash, size_t *ret_roothash_size, char **ret_verity_data, char **ret_roothashsig);
bool dissected_image_can_do_verity(const DissectedImage *image, unsigned partition_designator); bool dissected_image_can_do_verity(const DissectedImage *image, PartitionDesignator d);
bool dissected_image_has_verity(const DissectedImage *image, unsigned partition_designator); bool dissected_image_has_verity(const DissectedImage *image, PartitionDesignator d);
int mount_image_privately_interactively(const char *path, DissectImageFlags flags, char **ret_directory, LoopDevice **ret_loop_device, DecryptedImage **ret_decrypted_image); int mount_image_privately_interactively(const char *path, DissectImageFlags flags, char **ret_directory, LoopDevice **ret_loop_device, DecryptedImage **ret_decrypted_image);

View File

@ -7,26 +7,26 @@
#include "id128-util.h" #include "id128-util.h"
/* We only support root disk discovery for x86, x86-64, Itanium and ARM for /* We only support root disk discovery for x86, x86-64, Itanium and ARM for now, since EFI for anything else
* now, since EFI for anything else doesn't really exist, and we only * doesn't really exist, and we only care for root partitions on the same disk as the EFI ESP. */
* care for root partitions on the same disk as the EFI ESP. */
#define GPT_ROOT_X86 SD_ID128_MAKE(44,47,95,40,f2,97,41,b2,9a,f7,d1,31,d5,f0,45,8a) #define GPT_ROOT_X86 SD_ID128_MAKE(44,47,95,40,f2,97,41,b2,9a,f7,d1,31,d5,f0,45,8a)
#define GPT_ROOT_X86_64 SD_ID128_MAKE(4f,68,bc,e3,e8,cd,4d,b1,96,e7,fb,ca,f9,84,b7,09) #define GPT_ROOT_X86_64 SD_ID128_MAKE(4f,68,bc,e3,e8,cd,4d,b1,96,e7,fb,ca,f9,84,b7,09)
#define GPT_ROOT_ARM SD_ID128_MAKE(69,da,d7,10,2c,e4,4e,3c,b1,6c,21,a1,d4,9a,be,d3) #define GPT_ROOT_ARM SD_ID128_MAKE(69,da,d7,10,2c,e4,4e,3c,b1,6c,21,a1,d4,9a,be,d3)
#define GPT_ROOT_ARM_64 SD_ID128_MAKE(b9,21,b0,45,1d,f0,41,c3,af,44,4c,6f,28,0d,3f,ae) #define GPT_ROOT_ARM_64 SD_ID128_MAKE(b9,21,b0,45,1d,f0,41,c3,af,44,4c,6f,28,0d,3f,ae)
#define GPT_ROOT_IA64 SD_ID128_MAKE(99,3d,8d,3d,f8,0e,42,25,85,5a,9d,af,8e,d7,ea,97) #define GPT_ROOT_IA64 SD_ID128_MAKE(99,3d,8d,3d,f8,0e,42,25,85,5a,9d,af,8e,d7,ea,97)
#define GPT_ESP SD_ID128_MAKE(c1,2a,73,28,f8,1f,11,d2,ba,4b,00,a0,c9,3e,c9,3b) #define GPT_ESP SD_ID128_MAKE(c1,2a,73,28,f8,1f,11,d2,ba,4b,00,a0,c9,3e,c9,3b)
#define GPT_XBOOTLDR SD_ID128_MAKE(bc,13,c2,ff,59,e6,42,62,a3,52,b2,75,fd,6f,71,72) #define GPT_XBOOTLDR SD_ID128_MAKE(bc,13,c2,ff,59,e6,42,62,a3,52,b2,75,fd,6f,71,72)
#define GPT_SWAP SD_ID128_MAKE(06,57,fd,6d,a4,ab,43,c4,84,e5,09,33,c8,4b,4f,4f) #define GPT_SWAP SD_ID128_MAKE(06,57,fd,6d,a4,ab,43,c4,84,e5,09,33,c8,4b,4f,4f)
#define GPT_HOME SD_ID128_MAKE(93,3a,c7,e1,2e,b4,4f,13,b8,44,0e,14,e2,ae,f9,15) #define GPT_HOME SD_ID128_MAKE(93,3a,c7,e1,2e,b4,4f,13,b8,44,0e,14,e2,ae,f9,15)
#define GPT_SRV SD_ID128_MAKE(3b,8f,84,25,20,e0,4f,3b,90,7f,1a,25,a7,6f,98,e8) #define GPT_SRV SD_ID128_MAKE(3b,8f,84,25,20,e0,4f,3b,90,7f,1a,25,a7,6f,98,e8)
#define GPT_VAR SD_ID128_MAKE(4d,21,b0,16,b5,34,45,c2,a9,fb,5c,16,e0,91,fd,2d) #define GPT_VAR SD_ID128_MAKE(4d,21,b0,16,b5,34,45,c2,a9,fb,5c,16,e0,91,fd,2d)
#define GPT_TMP SD_ID128_MAKE(7e,c6,f5,57,3b,c5,4a,ca,b2,93,16,ef,5d,f6,39,d1) #define GPT_TMP SD_ID128_MAKE(7e,c6,f5,57,3b,c5,4a,ca,b2,93,16,ef,5d,f6,39,d1)
#define GPT_USER_HOME SD_ID128_MAKE(77,3f,91,ef,66,d4,49,b5,bd,83,d6,83,bf,40,ad,16) #define GPT_USER_HOME SD_ID128_MAKE(77,3f,91,ef,66,d4,49,b5,bd,83,d6,83,bf,40,ad,16)
#define GPT_LINUX_GENERIC SD_ID128_MAKE(0f,c6,3d,af,84,83,47,72,8e,79,3d,69,d8,47,7d,e4)
/* Verity partitions for the root partitions above (we only define them for the root partitions, because only they are /* Verity partitions for the root partitions above (we only define them for the root partitions, because only
* are commonly read-only and hence suitable for verity). */ * they are are commonly read-only and hence suitable for verity). */
#define GPT_ROOT_X86_VERITY SD_ID128_MAKE(d1,3c,5d,3b,b5,d1,42,2a,b2,9f,94,54,fd,c8,9d,76) #define GPT_ROOT_X86_VERITY SD_ID128_MAKE(d1,3c,5d,3b,b5,d1,42,2a,b2,9f,94,54,fd,c8,9d,76)
#define GPT_ROOT_X86_64_VERITY SD_ID128_MAKE(2c,73,57,ed,eb,d2,46,d9,ae,c1,23,d4,37,ec,2b,f5) #define GPT_ROOT_X86_64_VERITY SD_ID128_MAKE(2c,73,57,ed,eb,d2,46,d9,ae,c1,23,d4,37,ec,2b,f5)
#define GPT_ROOT_ARM_VERITY SD_ID128_MAKE(73,86,cd,f2,20,3c,47,a9,a4,98,f2,ec,ce,45,a2,d6) #define GPT_ROOT_ARM_VERITY SD_ID128_MAKE(73,86,cd,f2,20,3c,47,a9,a4,98,f2,ec,ce,45,a2,d6)
@ -62,15 +62,12 @@
#define GPT_FLAG_NO_BLOCK_IO_PROTOCOL (1ULL << 1) #define GPT_FLAG_NO_BLOCK_IO_PROTOCOL (1ULL << 1)
#define GPT_FLAG_LEGACY_BIOS_BOOTABLE (1ULL << 2) #define GPT_FLAG_LEGACY_BIOS_BOOTABLE (1ULL << 2)
/* Flags we recognize on the root, swap, home and srv partitions when /* Flags we recognize on the root, swap, home and srv partitions when doing auto-discovery. These happen to
* doing auto-discovery. These happen to be identical to what * be identical to what Microsoft defines for its own Basic Data Partitions, but that's just because we saw
* Microsoft defines for its own Basic Data Partitions, but that's * no point in defining any other values here. */
* just because we saw no point in defining any other values here. */
#define GPT_FLAG_READ_ONLY (1ULL << 60) #define GPT_FLAG_READ_ONLY (1ULL << 60)
#define GPT_FLAG_NO_AUTO (1ULL << 63) #define GPT_FLAG_NO_AUTO (1ULL << 63)
#define GPT_LINUX_GENERIC SD_ID128_MAKE(0f,c6,3d,af,84,83,47,72,8e,79,3d,69,d8,47,7d,e4)
const char *gpt_partition_type_uuid_to_string(sd_id128_t id); const char *gpt_partition_type_uuid_to_string(sd_id128_t id);
const char *gpt_partition_type_uuid_to_string_harder( const char *gpt_partition_type_uuid_to_string_harder(
sd_id128_t id, sd_id128_t id,

View File

@ -1071,7 +1071,13 @@ int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* set, u
int id = PTR_TO_INT(syscall_id) - 1; int id = PTR_TO_INT(syscall_id) - 1;
int error = PTR_TO_INT(val); int error = PTR_TO_INT(val);
if (action != SCMP_ACT_ALLOW && error >= 0) if (error == SECCOMP_ERROR_NUMBER_KILL)
a = scmp_act_kill_process();
#ifdef SCMP_ACT_LOG
else if (action == SCMP_ACT_LOG)
a = SCMP_ACT_LOG;
#endif
else if (action != SCMP_ACT_ALLOW && error >= 0)
a = SCMP_ACT_ERRNO(error); a = SCMP_ACT_ERRNO(error);
r = seccomp_rule_add_exact(seccomp, a, id, 0); r = seccomp_rule_add_exact(seccomp, a, id, 0);

View File

@ -5,7 +5,10 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include "errno-list.h"
#include "parse-util.h"
#include "set.h" #include "set.h"
#include "string-util.h"
const char* seccomp_arch_to_string(uint32_t c); const char* seccomp_arch_to_string(uint32_t c);
int seccomp_arch_from_string(const char *n, uint32_t *ret); int seccomp_arch_from_string(const char *n, uint32_t *ret);
@ -115,3 +118,25 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(scmp_filter_ctx, seccomp_release);
int parse_syscall_archs(char **l, Set **ret_archs); int parse_syscall_archs(char **l, Set **ret_archs);
uint32_t scmp_act_kill_process(void); uint32_t scmp_act_kill_process(void);
/* This is a special value to be used where syscall filters otherwise expect errno numbers, will be
replaced with real seccomp action. */
enum {
SECCOMP_ERROR_NUMBER_KILL = INT_MAX - 1,
};
static inline bool seccomp_errno_or_action_is_valid(int n) {
return n == SECCOMP_ERROR_NUMBER_KILL || errno_is_valid(n);
}
static inline int seccomp_parse_errno_or_action(const char *p) {
if (streq_ptr(p, "kill"))
return SECCOMP_ERROR_NUMBER_KILL;
return parse_errno(p);
}
static inline const char *seccomp_errno_or_action_to_string(int num) {
if (num == SECCOMP_ERROR_NUMBER_KILL)
return "kill";
return errno_to_name(num);
}

View File

@ -417,7 +417,6 @@ static int resolve_remote(Connection *c) {
static const struct addrinfo hints = { static const struct addrinfo hints = {
.ai_family = AF_UNSPEC, .ai_family = AF_UNSPEC,
.ai_socktype = SOCK_STREAM, .ai_socktype = SOCK_STREAM,
.ai_flags = AI_ADDRCONFIG
}; };
const char *node, *service; const char *node, *service;

View File

@ -4822,7 +4822,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
return 1; return 1;
} else if (STR_IN_SET(name, "SystemCallFilter", "RestrictAddressFamilies")) { } else if (STR_IN_SET(name, "SystemCallFilter", "SystemCallLog", "RestrictAddressFamilies")) {
_cleanup_strv_free_ char **l = NULL; _cleanup_strv_free_ char **l = NULL;
int allow_list; int allow_list;

View File

@ -421,11 +421,6 @@ tests += [
[], [],
'', 'manual'], '', 'manual'],
[['src/test/test-dissect-image.c'],
[],
[libblkid],
'', 'manual'],
[['src/test/test-signal-util.c'], [['src/test/test-signal-util.c'],
[], [],
[]], []],

View File

@ -1,51 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <fcntl.h>
#include <linux/loop.h>
#include <stdio.h>
#include "dissect-image.h"
#include "log.h"
#include "loop-util.h"
#include "string-util.h"
#include "tests.h"
int main(int argc, char *argv[]) {
_cleanup_(loop_device_unrefp) LoopDevice *d = NULL;
_cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
int r, i;
test_setup_logging(LOG_DEBUG);
if (argc < 2) {
log_error("Requires one command line argument.");
return EXIT_FAILURE;
}
r = loop_device_make_by_path(argv[1], O_RDONLY, LO_FLAGS_PARTSCAN, &d);
if (r < 0) {
log_error_errno(r, "Failed to set up loopback device: %m");
return EXIT_FAILURE;
}
r = dissect_image(d->fd, NULL, 0, NULL, NULL, DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_RELAX_VAR_CHECK, &m);
if (r < 0) {
log_error_errno(r, "Failed to dissect image: %m");
return EXIT_FAILURE;
}
for (i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) {
if (!m->partitions[i].found)
continue;
printf("Found %s partition, %s of type %s at #%i (%s)\n",
partition_designator_to_string(i),
m->partitions[i].rw ? "writable" : "read-only",
strna(m->partitions[i].fstype),
m->partitions[i].partno,
strna(m->partitions[i].node));
}
return EXIT_SUCCESS;
}

View File

@ -434,6 +434,8 @@ static void test_exec_systemcallfilter(Manager *m) {
test(__func__, m, "exec-systemcallfilter-with-errno-name.service", errno_from_name("EILSEQ"), CLD_EXITED); test(__func__, m, "exec-systemcallfilter-with-errno-name.service", errno_from_name("EILSEQ"), CLD_EXITED);
test(__func__, m, "exec-systemcallfilter-with-errno-number.service", 255, CLD_EXITED); test(__func__, m, "exec-systemcallfilter-with-errno-number.service", 255, CLD_EXITED);
test(__func__, m, "exec-systemcallfilter-with-errno-multi.service", errno_from_name("EILSEQ"), CLD_EXITED); test(__func__, m, "exec-systemcallfilter-with-errno-multi.service", errno_from_name("EILSEQ"), CLD_EXITED);
test(__func__, m, "exec-systemcallfilter-override-error-action.service", SIGSYS, CLD_KILLED);
test(__func__, m, "exec-systemcallfilter-override-error-action2.service", errno_from_name("EILSEQ"), CLD_EXITED);
#endif #endif
} }
@ -576,10 +578,14 @@ static void test_exec_dynamicuser(Manager *m) {
test(__func__, m, "exec-dynamicuser-supplementarygroups.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); test(__func__, m, "exec-dynamicuser-supplementarygroups.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(__func__, m, "exec-dynamicuser-statedir.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); test(__func__, m, "exec-dynamicuser-statedir.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
(void) rm_rf("/var/lib/quux", REMOVE_ROOT|REMOVE_PHYSICAL);
(void) rm_rf("/var/lib/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL); (void) rm_rf("/var/lib/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
(void) rm_rf("/var/lib/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL); (void) rm_rf("/var/lib/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL);
(void) rm_rf("/var/lib/waldo", REMOVE_ROOT|REMOVE_PHYSICAL);
(void) rm_rf("/var/lib/private/quux", REMOVE_ROOT|REMOVE_PHYSICAL);
(void) rm_rf("/var/lib/private/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL); (void) rm_rf("/var/lib/private/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
(void) rm_rf("/var/lib/private/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL); (void) rm_rf("/var/lib/private/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL);
(void) rm_rf("/var/lib/private/waldo", REMOVE_ROOT|REMOVE_PHYSICAL);
test(__func__, m, "exec-dynamicuser-statedir-migrate-step1.service", 0, CLD_EXITED); test(__func__, m, "exec-dynamicuser-statedir-migrate-step1.service", 0, CLD_EXITED);
test(__func__, m, "exec-dynamicuser-statedir-migrate-step2.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); test(__func__, m, "exec-dynamicuser-statedir-migrate-step2.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);

View File

@ -10,6 +10,9 @@
#include "log.h" #include "log.h"
#include "parse-util.h" #include "parse-util.h"
#include "string-util.h" #include "string-util.h"
#if HAVE_SECCOMP
#include "seccomp-util.h"
#endif
static void test_parse_boolean(void) { static void test_parse_boolean(void) {
assert_se(parse_boolean("1") == 1); assert_se(parse_boolean("1") == 1);
@ -852,6 +855,7 @@ static void test_parse_errno(void) {
} }
static void test_parse_syscall_and_errno(void) { static void test_parse_syscall_and_errno(void) {
#if HAVE_SECCOMP
_cleanup_free_ char *n = NULL; _cleanup_free_ char *n = NULL;
int e; int e;
@ -882,11 +886,16 @@ static void test_parse_syscall_and_errno(void) {
assert_se(e == 255); assert_se(e == 255);
n = mfree(n); n = mfree(n);
assert_se(parse_syscall_and_errno("hoge:kill", &n, &e) >= 0);
assert_se(streq(n, "hoge"));
assert_se(e == SECCOMP_ERROR_NUMBER_KILL);
n = mfree(n);
/* The function checks the syscall name is empty or not. */ /* The function checks the syscall name is empty or not. */
assert_se(parse_syscall_and_errno("", &n, &e) == -EINVAL); assert_se(parse_syscall_and_errno("", &n, &e) == -EINVAL);
assert_se(parse_syscall_and_errno(":255", &n, &e) == -EINVAL); assert_se(parse_syscall_and_errno(":255", &n, &e) == -EINVAL);
/* errno must be a valid errno name or number between 0 and ERRNO_MAX == 4095 */ /* errno must be a valid errno name or number between 0 and ERRNO_MAX == 4095, or "kill" */
assert_se(parse_syscall_and_errno("hoge:4096", &n, &e) == -ERANGE); assert_se(parse_syscall_and_errno("hoge:4096", &n, &e) == -ERANGE);
assert_se(parse_syscall_and_errno("hoge:-3", &n, &e) == -ERANGE); assert_se(parse_syscall_and_errno("hoge:-3", &n, &e) == -ERANGE);
assert_se(parse_syscall_and_errno("hoge:12.3", &n, &e) == -EINVAL); assert_se(parse_syscall_and_errno("hoge:12.3", &n, &e) == -EINVAL);
@ -896,6 +905,7 @@ static void test_parse_syscall_and_errno(void) {
assert_se(parse_syscall_and_errno("hoge:-EINVAL", &n, &e) == -EINVAL); assert_se(parse_syscall_and_errno("hoge:-EINVAL", &n, &e) == -EINVAL);
assert_se(parse_syscall_and_errno("hoge:EINVALaaa", &n, &e) == -EINVAL); assert_se(parse_syscall_and_errno("hoge:EINVALaaa", &n, &e) == -EINVAL);
assert_se(parse_syscall_and_errno("hoge:", &n, &e) == -EINVAL); assert_se(parse_syscall_and_errno("hoge:", &n, &e) == -EINVAL);
#endif
} }
static void test_parse_mtu(void) { static void test_parse_mtu(void) {

View File

@ -0,0 +1,8 @@
[Unit]
Description=Test for SystemCallFilter with specific kill action overriding default errno action
[Service]
ExecStart=/usr/bin/python3 -c 'import os\ntry: os.uname()\nexcept Exception as e: exit(e.errno)'
Type=oneshot
SystemCallFilter=~uname:kill
SystemCallErrorNumber=EILSEQ

View File

@ -0,0 +1,8 @@
[Unit]
Description=Test for SystemCallFilter with specific errno action overriding default kill action
[Service]
ExecStart=/usr/bin/python3 -c 'import os\ntry: os.uname()\nexcept Exception as e: exit(e.errno)'
Type=oneshot
SystemCallFilter=~uname:EILSEQ
SystemCallErrorNumber=kill

View File

@ -8,16 +8,16 @@
# (at your option) any later version. # (at your option) any later version.
# This unit gets pulled automatically into multi-user.target by # This unit gets pulled automatically into multi-user.target by
# systemd-rc-local-generator if @RC_LOCAL_SCRIPT_PATH_START@ is executable. # systemd-rc-local-generator if @RC_LOCAL_PATH@ is executable.
[Unit] [Unit]
Description=@RC_LOCAL_SCRIPT_PATH_START@ Compatibility Description=@RC_LOCAL_PATH@ Compatibility
Documentation=man:systemd-rc-local-generator(8) Documentation=man:systemd-rc-local-generator(8)
ConditionFileIsExecutable=@RC_LOCAL_SCRIPT_PATH_START@ ConditionFileIsExecutable=@RC_LOCAL_PATH@
After=network.target After=network.target
[Service] [Service]
Type=forking Type=forking
ExecStart=@RC_LOCAL_SCRIPT_PATH_START@ start ExecStart=@RC_LOCAL_PATH@ start
TimeoutSec=0 TimeoutSec=0
RemainAfterExit=yes RemainAfterExit=yes
GuessMainPID=no GuessMainPID=no