1
0
mirror of https://github.com/systemd/systemd synced 2026-03-19 11:34:46 +01:00

Compare commits

..

19 Commits

Author SHA1 Message Date
Yu Watanabe
431fc656bc Bump required minimum version of libseccomp to 2.4.0
Major distributions already have libseccomp 2.5.x or newer.
Let's bump to the required minimum version to 2.4.0, which provides
SCMP_ACT_KILL_PROCESS, SCMP_ACT_LOG, SCMP_ARCH_PARISC, and
SCMP_ARCH_PARISC64.

Note, libseccomp 2.4.0 was released on 2019-03-15.

See also #38608.
2026-01-02 12:54:18 +09:00
Yu Watanabe
23c82484e7 Bump required minimum version of cryptsetup to 2.4.0
Major distributions already have cryptsetup newer than 2.4.0.
Let's bump the minimal required version.

Note, cryptsetup 2.4.0 was released on 2021-08-18.

See also #38608.
2026-01-02 11:15:17 +09:00
Yu Watanabe
9ba0e5674b Bump required minimum version of elfutils to 0.177
Major distributions already have elfutils >= 0.190.
Let's bump the required minimum version.

Note, elfutils 0.177 was released on 2019-08-14.

See also #38608.
2026-01-02 11:12:27 +09:00
Yu Watanabe
e4fd21a777 Bump required minimum version of blkid to 2.37
Major distributions already have blkid >= 2.37.
Let's bump the minimal required version.

Note, util-linux (which provides blkid) 2.37 was released on 2021-06-01.

See also #38608.
2026-01-02 11:12:05 +09:00
Yu Watanabe
99d0a9fdb0 Bump required minimum version of OpenSSL to 3.0.0
All major distributions have switched to OpenSSL version 3.x.
Let's drop support of OpenSSL version 1.x.

Note, OpenSSL 3.0 was released on 2021-09-07 (and will be EOL on 2026-09-07).

See also #38608.
2026-01-02 11:09:52 +09:00
Yu Watanabe
33340fbe44 man: drop redundant 'and'
Also swap the order of entries, to make it consistent for other unit
types.

Follow-up for 79dd24cf14adc809620479d45a7b469cf3e82892.
2026-01-02 09:52:31 +09:00
Adam Williamson
b671f193e3 Enable systemd-coredump for offline updates
If a crash occurs during an offline update, we do not get a
coredump, because systemd-coredump is not enabled. This of course
complicates debugging.

Signed-off-by: Adam Williamson <awilliam@redhat.com>
2026-01-02 09:31:20 +09:00
Yu Watanabe
cb9d854207
network: Support interface-bound ECMP routes in MultiPathRoute= (#39742)
MultiPathRoute= can now specify device-only nexthops without a gateway
address, e.g. MultiPathRoute=@wg0. This enables ECMP configurations over
interfaces that don't use gateway addresses, such as WireGuard tunnels.

The syntax is extended from "address[@device] [weight]" to
"[address]@device [weight]". The address is now optional, but at least
one of gateway or device must be specified. The @ symbol must still be
present for device-only routes, making the syntax unambiguous: @wg0
specifies a device, while a bare IP address specifies a gateway.

Device-only nexthops are only available for IPv4 routes. Device-only
multipath routes for IPv6 are not supported by the kernel's netlink
interface and will be rejected with a warning.

This change is fully backwards compatible. All existing configurations
continue to work unchanged, as they always included a gateway address.

Closes #39699.
2026-01-02 09:25:43 +09:00
Daan De Meyer
4e805ec152 vmspawn: Add --user/--system and support user session machined registration
The UX of registering with the user session machined
instance is much better as there won't be an authorization
prompt. To make that available for users, let's add --user
and --system switches for vmspawn. For backwards compat, we'll
still try to register with the system machined instance if the
user machined instance is not available.
2026-01-02 08:49:36 +09:00
Yu Watanabe
2ff1a84b19
docs: update password agent document (#40235)
Adding some missing information from the code to the docs.
2026-01-02 08:03:37 +09:00
Mike Yuan
ca6b65991c udev,sysupdated: fix pidfd leak
Follow-up for 179dcf924f7d0ac9398f54baeb39b47abd23aeaf

After the mentioned commit, event_add_child_pidref() duplicates
the pidfd internally, hence the original pidfd would be leaked
with TAKE_PIDREF.
2026-01-02 07:59:15 +09:00
DaanDeMeyer
47d22e41e4 unit-def: Clean up whitespace 2026-01-02 06:28:39 +09:00
DaanDeMeyer
ded0f85f7b openssl-util: Make ret_user_interface required output argument
To avoid the argument accidentally not getting passed anymore during
refactoring, let's make it a required output argument so that callers
are required to provide it.

See 11f47cb70014894a9f09c730ee7aedcac89cf73e and
875b568f56e3a8a23edd9f20463c9019ec098900.
2026-01-02 06:27:51 +09:00
Ben Boeckel
0d15b2304b docs/PASSWORD_AGENTS: document the AcceptCached= field 2025-12-31 10:59:41 -05:00
Ben Boeckel
9f4606c361 docs/PASSWORD_AGENTS: document the Silent= field 2025-12-31 10:59:25 -05:00
Ben Boeckel
dc08cb1eb8 docs/PASSWORD_AGENTS: clarify that Echo=0 may obscure 2025-12-31 10:58:53 -05:00
Ben Boeckel
19d7ce2f7b docs/PASSWORD_AGENTS: note that the user directory may be created 2025-12-31 10:58:26 -05:00
Chris Down
23d02f6327 test: Add comprehensive tests for MultiPathRoute device-only syntax
Add unit tests for config_parse_multipath_route() covering the new
device-only nexthop syntax (@device). Tests verify basic parsing of
device-only routes, gateway with device routes, gateway-only routes,
interface index handling, etc. Also some checks on new hash/duplicate
semantics.

Also add an integration test to verify device-only multipath routes are
correctly installed in the kernel routing table.
2025-11-28 19:09:15 +08:00
Chris Down
645b709a38 network: Support interface-bound ECMP routes in MultiPathRoute=
MultiPathRoute= can now specify device-only nexthops without a gateway
address, e.g. MultiPathRoute=@wg0. This enables ECMP configurations over
interfaces that don't use gateway addresses, such as WireGuard tunnels.

The syntax is extended from "address[@device] [weight]" to
"[address]@device [weight]". The address is now optional, but at least
one of gateway or device must be specified. The @ symbol must still be
present for device-only routes, making the syntax unambiguous: @wg0
specifies a device, while a bare IP address specifies a gateway.

Device-only nexthops are only available for IPv4 routes. Device-only
multipath routes for IPv6 are not supported by the kernel's netlink
interface and will be rejected with a warning.

This change is fully backwards compatible. All existing configurations
continue to work unchanged, as they always included a gateway address.

Closes #39699.
2025-11-28 19:09:15 +08:00
37 changed files with 377 additions and 529 deletions

11
README
View File

@ -215,12 +215,11 @@ REQUIREMENTS:
libxcrypt or glibc (<= 2.38 built with --enable-crypt) libxcrypt or glibc (<= 2.38 built with --enable-crypt)
libmount >= 2.30 (from util-linux) libmount >= 2.30 (from util-linux)
(util-linux *must* be built without --enable-libmount-support-mtab) (util-linux *must* be built without --enable-libmount-support-mtab)
libseccomp >= 2.3.1 (optional) libseccomp >= 2.4.0 (optional)
libblkid >= 2.24 (from util-linux) (optional) libblkid >= 2.37 (from util-linux) (optional)
libkmod >= 15 (optional) libkmod >= 15 (optional)
PAM >= 1.1.2 (optional) PAM >= 1.1.2 (optional)
libcryptsetup >= 2.0.1 (optional), libcryptsetup >= 2.4.0 (optional),
>= 2.3.0 is required for signed Verity images support
libaudit (optional) libaudit (optional)
libacl (optional) libacl (optional)
libbpf >= 0.1.0 (optional), libbpf >= 0.1.0 (optional),
@ -243,11 +242,11 @@ REQUIREMENTS:
libcurl >= 7.32.0 (optional) libcurl >= 7.32.0 (optional)
libidn2 or libidn (optional) libidn2 or libidn (optional)
gnutls >= 3.1.4 (optional) gnutls >= 3.1.4 (optional)
openssl >= 1.1.0 (optional, required to support DNS-over-TLS) openssl >= 3.0.0 (optional, required to support DNS-over-TLS)
p11-kit >= 0.23.3 (optional) p11-kit >= 0.23.3 (optional)
libfido2 (optional) libfido2 (optional)
tpm2-tss (optional) tpm2-tss (optional)
elfutils >= 158 (optional) elfutils >= 177 (optional)
polkit (optional) polkit (optional)
tzdata >= 2014f (optional) tzdata >= 2014f (optional)
pkg-config pkg-config

View File

@ -40,7 +40,9 @@ It is easy to write additional agents. The basic algorithm to follow looks like
* You'll find the PID of the client asking the question in the `PID=` field in the `[Ask]` section * You'll find the PID of the client asking the question in the `PID=` field in the `[Ask]` section
(Before asking your question use `kill(PID, 0)` and ignore the file if this returns `ESRCH`; (Before asking your question use `kill(PID, 0)` and ignore the file if this returns `ESRCH`;
there's no need to show the data of this field but if you want to you may) there's no need to show the data of this field but if you want to you may)
* `Echo=` specifies whether the input should be obscured. If this field is missing or is `Echo=0`, the input should not be shown. * `Echo=` specifies whether the input should be obscured. If this field is missing or is `Echo=0`, the input should not be shown as-is.
* `Silent=` specifies whether the input should have any indication. If this field is `Silent=1`, nothing should be printed for any input.
* `AcceptCached=` specifies whether a cached password is acceptable or not. If this field is missing or is `AcceptCached=0`, the password should not be provided from a cache.
* The socket to send the response to is configured via `Socket=` in the `[Ask]` section. It is a `AF_UNIX`/`SOCK_DGRAM` socket in the file system. * The socket to send the response to is configured via `Socket=` in the `[Ask]` section. It is a `AF_UNIX`/`SOCK_DGRAM` socket in the file system.
* Ignore files where the time specified in the `NotAfter=` field in the `[Ask]` section is in the past. * Ignore files where the time specified in the `NotAfter=` field in the `[Ask]` section is in the past.
The time is specified in usecs, and refers to the `CLOCK_MONOTONIC` clock. If `NotAfter=` is `0`, no such check should take place. The time is specified in usecs, and refers to the `CLOCK_MONOTONIC` clock. If `NotAfter=` is `0`, no such check should take place.
@ -100,4 +102,4 @@ now available, with the same protocol as the system-wide
counterpart. Unprivileged, per-directory agents should watch this directory in counterpart. Unprivileged, per-directory agents should watch this directory in
parallel to the system-wide one. Unprivileged queriers (i.e. clients to these parallel to the system-wide one. Unprivileged queriers (i.e. clients to these
agents) should pick the per-user directory to place their password request agents) should pick the per-user directory to place their password request
files in. files in. If the directory does not exist, agents may create it.

View File

@ -12664,8 +12664,8 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \
<varname>LogsDirectoryQuotaUsage</varname>, <varname>LogsDirectoryQuotaUsage</varname>,
<varname>LogsDirectoryAccounting</varname>, and <varname>LogsDirectoryAccounting</varname>, and
<function>KillSubgroup()</function> were added in version 258.</para> <function>KillSubgroup()</function> were added in version 258.</para>
<para><varname>OOMKills</varname>, and <para><varname>UserNamespacePath</varname>,
<varname>UserNamespacePath</varname>, and <varname>OOMKills</varname>, and
<varname>ManagedOOMKills</varname> were added in 259.</para> <varname>ManagedOOMKills</varname> were added in 259.</para>
<para><varname>BindNetworkInterface</varname> was added in version 260.</para> <para><varname>BindNetworkInterface</varname> was added in version 260.</para>
</refsect2> </refsect2>

View File

@ -69,6 +69,18 @@
<xi:include href="version-info.xml" xpointer="v256"/></listitem> <xi:include href="version-info.xml" xpointer="v256"/></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--system</option></term>
<term><option>--user</option></term>
<listitem><para>Specify whether to interact with the user manager or the system manager and whether
to register with the user machined instance or the system machined instance. If
unspecified, the system manager and machined instance will be used when running as root, otherwise
the user manager and machined instance will be used.</para>
<xi:include href="version-info.xml" xpointer="v260"/></listitem>
</varlistentry>
</variablelist> </variablelist>
<refsect2> <refsect2>

View File

@ -2325,13 +2325,20 @@ NFTSet=prefix:netdev:filter:eth_ipv4_prefix</programlisting>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><varname>MultiPathRoute=<replaceable>address</replaceable>[@<replaceable>name</replaceable>] [<replaceable>weight</replaceable>]</varname></term> <term><varname>MultiPathRoute=</varname></term>
<listitem> <listitem>
<para>Configures multipath route. Multipath routing is the technique of using multiple <para>Configures multipath route. Multipath routing is the technique of using multiple
alternative paths through a network. Takes gateway address. Optionally, takes a network alternative paths through a network. Takes a gateway address and/or a network interface
interface name or index separated with <literal>@</literal>, and a weight in 1..256 for this name or index (prefixed with <literal>@</literal>). At least one of these must be specified.
multipath route separated with whitespace. This setting can be specified multiple times. If Optionally, a weight in 1..256 can be specified, separated with whitespace. This setting
an empty string is assigned, then the all previous assignments are cleared.</para> can be specified multiple times. If an empty string is assigned, then all previous
assignments are cleared.</para>
<para>Examples:</para>
<programlisting>MultiPathRoute=10.0.0.1@eth0 20
MultiPathRoute=192.168.1.1 50
MultiPathRoute=@wg0 15
MultiPathRoute=2001:db8::1@eth0</programlisting>
<xi:include href="version-info.xml" xpointer="v245"/> <xi:include href="version-info.xml" xpointer="v245"/>
</listitem> </listitem>

View File

@ -1180,7 +1180,7 @@ conf.set10('HAVE_PWQUALITY', have)
conf.set10('HAVE_PASSWDQC', not have and libpwquality.found()) conf.set10('HAVE_PASSWDQC', not have and libpwquality.found())
libseccomp = dependency('libseccomp', libseccomp = dependency('libseccomp',
version : '>= 2.3.1', version : '>= 2.4.0',
required : get_option('seccomp')) required : get_option('seccomp'))
conf.set10('HAVE_SECCOMP', libseccomp.found()) conf.set10('HAVE_SECCOMP', libseccomp.found())
libseccomp_cflags = libseccomp.partial_dependency(includes: true, compile_args: true) libseccomp_cflags = libseccomp.partial_dependency(includes: true, compile_args: true)
@ -1229,10 +1229,9 @@ conf.set10('HAVE_AUDIT', libaudit.found())
libaudit_cflags = libaudit.partial_dependency(includes: true, compile_args: true) libaudit_cflags = libaudit.partial_dependency(includes: true, compile_args: true)
libblkid = dependency('blkid', libblkid = dependency('blkid',
version : '>=2.37.0',
required : get_option('blkid')) required : get_option('blkid'))
conf.set10('HAVE_BLKID', libblkid.found()) conf.set10('HAVE_BLKID', libblkid.found())
conf.set10('HAVE_BLKID_PROBE_SET_HINT',
libblkid.found() and cc.has_function('blkid_probe_set_hint', dependencies : libblkid))
libblkid_cflags = libblkid.partial_dependency(includes: true, compile_args: true) libblkid_cflags = libblkid.partial_dependency(includes: true, compile_args: true)
libkmod = dependency('libkmod', libkmod = dependency('libkmod',
@ -1277,19 +1276,16 @@ if libcryptsetup_plugins.enabled()
endif endif
libcryptsetup = dependency('libcryptsetup', libcryptsetup = dependency('libcryptsetup',
version : libcryptsetup_plugins.enabled() ? '>= 2.4.0' : '>= 2.0.1', version : '>= 2.4.0',
required : libcryptsetup) required : libcryptsetup)
libcryptsetup_cflags = libcryptsetup.partial_dependency(includes: true, compile_args: true) libcryptsetup_cflags = libcryptsetup.partial_dependency(includes: true, compile_args: true)
have = libcryptsetup.found() have = libcryptsetup.found()
conf.set10('HAVE_LIBCRYPTSETUP', have) conf.set10('HAVE_LIBCRYPTSETUP', have)
conf.set10('HAVE_LIBCRYPTSETUP_PLUGINS',
libcryptsetup_plugins.allowed() and have)
foreach ident : [ foreach ident : [
'crypt_activate_by_token_pin', # 2.4
'crypt_logf', # 2.4
'crypt_reencrypt_run', # 2.4
'crypt_token_external_path', # 2.4
'crypt_token_max', # 2.4
'crypt_set_keyring_to_link', # 2.7 'crypt_set_keyring_to_link', # 2.7
'crypt_token_set_external_path', # 2.7 'crypt_token_set_external_path', # 2.7
] ]
@ -1301,12 +1297,6 @@ foreach ident : [
conf.set10('HAVE_' + ident.to_upper(), have_ident) conf.set10('HAVE_' + ident.to_upper(), have_ident)
endforeach endforeach
conf.set10('HAVE_LIBCRYPTSETUP_PLUGINS',
libcryptsetup_plugins.allowed() and
conf.get('HAVE_CRYPT_ACTIVATE_BY_TOKEN_PIN') == 1 and
conf.get('HAVE_CRYPT_LOGF') == 1 and
conf.get('HAVE_CRYPT_TOKEN_EXTERNAL_PATH') == 1)
libcurl = dependency('libcurl', libcurl = dependency('libcurl',
version : '>= 7.32.0', version : '>= 7.32.0',
required : get_option('libcurl')) required : get_option('libcurl'))
@ -1355,7 +1345,7 @@ libgnutls = dependency('gnutls',
conf.set10('HAVE_GNUTLS', libgnutls.found()) conf.set10('HAVE_GNUTLS', libgnutls.found())
libopenssl = dependency('openssl', libopenssl = dependency('openssl',
version : '>= 1.1.0', version : '>= 3.0.0',
required : get_option('openssl')) required : get_option('openssl'))
conf.set10('HAVE_OPENSSL', libopenssl.found()) conf.set10('HAVE_OPENSSL', libopenssl.found())
@ -1381,6 +1371,7 @@ conf.set10('HAVE_TSS2_ESYS3', tpm2.found() and tpm2.version().version_compare('>
conf.set('TPM2_NVPCR_BASE', get_option('tpm2-nvpcr-base')) conf.set('TPM2_NVPCR_BASE', get_option('tpm2-nvpcr-base'))
libdw = dependency('libdw', libdw = dependency('libdw',
version : '>=0.177',
required : get_option('elfutils')) required : get_option('elfutils'))
libdw_cflags = libdw.partial_dependency(includes: true, compile_args: true) libdw_cflags = libdw.partial_dependency(includes: true, compile_args: true)
libelf = dependency('libelf', libelf = dependency('libelf',
@ -1388,10 +1379,6 @@ libelf = dependency('libelf',
libelf_cflags = libelf.partial_dependency(includes: true, compile_args: true) libelf_cflags = libelf.partial_dependency(includes: true, compile_args: true)
conf.set10('HAVE_ELFUTILS', libdw.found() and libelf.found()) conf.set10('HAVE_ELFUTILS', libdw.found() and libelf.found())
# New in elfutils 0.177
conf.set10('HAVE_DWELF_ELF_E_MACHINE_STRING',
libdw.found() and cc.has_function('dwelf_elf_e_machine_string', dependencies : libdw))
# New in elfutils 0.192 # New in elfutils 0.192
conf.set10('HAVE_DWFL_SET_SYSROOT', conf.set10('HAVE_DWFL_SET_SYSROOT',
libdw.found() and cc.has_function('dwfl_set_sysroot', dependencies : libdw)) libdw.found() and cc.has_function('dwfl_set_sysroot', dependencies : libdw))

View File

@ -29,7 +29,7 @@ _systemd_vmspawn() {
local i verb comps local i verb comps
local -A OPTS=( local -A OPTS=(
[STANDALONE]='-h --help --version -q --quiet --no-pager -n --network-tap --network-user-mode' [STANDALONE]='-h --help --version -q --quiet --no-pager -n --network-tap --network-user-mode --user --system'
[PATH]='-D --directory -i --image --linux --initrd --extra-drive --forward-journal' [PATH]='-D --directory -i --image --linux --initrd --extra-drive --forward-journal'
[BOOL]='--kvm --vsock --tpm --secure-boot --discard-disk --register --pass-ssh-key' [BOOL]='--kvm --vsock --tpm --secure-boot --discard-disk --register --pass-ssh-key'
[FIRMWARE]='--firmware' [FIRMWARE]='--firmware'

View File

@ -317,7 +317,6 @@ DECLARE_STRING_TABLE_LOOKUP(unit_type, UnitType);
void unit_types_list(void); void unit_types_list(void);
DECLARE_STRING_TABLE_LOOKUP(unit_load_state, UnitLoadState); DECLARE_STRING_TABLE_LOOKUP(unit_load_state, UnitLoadState);
DECLARE_STRING_TABLE_LOOKUP(unit_active_state, UnitActiveState); DECLARE_STRING_TABLE_LOOKUP(unit_active_state, UnitActiveState);
DECLARE_STRING_TABLE_LOOKUP(freezer_state, FreezerState); DECLARE_STRING_TABLE_LOOKUP(freezer_state, FreezerState);
@ -325,35 +324,20 @@ FreezerState freezer_state_finish(FreezerState state) _const_;
FreezerState freezer_state_objective(FreezerState state) _const_; FreezerState freezer_state_objective(FreezerState state) _const_;
DECLARE_STRING_TABLE_LOOKUP(unit_marker, UnitMarker); DECLARE_STRING_TABLE_LOOKUP(unit_marker, UnitMarker);
DECLARE_STRING_TABLE_LOOKUP(automount_state, AutomountState); DECLARE_STRING_TABLE_LOOKUP(automount_state, AutomountState);
DECLARE_STRING_TABLE_LOOKUP(device_state, DeviceState); DECLARE_STRING_TABLE_LOOKUP(device_state, DeviceState);
DECLARE_STRING_TABLE_LOOKUP(mount_state, MountState); DECLARE_STRING_TABLE_LOOKUP(mount_state, MountState);
DECLARE_STRING_TABLE_LOOKUP(path_state, PathState); DECLARE_STRING_TABLE_LOOKUP(path_state, PathState);
DECLARE_STRING_TABLE_LOOKUP(scope_state, ScopeState); DECLARE_STRING_TABLE_LOOKUP(scope_state, ScopeState);
DECLARE_STRING_TABLE_LOOKUP(service_state, ServiceState); DECLARE_STRING_TABLE_LOOKUP(service_state, ServiceState);
DECLARE_STRING_TABLE_LOOKUP(slice_state, SliceState); DECLARE_STRING_TABLE_LOOKUP(slice_state, SliceState);
DECLARE_STRING_TABLE_LOOKUP(socket_state, SocketState); DECLARE_STRING_TABLE_LOOKUP(socket_state, SocketState);
DECLARE_STRING_TABLE_LOOKUP(swap_state, SwapState); DECLARE_STRING_TABLE_LOOKUP(swap_state, SwapState);
DECLARE_STRING_TABLE_LOOKUP(target_state, TargetState); DECLARE_STRING_TABLE_LOOKUP(target_state, TargetState);
DECLARE_STRING_TABLE_LOOKUP(timer_state, TimerState); DECLARE_STRING_TABLE_LOOKUP(timer_state, TimerState);
DECLARE_STRING_TABLE_LOOKUP(unit_dependency, UnitDependency); DECLARE_STRING_TABLE_LOOKUP(unit_dependency, UnitDependency);
DECLARE_STRING_TABLE_LOOKUP(notify_access, NotifyAccess); DECLARE_STRING_TABLE_LOOKUP(notify_access, NotifyAccess);
DECLARE_STRING_TABLE_LOOKUP(job_mode, JobMode); DECLARE_STRING_TABLE_LOOKUP(job_mode, JobMode);
DECLARE_STRING_TABLE_LOOKUP(exec_directory_type, ExecDirectoryType); DECLARE_STRING_TABLE_LOOKUP(exec_directory_type, ExecDirectoryType);
Glyph unit_active_state_to_glyph(UnitActiveState state); Glyph unit_active_state_to_glyph(UnitActiveState state);

View File

@ -1673,7 +1673,7 @@ static int apply_syscall_filter(const ExecContext *c, const ExecParameters *p) {
if (skip_seccomp_unavailable("SystemCallFilter=")) if (skip_seccomp_unavailable("SystemCallFilter="))
return 0; return 0;
negative_action = c->syscall_errno == SECCOMP_ERROR_NUMBER_KILL ? 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;
@ -1694,9 +1694,7 @@ static int apply_syscall_filter(const ExecContext *c, const ExecParameters *p) {
} }
static int apply_syscall_log(const ExecContext *c, const ExecParameters *p) { static int apply_syscall_log(const ExecContext *c, const ExecParameters *p) {
#ifdef SCMP_ACT_LOG
uint32_t default_action, action; uint32_t default_action, action;
#endif
assert(c); assert(c);
assert(p); assert(p);
@ -1704,7 +1702,6 @@ static int apply_syscall_log(const ExecContext *c, const ExecParameters *p) {
if (!context_has_syscall_logs(c)) if (!context_has_syscall_logs(c))
return 0; return 0;
#ifdef SCMP_ACT_LOG
if (skip_seccomp_unavailable("SystemCallLog=")) if (skip_seccomp_unavailable("SystemCallLog="))
return 0; return 0;
@ -1719,11 +1716,6 @@ static int apply_syscall_log(const ExecContext *c, const ExecParameters *p) {
} }
return seccomp_load_syscall_filter_set_raw(default_action, c->syscall_log, action, false); return seccomp_load_syscall_filter_set_raw(default_action, c->syscall_log, action, false);
#else
/* old libseccomp */
log_debug( "SECCOMP feature SCMP_ACT_LOG not available, skipping SystemCallLog=");
return 0;
#endif
} }
static int apply_syscall_archs(const ExecContext *c, const ExecParameters *p) { static int apply_syscall_archs(const ExecContext *c, const ExecParameters *p) {

View File

@ -331,11 +331,8 @@ static int parse_one_option(const char *option) {
arg_no_write_workqueue = true; arg_no_write_workqueue = true;
else if (streq(option, "luks")) else if (streq(option, "luks"))
arg_type = ANY_LUKS; arg_type = ANY_LUKS;
/* since cryptsetup 2.3.0 (Feb 2020) */
#ifdef CRYPT_BITLK
else if (streq(option, "bitlk")) else if (streq(option, "bitlk"))
arg_type = CRYPT_BITLK; arg_type = CRYPT_BITLK;
#endif
else if (streq(option, "tcrypt")) else if (streq(option, "tcrypt"))
arg_type = CRYPT_TCRYPT; arg_type = CRYPT_TCRYPT;
else if (STR_IN_SET(option, "tcrypt-hidden", "tcrypthidden")) { else if (STR_IN_SET(option, "tcrypt-hidden", "tcrypthidden")) {
@ -2492,11 +2489,9 @@ static uint32_t determine_flags(void) {
if (arg_no_write_workqueue) if (arg_no_write_workqueue)
flags |= CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE; flags |= CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE;
#ifdef CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF
/* Try to decrease the risk of OOM event if memory hard key derivation function is in use */ /* Try to decrease the risk of OOM event if memory hard key derivation function is in use */
/* https://gitlab.com/cryptsetup/cryptsetup/issues/446/ */ /* https://gitlab.com/cryptsetup/cryptsetup/issues/446/ */
flags |= CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF; flags |= CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF;
#endif
return flags; return flags;
} }
@ -2672,14 +2667,11 @@ static int verb_attach(int argc, char *argv[], void *userdata) {
} }
} }
/* since cryptsetup 2.3.0 (Feb 2020) */
#ifdef CRYPT_BITLK
if (streq_ptr(arg_type, CRYPT_BITLK)) { if (streq_ptr(arg_type, CRYPT_BITLK)) {
r = crypt_load(cd, CRYPT_BITLK, NULL); r = crypt_load(cd, CRYPT_BITLK, NULL);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to load Bitlocker superblock on device %s: %m", crypt_get_device_name(cd)); return log_error_errno(r, "Failed to load Bitlocker superblock on device %s: %m", crypt_get_device_name(cd));
} }
#endif
bool use_cached_passphrase = true, try_discover_key = !key_file; bool use_cached_passphrase = true, try_discover_key = !key_file;
const char *discovered_key_fn = strjoina(volume, ".key"); const char *discovered_key_fn = strjoina(volume, ".key");

View File

@ -94,10 +94,12 @@ static void route_nexthop_hash_func_full(const RouteNextHop *nh, struct siphash
/* See nh_comp() in net/ipv4/fib_semantics.c of the kernel. */ /* See nh_comp() in net/ipv4/fib_semantics.c of the kernel. */
siphash24_compress_typesafe(nh->family, state); siphash24_compress_typesafe(nh->family, state);
if (!IN_SET(nh->family, AF_INET, AF_INET6))
return;
/* For device-only nexthops parsed from config, family is AF_UNSPEC until verification.
* We still need to hash weight/ifindex/ifname to distinguish different device-only entries. */
if (IN_SET(nh->family, AF_INET, AF_INET6))
in_addr_hash_func(&nh->gw, nh->family, state); in_addr_hash_func(&nh->gw, nh->family, state);
if (with_weight) if (with_weight)
siphash24_compress_typesafe(nh->weight, state); siphash24_compress_typesafe(nh->weight, state);
siphash24_compress_typesafe(nh->ifindex, state); siphash24_compress_typesafe(nh->ifindex, state);
@ -115,12 +117,13 @@ static int route_nexthop_compare_func_full(const RouteNextHop *a, const RouteNex
if (r != 0) if (r != 0)
return r; return r;
if (!IN_SET(a->family, AF_INET, AF_INET6)) /* For device-only nexthops parsed from config, family is AF_UNSPEC until verification.
return 0; * We still need to compare weight/ifindex/ifname to distinguish different device-only entries. */
if (IN_SET(a->family, AF_INET, AF_INET6)) {
r = memcmp(&a->gw, &b->gw, FAMILY_ADDRESS_SIZE(a->family)); r = memcmp(&a->gw, &b->gw, FAMILY_ADDRESS_SIZE(a->family));
if (r != 0) if (r != 0)
return r; return r;
}
if (with_weight) { if (with_weight) {
r = CMP(a->weight, b->weight); r = CMP(a->weight, b->weight);
@ -553,6 +556,9 @@ static int append_nexthop_one(const Route *route, const RouteNextHop *nh, struct
(*rta)->rta_len += sizeof(struct rtnexthop); (*rta)->rta_len += sizeof(struct rtnexthop);
/* For device-only nexthops, skip RTA_GATEWAY entirely. The kernel will use the
* interface specified in rtnh_ifindex without requiring a gateway address. */
if (in_addr_is_set(nh->family, &nh->gw)) {
if (nh->family == route->family) { if (nh->family == route->family) {
r = rtattr_append_attribute(rta, RTA_GATEWAY, &nh->gw, FAMILY_ADDRESS_SIZE(nh->family)); r = rtattr_append_attribute(rta, RTA_GATEWAY, &nh->gw, FAMILY_ADDRESS_SIZE(nh->family));
if (r < 0) if (r < 0)
@ -577,6 +583,7 @@ static int append_nexthop_one(const Route *route, const RouteNextHop *nh, struct
} else if (nh->family == AF_INET) } else if (nh->family == AF_INET)
assert_not_reached(); assert_not_reached();
}
return 0; return 0;
@ -1080,12 +1087,17 @@ int config_parse_multipath_route(
} }
} }
if (isempty(word)) {
if (!dev)
return log_syntax_parse_error(unit, filename, line, SYNTHETIC_ERRNO(EINVAL), lvalue, rvalue);
} else {
r = in_addr_from_string_auto(word, &nh->family, &nh->gw); r = in_addr_from_string_auto(word, &nh->family, &nh->gw);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid multipath route gateway '%s', ignoring assignment: %m", rvalue); "Invalid multipath route gateway '%s', ignoring assignment: %m", rvalue);
return 0; return 0;
} }
}
if (!isempty(p)) { if (!isempty(p)) {
r = safe_atou32(p, &nh->weight); r = safe_atou32(p, &nh->weight);

View File

@ -6,6 +6,8 @@
#include "networkd-address.h" #include "networkd-address.h"
#include "networkd-manager.h" #include "networkd-manager.h"
#include "networkd-network.h" #include "networkd-network.h"
#include "networkd-route-nexthop.h"
#include "ordered-set.h"
#include "set.h" #include "set.h"
#include "strv.h" #include "strv.h"
#include "tests.h" #include "tests.h"
@ -263,4 +265,163 @@ TEST(config_parse_match_strv) {
"KEY3=val with \\quotation\\"))); "KEY3=val with \\quotation\\")));
} }
static int parse_mpr(const char *rvalue, OrderedSet **nexthops) {
return config_parse_multipath_route(
"network", "filename", 1, "section", 1, "MultiPathRoute", 0, rvalue, nexthops, NULL);
}
static void test_config_parse_multipath_route_one(const char *rvalue, int expected_ret, size_t expected_size) {
_cleanup_ordered_set_free_ OrderedSet *nexthops = NULL;
ASSERT_OK_EQ(parse_mpr(rvalue, &nexthops), expected_ret);
ASSERT_EQ(ordered_set_size(nexthops), expected_size);
}
static void test_config_parse_multipath_route_verify(
const char *rvalue,
int expected_family,
const char *expected_gw,
const char *expected_ifname,
int expected_ifindex,
uint32_t expected_weight) {
_cleanup_ordered_set_free_ OrderedSet *nexthops = NULL;
RouteNextHop *nh;
ASSERT_OK_EQ(parse_mpr(rvalue, &nexthops), 1);
ASSERT_EQ(ordered_set_size(nexthops), 1u);
ASSERT_NOT_NULL(nh = ordered_set_first(nexthops));
ASSERT_EQ(nh->family, expected_family);
if (expected_gw) {
union in_addr_union gw;
ASSERT_OK(in_addr_from_string(expected_family, expected_gw, &gw));
ASSERT_EQ(memcmp(&nh->gw, &gw, FAMILY_ADDRESS_SIZE(expected_family)), 0);
} else
ASSERT_FALSE(in_addr_is_set(nh->family, &nh->gw));
ASSERT_STREQ(nh->ifname, expected_ifname);
ASSERT_EQ(nh->ifindex, expected_ifindex);
ASSERT_EQ(nh->weight, expected_weight);
}
TEST(config_parse_multipath_route) {
_cleanup_ordered_set_free_ OrderedSet *nexthops = NULL;
/* Device only routes */
test_config_parse_multipath_route_verify("@wg0", AF_UNSPEC, NULL, "wg0", 0, 0);
test_config_parse_multipath_route_verify("@wg0 10", AF_UNSPEC, NULL, "wg0", 0, 9);
test_config_parse_multipath_route_verify("@eth0 255", AF_UNSPEC, NULL, "eth0", 0, 254);
test_config_parse_multipath_route_verify("@1 15", AF_UNSPEC, NULL, NULL, 1, 14);
/* Gateway with device */
test_config_parse_multipath_route_verify("10.0.0.1@eth0", AF_INET, "10.0.0.1", "eth0", 0, 0);
test_config_parse_multipath_route_verify("10.0.0.1@eth0 20", AF_INET, "10.0.0.1", "eth0", 0, 19);
test_config_parse_multipath_route_verify("2001:db8::1@wg0 15", AF_INET6, "2001:db8::1", "wg0", 0, 14);
/* Gateway without device */
test_config_parse_multipath_route_verify("192.168.1.1", AF_INET, "192.168.1.1", NULL, 0, 0);
test_config_parse_multipath_route_verify("192.168.1.1 100", AF_INET, "192.168.1.1", NULL, 0, 99);
test_config_parse_multipath_route_verify("fe80::1", AF_INET6, "fe80::1", NULL, 0, 0);
/* Interface index instead of name */
test_config_parse_multipath_route_verify("10.0.0.1@5", AF_INET, "10.0.0.1", NULL, 5, 0);
test_config_parse_multipath_route_verify("@10", AF_UNSPEC, NULL, NULL, 10, 0);
test_config_parse_multipath_route_verify("@10 50", AF_UNSPEC, NULL, NULL, 10, 49);
/* Empty value clears nexthops */
ASSERT_OK_EQ(parse_mpr("@wg0 15", &nexthops), 1);
ASSERT_EQ(ordered_set_size(nexthops), 1u);
ASSERT_OK_EQ(parse_mpr("", &nexthops), 1);
ASSERT_NULL(nexthops);
/* Make sure device-only/AF_UNSPEC routes do not collapse into a single entry. */
/* Different interfaces, same weight */
ASSERT_OK_EQ(parse_mpr("@wg0 15", &nexthops), 1);
ASSERT_EQ(ordered_set_size(nexthops), 1u);
ASSERT_OK_EQ(parse_mpr("@wg1 15", &nexthops), 1);
ASSERT_EQ(ordered_set_size(nexthops), 2u);
/* Same interface, different weights */
ASSERT_OK_EQ(parse_mpr("@eth0 10", &nexthops), 1);
ASSERT_OK_EQ(parse_mpr("@eth0 20", &nexthops), 1);
ASSERT_EQ(ordered_set_size(nexthops), 4u);
/* Interface name vs interface index */
ASSERT_OK_EQ(parse_mpr("@5 15", &nexthops), 1);
ASSERT_EQ(ordered_set_size(nexthops), 5u);
/* Mixing device-only and gateway routes */
ASSERT_OK_EQ(parse_mpr("10.0.0.1@eth0 20", &nexthops), 1);
ASSERT_OK_EQ(parse_mpr("192.168.1.1 30", &nexthops), 1);
ASSERT_EQ(ordered_set_size(nexthops), 7u);
/* Large interface index */
ASSERT_OK_EQ(parse_mpr("@999999 10", &nexthops), 1);
ASSERT_EQ(ordered_set_size(nexthops), 8u);
/* IPv4 and IPv6 mixing */
ASSERT_OK_EQ(parse_mpr("2001:db8::1@eth0 20", &nexthops), 1);
ASSERT_EQ(ordered_set_size(nexthops), 9u);
/* Default weight handling */
ASSERT_OK_EQ(parse_mpr("@wg2", &nexthops), 1);
ASSERT_OK_EQ(parse_mpr("@wg3", &nexthops), 1);
ASSERT_EQ(ordered_set_size(nexthops), 11u);
nexthops = ordered_set_free(nexthops);
/* Insertion order does not affect deduplication */
_cleanup_ordered_set_free_ OrderedSet *nexthops2 = NULL;
ASSERT_OK_EQ(parse_mpr("@wg0 10", &nexthops), 1);
ASSERT_OK_EQ(parse_mpr("@wg1 20", &nexthops), 1);
ASSERT_OK_EQ(parse_mpr("@wg1 20", &nexthops2), 1);
ASSERT_OK_EQ(parse_mpr("@wg0 10", &nexthops2), 1);
ASSERT_EQ(ordered_set_size(nexthops), 2u);
ASSERT_EQ(ordered_set_size(nexthops2), 2u);
nexthops = ordered_set_free(nexthops);
/* Duplicate routes should be detected and rejected with a warning. */
/* Exact duplicates are rejected */
ASSERT_OK_EQ(parse_mpr("@wg0 15", &nexthops), 1);
ASSERT_EQ(ordered_set_size(nexthops), 1u);
ASSERT_OK_EQ(parse_mpr("@wg0 15", &nexthops), 0);
ASSERT_EQ(ordered_set_size(nexthops), 1u);
nexthops = ordered_set_free(nexthops);
/* Default weight vs explicit weight=1 are treated as identical */
ASSERT_OK_EQ(parse_mpr("@eth0", &nexthops), 1);
ASSERT_EQ(ordered_set_size(nexthops), 1u);
ASSERT_OK_EQ(parse_mpr("@eth0 1", &nexthops), 0);
ASSERT_EQ(ordered_set_size(nexthops), 1u);
nexthops = ordered_set_free(nexthops);
/* Weight=1 then default weight (reverse order), still detected as duplicate */
ASSERT_OK_EQ(parse_mpr("@wg0 1", &nexthops), 1);
ASSERT_EQ(ordered_set_size(nexthops), 1u);
ASSERT_OK_EQ(parse_mpr("@wg0", &nexthops), 0);
ASSERT_EQ(ordered_set_size(nexthops), 1u);
nexthops = ordered_set_free(nexthops);
/* Device-only vs gateway with device are semantically distinct, both accepted */
ASSERT_OK_EQ(parse_mpr("@eth0 10", &nexthops), 1);
ASSERT_OK_EQ(parse_mpr("10.0.0.1@eth0 10", &nexthops), 1);
ASSERT_EQ(ordered_set_size(nexthops), 2u);
/* Invalid input should be rejected */
/* Invalid gateway addresses */
test_config_parse_multipath_route_one("999.999.999.999", 0, 0);
test_config_parse_multipath_route_one("not-an-ip", 0, 0);
test_config_parse_multipath_route_one("10", 0, 0);
/* Invalid weights */
test_config_parse_multipath_route_one("@wg0 0", 0, 0); /* Weight 0 */
test_config_parse_multipath_route_one("@wg0 257", 0, 0); /* Weight > 256 */
test_config_parse_multipath_route_one("@wg0 -1", 0, 0); /* Negative */
test_config_parse_multipath_route_one("@wg0 abc", 0, 0); /* Non-numeric */
}
DEFINE_TEST_MAIN(LOG_INFO); DEFINE_TEST_MAIN(LOG_INFO);

View File

@ -1554,15 +1554,9 @@ static int oci_seccomp_action_from_string(const char *name, uint32_t *ret) {
{ "SCMP_ACT_ALLOW", SCMP_ACT_ALLOW }, { "SCMP_ACT_ALLOW", SCMP_ACT_ALLOW },
{ "SCMP_ACT_ERRNO", SCMP_ACT_ERRNO(EPERM) }, /* the OCI spec doesn't document the error, but it appears EPERM is supposed to be used */ { "SCMP_ACT_ERRNO", SCMP_ACT_ERRNO(EPERM) }, /* the OCI spec doesn't document the error, but it appears EPERM is supposed to be used */
{ "SCMP_ACT_KILL", SCMP_ACT_KILL }, { "SCMP_ACT_KILL", SCMP_ACT_KILL },
#ifdef SCMP_ACT_KILL_PROCESS
{ "SCMP_ACT_KILL_PROCESS", SCMP_ACT_KILL_PROCESS }, { "SCMP_ACT_KILL_PROCESS", SCMP_ACT_KILL_PROCESS },
#endif
#ifdef SCMP_ACT_KILL_THREAD
{ "SCMP_ACT_KILL_THREAD", SCMP_ACT_KILL_THREAD }, { "SCMP_ACT_KILL_THREAD", SCMP_ACT_KILL_THREAD },
#endif
#ifdef SCMP_ACT_LOG
{ "SCMP_ACT_LOG", SCMP_ACT_LOG }, { "SCMP_ACT_LOG", SCMP_ACT_LOG },
#endif
{ "SCMP_ACT_TRAP", SCMP_ACT_TRAP }, { "SCMP_ACT_TRAP", SCMP_ACT_TRAP },
/* We don't support SCMP_ACT_TRACE because that requires a tracer, and that doesn't really make sense /* We don't support SCMP_ACT_TRACE because that requires a tracer, and that doesn't really make sense
@ -1596,12 +1590,8 @@ static int oci_seccomp_arch_from_string(const char *name, uint32_t *ret) {
{ "SCMP_ARCH_MIPSEL64", SCMP_ARCH_MIPSEL64 }, { "SCMP_ARCH_MIPSEL64", SCMP_ARCH_MIPSEL64 },
{ "SCMP_ARCH_MIPSEL64N32", SCMP_ARCH_MIPSEL64N32 }, { "SCMP_ARCH_MIPSEL64N32", SCMP_ARCH_MIPSEL64N32 },
{ "SCMP_ARCH_NATIVE", SCMP_ARCH_NATIVE }, { "SCMP_ARCH_NATIVE", SCMP_ARCH_NATIVE },
#ifdef SCMP_ARCH_PARISC
{ "SCMP_ARCH_PARISC", SCMP_ARCH_PARISC }, { "SCMP_ARCH_PARISC", SCMP_ARCH_PARISC },
#endif
#ifdef SCMP_ARCH_PARISC64
{ "SCMP_ARCH_PARISC64", SCMP_ARCH_PARISC64 }, { "SCMP_ARCH_PARISC64", SCMP_ARCH_PARISC64 },
#endif
{ "SCMP_ARCH_PPC", SCMP_ARCH_PPC }, { "SCMP_ARCH_PPC", SCMP_ARCH_PPC },
{ "SCMP_ARCH_PPC64", SCMP_ARCH_PPC64 }, { "SCMP_ARCH_PPC64", SCMP_ARCH_PPC64 },
{ "SCMP_ARCH_PPC64LE", SCMP_ARCH_PPC64LE }, { "SCMP_ARCH_PPC64LE", SCMP_ARCH_PPC64LE },

View File

@ -5442,11 +5442,7 @@ static int partition_encrypt(Context *context, Partition *p, PartitionTarget *ta
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to load reencryption context: %m"); return log_error_errno(r, "Failed to load reencryption context: %m");
#if HAVE_CRYPT_REENCRYPT_RUN
r = sym_crypt_reencrypt_run(cd, NULL, NULL); r = sym_crypt_reencrypt_run(cd, NULL, NULL);
#else
r = sym_crypt_reencrypt(cd, NULL);
#endif
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to encrypt %s: %m", node); return log_error_errno(r, "Failed to encrypt %s: %m", node);
} else { } else {
@ -5507,7 +5503,7 @@ static int partition_encrypt(Context *context, Partition *p, PartitionTarget *ta
return 0; return 0;
#else #else
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"libcryptsetup is not supported or is missing required symbols, cannot encrypt."); "libcryptsetup is not supported, cannot encrypt.");
#endif #endif
} }

View File

@ -17,7 +17,7 @@
#include "string-util.h" #include "string-util.h"
#include "time-util.h" #include "time-util.h"
#if HAVE_OPENSSL && OPENSSL_VERSION_MAJOR >= 3 #if HAVE_OPENSSL
DISABLE_WARNING_DEPRECATED_DECLARATIONS; DISABLE_WARNING_DEPRECATED_DECLARATIONS;
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(RSA*, RSA_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(RSA*, RSA_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EC_KEY*, EC_KEY_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EC_KEY*, EC_KEY_free, NULL);

View File

@ -39,11 +39,7 @@ DLSYM_PROTOTYPE(crypt_keyslot_max) = NULL;
DLSYM_PROTOTYPE(crypt_load) = NULL; DLSYM_PROTOTYPE(crypt_load) = NULL;
DLSYM_PROTOTYPE(crypt_metadata_locking) = NULL; DLSYM_PROTOTYPE(crypt_metadata_locking) = NULL;
DLSYM_PROTOTYPE(crypt_reencrypt_init_by_passphrase) = NULL; DLSYM_PROTOTYPE(crypt_reencrypt_init_by_passphrase) = NULL;
#if HAVE_CRYPT_REENCRYPT_RUN
DLSYM_PROTOTYPE(crypt_reencrypt_run); DLSYM_PROTOTYPE(crypt_reencrypt_run);
#else
DLSYM_PROTOTYPE(crypt_reencrypt);
#endif
DLSYM_PROTOTYPE(crypt_resize) = NULL; DLSYM_PROTOTYPE(crypt_resize) = NULL;
DLSYM_PROTOTYPE(crypt_resume_by_volume_key) = NULL; DLSYM_PROTOTYPE(crypt_resume_by_volume_key) = NULL;
DLSYM_PROTOTYPE(crypt_set_data_device) = NULL; DLSYM_PROTOTYPE(crypt_set_data_device) = NULL;
@ -55,15 +51,7 @@ DLSYM_PROTOTYPE(crypt_set_pbkdf_type) = NULL;
DLSYM_PROTOTYPE(crypt_suspend) = NULL; DLSYM_PROTOTYPE(crypt_suspend) = NULL;
DLSYM_PROTOTYPE(crypt_token_json_get) = NULL; DLSYM_PROTOTYPE(crypt_token_json_get) = NULL;
DLSYM_PROTOTYPE(crypt_token_json_set) = NULL; DLSYM_PROTOTYPE(crypt_token_json_set) = NULL;
#if HAVE_CRYPT_TOKEN_MAX
DLSYM_PROTOTYPE(crypt_token_max) = NULL; DLSYM_PROTOTYPE(crypt_token_max) = NULL;
#else
int crypt_token_max(_unused_ const char *type) {
assert(streq(type, CRYPT_LUKS2));
return 32;
}
#endif
#if HAVE_CRYPT_TOKEN_SET_EXTERNAL_PATH #if HAVE_CRYPT_TOKEN_SET_EXTERNAL_PATH
DLSYM_PROTOTYPE(crypt_token_set_external_path) = NULL; DLSYM_PROTOTYPE(crypt_token_set_external_path) = NULL;
#endif #endif
@ -252,11 +240,7 @@ int dlopen_cryptsetup(void) {
DLSYM_ARG(crypt_load), DLSYM_ARG(crypt_load),
DLSYM_ARG(crypt_metadata_locking), DLSYM_ARG(crypt_metadata_locking),
DLSYM_ARG(crypt_reencrypt_init_by_passphrase), DLSYM_ARG(crypt_reencrypt_init_by_passphrase),
#if HAVE_CRYPT_REENCRYPT_RUN
DLSYM_ARG(crypt_reencrypt_run), DLSYM_ARG(crypt_reencrypt_run),
#else
DLSYM_ARG(crypt_reencrypt),
#endif
DLSYM_ARG(crypt_resize), DLSYM_ARG(crypt_resize),
DLSYM_ARG(crypt_resume_by_volume_key), DLSYM_ARG(crypt_resume_by_volume_key),
DLSYM_ARG(crypt_set_data_device), DLSYM_ARG(crypt_set_data_device),
@ -268,9 +252,7 @@ int dlopen_cryptsetup(void) {
DLSYM_ARG(crypt_suspend), DLSYM_ARG(crypt_suspend),
DLSYM_ARG(crypt_token_json_get), DLSYM_ARG(crypt_token_json_get),
DLSYM_ARG(crypt_token_json_set), DLSYM_ARG(crypt_token_json_set),
#if HAVE_CRYPT_TOKEN_MAX
DLSYM_ARG(crypt_token_max), DLSYM_ARG(crypt_token_max),
#endif
#if HAVE_CRYPT_TOKEN_SET_EXTERNAL_PATH #if HAVE_CRYPT_TOKEN_SET_EXTERNAL_PATH
DLSYM_ARG(crypt_token_set_external_path), DLSYM_ARG(crypt_token_set_external_path),
#endif #endif

View File

@ -7,14 +7,6 @@
#if HAVE_LIBCRYPTSETUP #if HAVE_LIBCRYPTSETUP
#include <libcryptsetup.h> /* IWYU pragma: export */ #include <libcryptsetup.h> /* IWYU pragma: export */
/* These next two are defined in libcryptsetup.h from cryptsetup version 2.3.4 forwards. */
#ifndef CRYPT_ACTIVATE_NO_READ_WORKQUEUE
#define CRYPT_ACTIVATE_NO_READ_WORKQUEUE (1 << 24)
#endif
#ifndef CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE
#define CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE (1 << 25)
#endif
extern DLSYM_PROTOTYPE(crypt_activate_by_passphrase); extern DLSYM_PROTOTYPE(crypt_activate_by_passphrase);
extern DLSYM_PROTOTYPE(crypt_activate_by_signed_key); extern DLSYM_PROTOTYPE(crypt_activate_by_signed_key);
extern DLSYM_PROTOTYPE(crypt_activate_by_volume_key); extern DLSYM_PROTOTYPE(crypt_activate_by_volume_key);
@ -39,11 +31,7 @@ extern DLSYM_PROTOTYPE(crypt_keyslot_max);
extern DLSYM_PROTOTYPE(crypt_load); extern DLSYM_PROTOTYPE(crypt_load);
extern DLSYM_PROTOTYPE(crypt_metadata_locking); extern DLSYM_PROTOTYPE(crypt_metadata_locking);
extern DLSYM_PROTOTYPE(crypt_reencrypt_init_by_passphrase); extern DLSYM_PROTOTYPE(crypt_reencrypt_init_by_passphrase);
#if HAVE_CRYPT_REENCRYPT_RUN
extern DLSYM_PROTOTYPE(crypt_reencrypt_run); extern DLSYM_PROTOTYPE(crypt_reencrypt_run);
#else
extern DLSYM_PROTOTYPE(crypt_reencrypt);
#endif
extern DLSYM_PROTOTYPE(crypt_resize); extern DLSYM_PROTOTYPE(crypt_resize);
extern DLSYM_PROTOTYPE(crypt_resume_by_volume_key); extern DLSYM_PROTOTYPE(crypt_resume_by_volume_key);
extern DLSYM_PROTOTYPE(crypt_set_data_device); extern DLSYM_PROTOTYPE(crypt_set_data_device);
@ -55,13 +43,7 @@ extern DLSYM_PROTOTYPE(crypt_set_pbkdf_type);
extern DLSYM_PROTOTYPE(crypt_suspend); extern DLSYM_PROTOTYPE(crypt_suspend);
extern DLSYM_PROTOTYPE(crypt_token_json_get); extern DLSYM_PROTOTYPE(crypt_token_json_get);
extern DLSYM_PROTOTYPE(crypt_token_json_set); extern DLSYM_PROTOTYPE(crypt_token_json_set);
#if HAVE_CRYPT_TOKEN_MAX
extern DLSYM_PROTOTYPE(crypt_token_max); extern DLSYM_PROTOTYPE(crypt_token_max);
#else
/* As a fallback, use the same hard-coded value libcryptsetup uses internally. */
int crypt_token_max(_unused_ const char *type);
#define sym_crypt_token_max(type) crypt_token_max(type)
#endif
#if HAVE_CRYPT_TOKEN_SET_EXTERNAL_PATH #if HAVE_CRYPT_TOKEN_SET_EXTERNAL_PATH
extern DLSYM_PROTOTYPE(crypt_token_set_external_path); extern DLSYM_PROTOTYPE(crypt_token_set_external_path);
#endif #endif

View File

@ -47,9 +47,7 @@ static DLSYM_PROTOTYPE(dwarf_formstring) = NULL;
static DLSYM_PROTOTYPE(dwarf_getscopes) = NULL; static DLSYM_PROTOTYPE(dwarf_getscopes) = NULL;
static DLSYM_PROTOTYPE(dwarf_getscopes_die) = NULL; static DLSYM_PROTOTYPE(dwarf_getscopes_die) = NULL;
static DLSYM_PROTOTYPE(dwelf_elf_begin) = NULL; static DLSYM_PROTOTYPE(dwelf_elf_begin) = NULL;
#if HAVE_DWELF_ELF_E_MACHINE_STRING
static DLSYM_PROTOTYPE(dwelf_elf_e_machine_string) = NULL; static DLSYM_PROTOTYPE(dwelf_elf_e_machine_string) = NULL;
#endif
static DLSYM_PROTOTYPE(dwelf_elf_gnu_build_id) = NULL; static DLSYM_PROTOTYPE(dwelf_elf_gnu_build_id) = NULL;
static DLSYM_PROTOTYPE(dwarf_tag) = NULL; static DLSYM_PROTOTYPE(dwarf_tag) = NULL;
static DLSYM_PROTOTYPE(dwfl_addrmodule) = NULL; static DLSYM_PROTOTYPE(dwfl_addrmodule) = NULL;
@ -111,9 +109,7 @@ int dlopen_dw(void) {
DLSYM_ARG(dwarf_diename), DLSYM_ARG(dwarf_diename),
DLSYM_ARG(dwelf_elf_gnu_build_id), DLSYM_ARG(dwelf_elf_gnu_build_id),
DLSYM_ARG(dwelf_elf_begin), DLSYM_ARG(dwelf_elf_begin),
#if HAVE_DWELF_ELF_E_MACHINE_STRING
DLSYM_ARG(dwelf_elf_e_machine_string), DLSYM_ARG(dwelf_elf_e_machine_string),
#endif
DLSYM_ARG(dwfl_addrmodule), DLSYM_ARG(dwfl_addrmodule),
DLSYM_ARG(dwfl_frame_pc), DLSYM_ARG(dwfl_frame_pc),
DLSYM_ARG(dwfl_module_addrdie), DLSYM_ARG(dwfl_module_addrdie),
@ -773,7 +769,6 @@ static int parse_elf(
if (r < 0) if (r < 0)
return log_warning_errno(r, "Failed to build JSON object: %m"); return log_warning_errno(r, "Failed to build JSON object: %m");
#if HAVE_DWELF_ELF_E_MACHINE_STRING
const char *elf_architecture = sym_dwelf_elf_e_machine_string(elf_header.e_machine); const char *elf_architecture = sym_dwelf_elf_e_machine_string(elf_header.e_machine);
if (elf_architecture) { if (elf_architecture) {
r = sd_json_variant_merge_objectbo( r = sd_json_variant_merge_objectbo(
@ -785,7 +780,6 @@ static int parse_elf(
if (ret) if (ret)
fprintf(c.m.f, "ELF object binary architecture: %s\n", elf_architecture); fprintf(c.m.f, "ELF object binary architecture: %s\n", elf_architecture);
} }
#endif
/* We always at least have the ELF type, so merge that (and possibly the arch). */ /* We always at least have the ELF type, so merge that (and possibly the arch). */
r = sd_json_variant_merge_object(&elf_metadata, package_metadata); r = sd_json_variant_merge_object(&elf_metadata, package_metadata);

View File

@ -97,21 +97,12 @@ int openssl_digest_size(const char *digest_alg, size_t *ret_digest_size) {
assert(digest_alg); assert(digest_alg);
assert(ret_digest_size); assert(ret_digest_size);
#if OPENSSL_VERSION_MAJOR >= 3
_cleanup_(EVP_MD_freep) EVP_MD *md = EVP_MD_fetch(NULL, digest_alg, NULL); _cleanup_(EVP_MD_freep) EVP_MD *md = EVP_MD_fetch(NULL, digest_alg, NULL);
#else
const EVP_MD *md = EVP_get_digestbyname(digest_alg);
#endif
if (!md) if (!md)
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"Digest algorithm '%s' not supported.", digest_alg); "Digest algorithm '%s' not supported.", digest_alg);
size_t digest_size; size_t digest_size = EVP_MD_get_size(md);
#if OPENSSL_VERSION_MAJOR >= 3
digest_size = EVP_MD_get_size(md);
#else
digest_size = EVP_MD_size(md);
#endif
if (digest_size == 0) if (digest_size == 0)
return log_openssl_errors("Failed to get Digest size"); return log_openssl_errors("Failed to get Digest size");
@ -136,11 +127,7 @@ int openssl_digest_many(
assert(ret_digest); assert(ret_digest);
/* ret_digest_size is optional, as caller may already know the digest size */ /* ret_digest_size is optional, as caller may already know the digest size */
#if OPENSSL_VERSION_MAJOR >= 3
_cleanup_(EVP_MD_freep) EVP_MD *md = EVP_MD_fetch(NULL, digest_alg, NULL); _cleanup_(EVP_MD_freep) EVP_MD *md = EVP_MD_fetch(NULL, digest_alg, NULL);
#else
const EVP_MD *md = EVP_get_digestbyname(digest_alg);
#endif
if (!md) if (!md)
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"Digest algorithm '%s' not supported.", digest_alg); "Digest algorithm '%s' not supported.", digest_alg);
@ -196,16 +183,11 @@ int openssl_hmac_many(
assert(ret_digest); assert(ret_digest);
/* ret_digest_size is optional, as caller may already know the digest size */ /* ret_digest_size is optional, as caller may already know the digest size */
#if OPENSSL_VERSION_MAJOR >= 3
_cleanup_(EVP_MD_freep) EVP_MD *md = EVP_MD_fetch(NULL, digest_alg, NULL); _cleanup_(EVP_MD_freep) EVP_MD *md = EVP_MD_fetch(NULL, digest_alg, NULL);
#else
const EVP_MD *md = EVP_get_digestbyname(digest_alg);
#endif
if (!md) if (!md)
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"Digest algorithm '%s' not supported.", digest_alg); "Digest algorithm '%s' not supported.", digest_alg);
#if OPENSSL_VERSION_MAJOR >= 3
_cleanup_(EVP_MAC_freep) EVP_MAC *mac = EVP_MAC_fetch(NULL, "HMAC", NULL); _cleanup_(EVP_MAC_freep) EVP_MAC *mac = EVP_MAC_fetch(NULL, "HMAC", NULL);
if (!mac) if (!mac)
return log_openssl_errors("Failed to create new EVP_MAC"); return log_openssl_errors("Failed to create new EVP_MAC");
@ -227,29 +209,12 @@ int openssl_hmac_many(
if (!EVP_MAC_init(ctx, key, key_size, params)) if (!EVP_MAC_init(ctx, key, key_size, params))
return log_openssl_errors("Failed to initialize EVP_MAC_CTX"); return log_openssl_errors("Failed to initialize EVP_MAC_CTX");
#else
_cleanup_(HMAC_CTX_freep) HMAC_CTX *ctx = HMAC_CTX_new();
if (!ctx)
return log_openssl_errors("Failed to create new HMAC_CTX");
if (!HMAC_Init_ex(ctx, key, key_size, md, NULL))
return log_openssl_errors("Failed to initialize HMAC_CTX");
#endif
for (size_t i = 0; i < n_data; i++) for (size_t i = 0; i < n_data; i++)
#if OPENSSL_VERSION_MAJOR >= 3
if (!EVP_MAC_update(ctx, data[i].iov_base, data[i].iov_len)) if (!EVP_MAC_update(ctx, data[i].iov_base, data[i].iov_len))
#else
if (!HMAC_Update(ctx, data[i].iov_base, data[i].iov_len))
#endif
return log_openssl_errors("Failed to update HMAC"); return log_openssl_errors("Failed to update HMAC");
size_t digest_size; size_t digest_size = EVP_MAC_CTX_get_mac_size(ctx);
#if OPENSSL_VERSION_MAJOR >= 3
digest_size = EVP_MAC_CTX_get_mac_size(ctx);
#else
digest_size = HMAC_size(ctx);
#endif
if (digest_size == 0) if (digest_size == 0)
return log_openssl_errors("Failed to get HMAC digest size"); return log_openssl_errors("Failed to get HMAC digest size");
@ -257,13 +222,8 @@ int openssl_hmac_many(
if (!buf) if (!buf)
return log_oom_debug(); return log_oom_debug();
#if OPENSSL_VERSION_MAJOR >= 3
size_t size; size_t size;
if (!EVP_MAC_final(ctx, buf, &size, digest_size)) if (!EVP_MAC_final(ctx, buf, &size, digest_size))
#else
unsigned size;
if (!HMAC_Final(ctx, buf, &size))
#endif
return log_openssl_errors("Failed to finalize HMAC"); return log_openssl_errors("Failed to finalize HMAC");
assert(size == digest_size); assert(size == digest_size);
@ -306,11 +266,7 @@ int openssl_cipher_many(
if (asprintf(&cipher_alg, "%s-%zu-%s", alg, bits, mode) < 0) if (asprintf(&cipher_alg, "%s-%zu-%s", alg, bits, mode) < 0)
return log_oom_debug(); return log_oom_debug();
#if OPENSSL_VERSION_MAJOR >= 3
_cleanup_(EVP_CIPHER_freep) EVP_CIPHER *cipher = EVP_CIPHER_fetch(NULL, cipher_alg, NULL); _cleanup_(EVP_CIPHER_freep) EVP_CIPHER *cipher = EVP_CIPHER_fetch(NULL, cipher_alg, NULL);
#else
const EVP_CIPHER *cipher = EVP_get_cipherbyname(cipher_alg);
#endif
if (!cipher) if (!cipher)
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"Cipher algorithm '%s' not supported.", cipher_alg); "Cipher algorithm '%s' not supported.", cipher_alg);
@ -391,7 +347,6 @@ int kdf_ss_derive(
size_t derive_size, size_t derive_size,
void **ret) { void **ret) {
#if OPENSSL_VERSION_MAJOR >= 3
assert(digest); assert(digest);
assert(key); assert(key);
assert(derive_size > 0); assert(derive_size > 0);
@ -437,9 +392,6 @@ int kdf_ss_derive(
*ret = TAKE_PTR(buf); *ret = TAKE_PTR(buf);
return 0; return 0;
#else
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "KDF-SS requires OpenSSL >= 3.");
#endif
} }
/* Perform Key-Based HMAC KDF. The mode must be "COUNTER" or "FEEDBACK". The parameter naming is from the /* Perform Key-Based HMAC KDF. The mode must be "COUNTER" or "FEEDBACK". The parameter naming is from the
@ -461,7 +413,6 @@ int kdf_kb_hmac_derive(
size_t derive_size, size_t derive_size,
void **ret) { void **ret) {
#if OPENSSL_VERSION_MAJOR >= 3
assert(mode); assert(mode);
assert(strcaseeq(mode, "COUNTER") || strcaseeq(mode, "FEEDBACK")); assert(strcaseeq(mode, "COUNTER") || strcaseeq(mode, "FEEDBACK"));
assert(digest); assert(digest);
@ -523,9 +474,6 @@ int kdf_kb_hmac_derive(
*ret = TAKE_PTR(buf); *ret = TAKE_PTR(buf);
return 0; return 0;
#else
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "KDF-KB requires OpenSSL >= 3.");
#endif
} }
int rsa_encrypt_bytes( int rsa_encrypt_bytes(
@ -583,11 +531,7 @@ int rsa_oaep_encrypt_bytes(
assert(ret_encrypt_key); assert(ret_encrypt_key);
assert(ret_encrypt_key_size); assert(ret_encrypt_key_size);
#if OPENSSL_VERSION_MAJOR >= 3
_cleanup_(EVP_MD_freep) EVP_MD *md = EVP_MD_fetch(NULL, digest_alg, NULL); _cleanup_(EVP_MD_freep) EVP_MD *md = EVP_MD_fetch(NULL, digest_alg, NULL);
#else
const EVP_MD *md = EVP_get_digestbyname(digest_alg);
#endif
if (!md) if (!md)
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"Digest algorithm '%s' not supported.", digest_alg); "Digest algorithm '%s' not supported.", digest_alg);
@ -672,7 +616,6 @@ int rsa_pkey_from_n_e(const void *n, size_t n_size, const void *e, size_t e_size
assert(e_size != 0); assert(e_size != 0);
assert(ret); assert(ret);
#if OPENSSL_VERSION_MAJOR >= 3
_cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
if (!ctx) if (!ctx)
return log_openssl_errors("Failed to create new EVP_PKEY_CTX"); return log_openssl_errors("Failed to create new EVP_PKEY_CTX");
@ -701,34 +644,6 @@ int rsa_pkey_from_n_e(const void *n, size_t n_size, const void *e, size_t e_size
if (EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0) if (EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0)
return log_openssl_errors("Failed to create RSA EVP_PKEY"); return log_openssl_errors("Failed to create RSA EVP_PKEY");
#else
_cleanup_(BN_freep) BIGNUM *bn_n = BN_bin2bn(n, n_size, NULL);
if (!bn_n)
return log_openssl_errors("Failed to create BIGNUM for RSA n");
_cleanup_(BN_freep) BIGNUM *bn_e = BN_bin2bn(e, e_size, NULL);
if (!bn_e)
return log_openssl_errors("Failed to create BIGNUM for RSA e");
_cleanup_(RSA_freep) RSA *rsa_key = RSA_new();
if (!rsa_key)
return log_openssl_errors("Failed to create new RSA");
if (!RSA_set0_key(rsa_key, bn_n, bn_e, NULL))
return log_openssl_errors("Failed to set RSA n/e");
/* rsa_key owns these now, don't free */
TAKE_PTR(bn_n);
TAKE_PTR(bn_e);
pkey = EVP_PKEY_new();
if (!pkey)
return log_openssl_errors("Failed to create new EVP_PKEY");
if (!EVP_PKEY_assign_RSA(pkey, rsa_key))
return log_openssl_errors("Failed to assign RSA key");
/* pkey owns this now, don't free */
TAKE_PTR(rsa_key);
#endif
*ret = TAKE_PTR(pkey); *ret = TAKE_PTR(pkey);
@ -749,7 +664,6 @@ int rsa_pkey_to_n_e(
assert(ret_e); assert(ret_e);
assert(ret_e_size); assert(ret_e_size);
#if OPENSSL_VERSION_MAJOR >= 3
_cleanup_(BN_freep) BIGNUM *bn_n = NULL; _cleanup_(BN_freep) BIGNUM *bn_n = NULL;
if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &bn_n)) if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &bn_n))
return log_openssl_errors("Failed to get RSA n"); return log_openssl_errors("Failed to get RSA n");
@ -757,19 +671,6 @@ int rsa_pkey_to_n_e(
_cleanup_(BN_freep) BIGNUM *bn_e = NULL; _cleanup_(BN_freep) BIGNUM *bn_e = NULL;
if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &bn_e)) if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &bn_e))
return log_openssl_errors("Failed to get RSA e"); return log_openssl_errors("Failed to get RSA e");
#else
const RSA *rsa = EVP_PKEY_get0_RSA((EVP_PKEY*) pkey);
if (!rsa)
return log_openssl_errors("Failed to get RSA key from public key");
const BIGNUM *bn_n = RSA_get0_n(rsa);
if (!bn_n)
return log_openssl_errors("Failed to get RSA n");
const BIGNUM *bn_e = RSA_get0_e(rsa);
if (!bn_e)
return log_openssl_errors("Failed to get RSA e");
#endif
size_t n_size = BN_num_bytes(bn_n), e_size = BN_num_bytes(bn_e); size_t n_size = BN_num_bytes(bn_n), e_size = BN_num_bytes(bn_e);
_cleanup_free_ void *n = malloc(n_size), *e = malloc(e_size); _cleanup_free_ void *n = malloc(n_size), *e = malloc(e_size);
@ -823,7 +724,6 @@ int ecc_pkey_from_curve_x_y(
if (!EC_POINT_set_affine_coordinates(group, point, bn_x, bn_y, NULL)) if (!EC_POINT_set_affine_coordinates(group, point, bn_x, bn_y, NULL))
return log_openssl_errors("Failed to set ECC coordinates"); return log_openssl_errors("Failed to set ECC coordinates");
#if OPENSSL_VERSION_MAJOR >= 3
if (EVP_PKEY_fromdata_init(ctx) <= 0) if (EVP_PKEY_fromdata_init(ctx) <= 0)
return log_openssl_errors("Failed to initialize EVP_PKEY_CTX"); return log_openssl_errors("Failed to initialize EVP_PKEY_CTX");
@ -850,26 +750,6 @@ int ecc_pkey_from_curve_x_y(
_cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL; _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL;
if (EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0) if (EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0)
return log_openssl_errors("Failed to create ECC EVP_PKEY"); return log_openssl_errors("Failed to create ECC EVP_PKEY");
#else
_cleanup_(EC_KEY_freep) EC_KEY *eckey = EC_KEY_new();
if (!eckey)
return log_openssl_errors("Failed to create new EC_KEY");
if (!EC_KEY_set_group(eckey, group))
return log_openssl_errors("Failed to set ECC group");
if (!EC_KEY_set_public_key(eckey, point))
return log_openssl_errors("Failed to set ECC point");
_cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = EVP_PKEY_new();
if (!pkey)
return log_openssl_errors("Failed to create new EVP_PKEY");
if (!EVP_PKEY_assign_EC_KEY(pkey, eckey))
return log_openssl_errors("Failed to assign ECC key");
/* pkey owns this now, don't free */
TAKE_PTR(eckey);
#endif
*ret = TAKE_PTR(pkey); *ret = TAKE_PTR(pkey);
return 0; return 0;
@ -888,7 +768,6 @@ int ecc_pkey_to_curve_x_y(
assert(pkey); assert(pkey);
#if OPENSSL_VERSION_MAJOR >= 3
size_t name_size; size_t name_size;
if (!EVP_PKEY_get_utf8_string_param(pkey, OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0, &name_size)) if (!EVP_PKEY_get_utf8_string_param(pkey, OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0, &name_size))
return log_openssl_errors("Failed to get ECC group name size"); return log_openssl_errors("Failed to get ECC group name size");
@ -909,31 +788,6 @@ int ecc_pkey_to_curve_x_y(
if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_Y, &bn_y)) if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_Y, &bn_y))
return log_openssl_errors("Failed to get ECC point y"); return log_openssl_errors("Failed to get ECC point y");
#else
const EC_KEY *eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY*) pkey);
if (!eckey)
return log_openssl_errors("Failed to get EC_KEY");
const EC_GROUP *group = EC_KEY_get0_group(eckey);
if (!group)
return log_openssl_errors("Failed to get EC_GROUP");
curve_id = EC_GROUP_get_curve_name(group);
if (curve_id == NID_undef)
return log_openssl_errors("Failed to get ECC curve id");
const EC_POINT *point = EC_KEY_get0_public_key(eckey);
if (!point)
return log_openssl_errors("Failed to get EC_POINT");
bn_x = BN_new();
bn_y = BN_new();
if (!bn_x || !bn_y)
return log_openssl_errors("Failed to create new BIGNUM");
if (!EC_POINT_get_affine_coordinates(group, point, bn_x, bn_y, NULL))
return log_openssl_errors("Failed to get ECC x/y.");
#endif
size_t x_size = BN_num_bytes(bn_x), y_size = BN_num_bytes(bn_y); size_t x_size = BN_num_bytes(bn_x), y_size = BN_num_bytes(bn_y);
_cleanup_free_ void *x = malloc(x_size), *y = malloc(y_size); _cleanup_free_ void *x = malloc(x_size), *y = malloc(y_size);
@ -1247,10 +1101,8 @@ static int ecc_pkey_generate_volume_keys(
_cleanup_(erase_and_freep) void *decrypted_key = NULL; _cleanup_(erase_and_freep) void *decrypted_key = NULL;
_cleanup_free_ unsigned char *saved_key = NULL; _cleanup_free_ unsigned char *saved_key = NULL;
size_t decrypted_key_size, saved_key_size; size_t decrypted_key_size, saved_key_size;
int nid = NID_undef;
int r; int r;
#if OPENSSL_VERSION_MAJOR >= 3
_cleanup_free_ char *curve_name = NULL; _cleanup_free_ char *curve_name = NULL;
size_t len = 0; size_t len = 0;
@ -1265,19 +1117,7 @@ static int ecc_pkey_generate_volume_keys(
if (EVP_PKEY_get_group_name(pkey, curve_name, len, &len) != 1) if (EVP_PKEY_get_group_name(pkey, curve_name, len, &len) != 1)
return log_openssl_errors("Failed to get PKEY group name"); return log_openssl_errors("Failed to get PKEY group name");
nid = OBJ_sn2nid(curve_name); r = ecc_pkey_new(OBJ_sn2nid(curve_name), &pkey_new);
#else
EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey);
if (!ec_key)
return log_openssl_errors("PKEY doesn't have EC_KEY associated");
if (EC_KEY_check_key(ec_key) != 1)
return log_openssl_errors("EC_KEY associated with PKEY is not valid");
nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key));
#endif
r = ecc_pkey_new(nid, &pkey_new);
if (r < 0) if (r < 0)
return log_debug_errno(r, "Failed to generate a new EC keypair: %m"); return log_debug_errno(r, "Failed to generate a new EC keypair: %m");
@ -1285,38 +1125,11 @@ static int ecc_pkey_generate_volume_keys(
if (r < 0) if (r < 0)
return log_debug_errno(r, "Failed to derive shared secret: %m"); return log_debug_errno(r, "Failed to derive shared secret: %m");
#if OPENSSL_VERSION_MAJOR >= 3
/* EVP_PKEY_get1_encoded_public_key() always returns uncompressed format of EC points. /* EVP_PKEY_get1_encoded_public_key() always returns uncompressed format of EC points.
See https://github.com/openssl/openssl/discussions/22835 */ See https://github.com/openssl/openssl/discussions/22835 */
saved_key_size = EVP_PKEY_get1_encoded_public_key(pkey_new, &saved_key); saved_key_size = EVP_PKEY_get1_encoded_public_key(pkey_new, &saved_key);
if (saved_key_size == 0) if (saved_key_size == 0)
return log_openssl_errors("Failed to convert the generated public key to SEC1 format"); return log_openssl_errors("Failed to convert the generated public key to SEC1 format");
#else
EC_KEY *ec_key_new = EVP_PKEY_get0_EC_KEY(pkey_new);
if (!ec_key_new)
return log_openssl_errors("The generated key doesn't have associated EC_KEY");
if (EC_KEY_check_key(ec_key_new) != 1)
return log_openssl_errors("EC_KEY associated with the generated key is not valid");
saved_key_size = EC_POINT_point2oct(EC_KEY_get0_group(ec_key_new),
EC_KEY_get0_public_key(ec_key_new),
POINT_CONVERSION_UNCOMPRESSED,
NULL, 0, NULL);
if (saved_key_size == 0)
return log_openssl_errors("Failed to determine size of the generated public key");
saved_key = malloc(saved_key_size);
if (!saved_key)
return log_oom_debug();
saved_key_size = EC_POINT_point2oct(EC_KEY_get0_group(ec_key_new),
EC_KEY_get0_public_key(ec_key_new),
POINT_CONVERSION_UNCOMPRESSED,
saved_key, saved_key_size, NULL);
if (saved_key_size == 0)
return log_openssl_errors("Failed to convert the generated public key to SEC1 format");
#endif
*ret_decrypted_key = TAKE_PTR(decrypted_key); *ret_decrypted_key = TAKE_PTR(decrypted_key);
*ret_decrypted_key_size = decrypted_key_size; *ret_decrypted_key_size = decrypted_key_size;
@ -1375,11 +1188,7 @@ int pkey_generate_volume_keys(
assert(ret_saved_key); assert(ret_saved_key);
assert(ret_saved_key_size); assert(ret_saved_key_size);
#if OPENSSL_VERSION_MAJOR >= 3
int type = EVP_PKEY_get_base_id(pkey); int type = EVP_PKEY_get_base_id(pkey);
#else
int type = EVP_PKEY_base_id(pkey);
#endif
switch (type) { switch (type) {
case EVP_PKEY_RSA: case EVP_PKEY_RSA:
@ -1405,7 +1214,6 @@ static int load_key_from_provider(
assert(private_key_uri); assert(private_key_uri);
assert(ret); assert(ret);
#if OPENSSL_VERSION_MAJOR >= 3
/* Load the provider so that this can work without any custom written configuration in /etc/. /* Load the provider so that this can work without any custom written configuration in /etc/.
* Also load the 'default' as that seems to be the recommendation. */ * Also load the 'default' as that seems to be the recommendation. */
if (!OSSL_PROVIDER_try_load(/* ctx= */ NULL, provider, /* retain_fallbacks= */ true)) if (!OSSL_PROVIDER_try_load(/* ctx= */ NULL, provider, /* retain_fallbacks= */ true))
@ -1436,9 +1244,6 @@ static int load_key_from_provider(
*ret = TAKE_PTR(private_key); *ret = TAKE_PTR(private_key);
return 0; return 0;
#else
return -EOPNOTSUPP;
#endif
} }
static int load_key_from_engine(const char *engine, const char *private_key_uri, EVP_PKEY **ret) { static int load_key_from_engine(const char *engine, const char *private_key_uri, EVP_PKEY **ret) {
@ -1609,7 +1414,6 @@ static int load_x509_certificate_from_provider(const char *provider, const char
assert(certificate_uri); assert(certificate_uri);
assert(ret); assert(ret);
#if OPENSSL_VERSION_MAJOR >= 3
/* Load the provider so that this can work without any custom written configuration in /etc/. /* Load the provider so that this can work without any custom written configuration in /etc/.
* Also load the 'default' as that seems to be the recommendation. */ * Also load the 'default' as that seems to be the recommendation. */
if (!OSSL_PROVIDER_try_load(/* ctx= */ NULL, provider, /* retain_fallbacks= */ true)) if (!OSSL_PROVIDER_try_load(/* ctx= */ NULL, provider, /* retain_fallbacks= */ true))
@ -1640,9 +1444,6 @@ static int load_x509_certificate_from_provider(const char *provider, const char
*ret = TAKE_PTR(cert); *ret = TAKE_PTR(cert);
return 0; return 0;
#else
return -EOPNOTSUPP;
#endif
} }
OpenSSLAskPasswordUI* openssl_ask_password_ui_free(OpenSSLAskPasswordUI *ui) { OpenSSLAskPasswordUI* openssl_ask_password_ui_free(OpenSSLAskPasswordUI *ui) {
@ -1712,16 +1513,19 @@ int openssl_load_private_key(
int r; int r;
/* The caller must keep the OpenSSLAskPasswordUI object alive as long as the EVP_PKEY object so that
* the user can enter any needed hardware token pin to unlock the private key when needed. */
assert(private_key); assert(private_key);
assert(request); assert(request);
assert(ret_private_key); assert(ret_private_key);
assert(ret_user_interface);
if (private_key_source_type == OPENSSL_KEY_SOURCE_FILE) { if (private_key_source_type == OPENSSL_KEY_SOURCE_FILE) {
r = openssl_load_private_key_from_file(private_key, ret_private_key); r = openssl_load_private_key_from_file(private_key, ret_private_key);
if (r < 0) if (r < 0)
return r; return r;
if (ret_user_interface)
*ret_user_interface = NULL; *ret_user_interface = NULL;
} else { } else {
_cleanup_(openssl_ask_password_ui_freep) OpenSSLAskPasswordUI *ui = NULL; _cleanup_(openssl_ask_password_ui_freep) OpenSSLAskPasswordUI *ui = NULL;
@ -1747,7 +1551,6 @@ int openssl_load_private_key(
private_key, private_key,
private_key_source); private_key_source);
if (ret_user_interface)
*ret_user_interface = TAKE_PTR(ui); *ret_user_interface = TAKE_PTR(ui);
} }

View File

@ -32,27 +32,21 @@ int parse_openssl_key_source_argument(const char *argument, char **private_key_s
#if HAVE_OPENSSL #if HAVE_OPENSSL
# include <openssl/bio.h> /* IWYU pragma: export */ # include <openssl/bio.h> /* IWYU pragma: export */
# include <openssl/bn.h> /* IWYU pragma: export */ # include <openssl/bn.h> /* IWYU pragma: export */
# include <openssl/core_names.h> /* IWYU pragma: export */
# include <openssl/crypto.h> /* IWYU pragma: export */ # include <openssl/crypto.h> /* IWYU pragma: export */
# include <openssl/err.h> /* IWYU pragma: export */ # include <openssl/err.h> /* IWYU pragma: export */
# include <openssl/evp.h> /* IWYU pragma: export */ # include <openssl/evp.h> /* IWYU pragma: export */
# include <openssl/kdf.h> /* IWYU pragma: export */
# include <openssl/opensslv.h> /* IWYU pragma: export */ # include <openssl/opensslv.h> /* IWYU pragma: export */
# include <openssl/param_build.h> /* IWYU pragma: export */
# include <openssl/pkcs7.h> /* IWYU pragma: export */ # include <openssl/pkcs7.h> /* IWYU pragma: export */
# include <openssl/provider.h> /* IWYU pragma: export */
# include <openssl/ssl.h> /* IWYU pragma: export */ # include <openssl/ssl.h> /* IWYU pragma: export */
# include <openssl/store.h> /* IWYU pragma: export */
# ifndef OPENSSL_NO_UI_CONSOLE # ifndef OPENSSL_NO_UI_CONSOLE
# include <openssl/ui.h> /* IWYU pragma: export */ # include <openssl/ui.h> /* IWYU pragma: export */
# endif # endif
# include <openssl/x509v3.h> /* IWYU pragma: export */ # include <openssl/x509v3.h> /* IWYU pragma: export */
# ifndef OPENSSL_VERSION_MAJOR
/* OPENSSL_VERSION_MAJOR macro was added in OpenSSL 3. Thus, if it doesn't exist, we must be before OpenSSL 3. */
# define OPENSSL_VERSION_MAJOR 1
# endif
# if OPENSSL_VERSION_MAJOR >= 3
# include <openssl/core_names.h> /* IWYU pragma: export */
# include <openssl/kdf.h> /* IWYU pragma: export */
# include <openssl/param_build.h> /* IWYU pragma: export */
# include <openssl/provider.h> /* IWYU pragma: export */
# include <openssl/store.h> /* IWYU pragma: export */
# endif
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_MACRO(void*, OPENSSL_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_MACRO(void*, OPENSSL_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(ASN1_OCTET_STRING*, ASN1_OCTET_STRING_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(ASN1_OCTET_STRING*, ASN1_OCTET_STRING_free, NULL);
@ -64,10 +58,20 @@ DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(BN_CTX*, BN_CTX_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EC_GROUP*, EC_GROUP_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EC_GROUP*, EC_GROUP_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EC_POINT*, EC_POINT_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EC_POINT*, EC_POINT_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(ECDSA_SIG*, ECDSA_SIG_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(ECDSA_SIG*, ECDSA_SIG_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_CIPHER*, EVP_CIPHER_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_CIPHER_CTX*, EVP_CIPHER_CTX_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_CIPHER_CTX*, EVP_CIPHER_CTX_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_KDF*, EVP_KDF_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_KDF_CTX*, EVP_KDF_CTX_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MAC*, EVP_MAC_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MAC_CTX*, EVP_MAC_CTX_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MD*, EVP_MD_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MD_CTX*, EVP_MD_CTX_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MD_CTX*, EVP_MD_CTX_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_PKEY*, EVP_PKEY_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_PKEY*, EVP_PKEY_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_PKEY_CTX*, EVP_PKEY_CTX_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_PKEY_CTX*, EVP_PKEY_CTX_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(OSSL_PARAM*, OSSL_PARAM_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(OSSL_PARAM_BLD*, OSSL_PARAM_BLD_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(OSSL_STORE_CTX*, OSSL_STORE_close, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(OSSL_STORE_INFO*, OSSL_STORE_INFO_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(PKCS7*, PKCS7_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(PKCS7*, PKCS7_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(PKCS7_SIGNER_INFO*, PKCS7_SIGNER_INFO_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(PKCS7_SIGNER_INFO*, PKCS7_SIGNER_INFO_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(SSL*, SSL_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(SSL*, SSL_free, NULL);
@ -94,23 +98,6 @@ static inline STACK_OF(X509_ATTRIBUTE) *x509_attribute_free_many(STACK_OF(X509_A
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(STACK_OF(X509_ATTRIBUTE)*, x509_attribute_free_many, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(STACK_OF(X509_ATTRIBUTE)*, x509_attribute_free_many, NULL);
#if OPENSSL_VERSION_MAJOR >= 3
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_CIPHER*, EVP_CIPHER_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_KDF*, EVP_KDF_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_KDF_CTX*, EVP_KDF_CTX_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MAC*, EVP_MAC_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MAC_CTX*, EVP_MAC_CTX_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MD*, EVP_MD_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(OSSL_PARAM*, OSSL_PARAM_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(OSSL_PARAM_BLD*, OSSL_PARAM_BLD_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(OSSL_STORE_CTX*, OSSL_STORE_close, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(OSSL_STORE_INFO*, OSSL_STORE_INFO_free, NULL);
#else
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EC_KEY*, EC_KEY_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(HMAC_CTX*, HMAC_CTX_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(RSA*, RSA_free, NULL);
#endif
static inline void sk_X509_free_allp(STACK_OF(X509) **sk) { static inline void sk_X509_free_allp(STACK_OF(X509) **sk) {
if (!sk || !*sk) if (!sk || !*sk)
return; return;

View File

@ -546,7 +546,6 @@ int pkcs11_token_read_public_key(
if (!os) if (!os)
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unable to decode CKA_EC_POINT."); return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unable to decode CKA_EC_POINT.");
#if OPENSSL_VERSION_MAJOR >= 3
_cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
if (!ctx) if (!ctx)
return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to create an EVP_PKEY_CTX for EC."); return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to create an EVP_PKEY_CTX for EC.");
@ -642,31 +641,6 @@ int pkcs11_token_read_public_key(
if (EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, ec_params) != 1) if (EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, ec_params) != 1)
return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to create EVP_PKEY from EC parameters."); return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to create EVP_PKEY from EC parameters.");
#else
_cleanup_(EC_POINT_freep) EC_POINT *point = EC_POINT_new(group);
if (!point)
return log_oom_debug();
if (EC_POINT_oct2point(group, point, os->data, os->length, NULL) != 1)
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unable to decode CKA_EC_POINT.");
_cleanup_(EC_KEY_freep) EC_KEY *ec_key = EC_KEY_new();
if (!ec_key)
return log_oom_debug();
if (EC_KEY_set_group(ec_key, group) != 1)
return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to set group for EC_KEY.");
if (EC_KEY_set_public_key(ec_key, point) != 1)
return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to set public key for EC_KEY.");
pkey = EVP_PKEY_new();
if (!pkey)
return log_oom_debug();
if (EVP_PKEY_set1_EC_KEY(pkey, ec_key) != 1)
return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to assign EC_KEY to EVP_PKEY.");
#endif
break; break;
} }
default: default:

View File

@ -129,10 +129,10 @@ uint32_t seccomp_local_archs[] = {
SCMP_ARCH_MIPSEL64, SCMP_ARCH_MIPSEL64,
SCMP_ARCH_MIPS64N32, SCMP_ARCH_MIPS64N32,
SCMP_ARCH_MIPSEL64N32, /* native */ SCMP_ARCH_MIPSEL64N32, /* native */
#elif defined(__hppa64__) && defined(SCMP_ARCH_PARISC) && defined(SCMP_ARCH_PARISC64) #elif defined(__hppa64__)
SCMP_ARCH_PARISC, SCMP_ARCH_PARISC,
SCMP_ARCH_PARISC64, /* native */ SCMP_ARCH_PARISC64, /* native */
#elif defined(__hppa__) && defined(SCMP_ARCH_PARISC) #elif defined(__hppa__)
SCMP_ARCH_PARISC, SCMP_ARCH_PARISC,
#elif defined(__powerpc64__) && __BYTE_ORDER == __BIG_ENDIAN #elif defined(__powerpc64__) && __BYTE_ORDER == __BIG_ENDIAN
SCMP_ARCH_PPC, SCMP_ARCH_PPC,
@ -190,14 +190,10 @@ const char* seccomp_arch_to_string(uint32_t c) {
return "mips64-le"; return "mips64-le";
case SCMP_ARCH_MIPSEL64N32: case SCMP_ARCH_MIPSEL64N32:
return "mips64-le-n32"; return "mips64-le-n32";
#ifdef SCMP_ARCH_PARISC
case SCMP_ARCH_PARISC: case SCMP_ARCH_PARISC:
return "parisc"; return "parisc";
#endif
#ifdef SCMP_ARCH_PARISC64
case SCMP_ARCH_PARISC64: case SCMP_ARCH_PARISC64:
return "parisc64"; return "parisc64";
#endif
case SCMP_ARCH_PPC: case SCMP_ARCH_PPC:
return "ppc"; return "ppc";
case SCMP_ARCH_PPC64: case SCMP_ARCH_PPC64:
@ -251,14 +247,10 @@ int seccomp_arch_from_string(const char *n, uint32_t *ret) {
*ret = SCMP_ARCH_MIPSEL64; *ret = SCMP_ARCH_MIPSEL64;
else if (streq(n, "mips64-le-n32")) else if (streq(n, "mips64-le-n32"))
*ret = SCMP_ARCH_MIPSEL64N32; *ret = SCMP_ARCH_MIPSEL64N32;
#ifdef SCMP_ARCH_PARISC
else if (streq(n, "parisc")) else if (streq(n, "parisc"))
*ret = SCMP_ARCH_PARISC; *ret = SCMP_ARCH_PARISC;
#endif
#ifdef SCMP_ARCH_PARISC64
else if (streq(n, "parisc64")) else if (streq(n, "parisc64"))
*ret = SCMP_ARCH_PARISC64; *ret = SCMP_ARCH_PARISC64;
#endif
else if (streq(n, "ppc")) else if (streq(n, "ppc"))
*ret = SCMP_ARCH_PPC; *ret = SCMP_ARCH_PPC;
else if (streq(n, "ppc64")) else if (streq(n, "ppc64"))
@ -1159,10 +1151,8 @@ static uint32_t override_default_action(uint32_t default_action) {
if (default_action == SCMP_ACT_ALLOW) if (default_action == SCMP_ACT_ALLOW)
return default_action; return default_action;
#ifdef SCMP_ACT_LOG
if (default_action == SCMP_ACT_LOG) if (default_action == SCMP_ACT_LOG)
return default_action; return default_action;
#endif
return SCMP_ACT_ERRNO(ENOSYS); return SCMP_ACT_ERRNO(ENOSYS);
} }
@ -1264,11 +1254,9 @@ int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* filter
int error = PTR_TO_INT(val); int error = PTR_TO_INT(val);
if (error == SECCOMP_ERROR_NUMBER_KILL) if (error == SECCOMP_ERROR_NUMBER_KILL)
a = scmp_act_kill_process(); a = SCMP_ACT_KILL_PROCESS;
#ifdef SCMP_ACT_LOG
else if (action == SCMP_ACT_LOG) else if (action == SCMP_ACT_LOG)
a = SCMP_ACT_LOG; a = SCMP_ACT_LOG;
#endif
else if (error >= 0) else if (error >= 0)
a = SCMP_ACT_ERRNO(error); a = SCMP_ACT_ERRNO(error);
@ -1677,12 +1665,8 @@ int seccomp_restrict_address_families(Set *address_families, bool allow_list) {
case SCMP_ARCH_X86: case SCMP_ARCH_X86:
case SCMP_ARCH_MIPSEL: case SCMP_ARCH_MIPSEL:
case SCMP_ARCH_MIPS: case SCMP_ARCH_MIPS:
#ifdef SCMP_ARCH_PARISC
case SCMP_ARCH_PARISC: case SCMP_ARCH_PARISC:
#endif
#ifdef SCMP_ARCH_PARISC64
case SCMP_ARCH_PARISC64: case SCMP_ARCH_PARISC64:
#endif
case SCMP_ARCH_PPC: case SCMP_ARCH_PPC:
case SCMP_ARCH_PPC64: case SCMP_ARCH_PPC64:
case SCMP_ARCH_PPC64LE: case SCMP_ARCH_PPC64LE:
@ -2488,21 +2472,6 @@ int seccomp_restrict_suid_sgid(void) {
return 0; return 0;
} }
uint32_t scmp_act_kill_process(void) {
/* Returns SCMP_ACT_KILL_PROCESS if it's supported, and SCMP_ACT_KILL_THREAD otherwise. We never
* actually want to use SCMP_ACT_KILL_THREAD as its semantics are nuts (killing arbitrary threads of
* a program is just a bad idea), but on old kernels/old libseccomp it is all we have, and at least
* for single-threaded apps does the right thing. */
#ifdef SCMP_ACT_KILL_PROCESS
if (dlopen_libseccomp() >= 0 && sym_seccomp_api_get() >= 3)
return SCMP_ACT_KILL_PROCESS;
#endif
return SCMP_ACT_KILL; /* same as SCMP_ACT_KILL_THREAD */
}
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;
const char *p; const char *p;

View File

@ -153,9 +153,6 @@ _DEFINE_ABS_WRAPPER(SECCOMP_FATAL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(scmp_filter_ctx, sym_seccomp_release, seccomp_releasep, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(scmp_filter_ctx, sym_seccomp_release, seccomp_releasep, NULL);
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);
int parse_syscall_and_errno(const char *in, char **name, int *error); int parse_syscall_and_errno(const char *in, char **name, int *error);
int seccomp_suppress_sync(void); int seccomp_suppress_sync(void);

View File

@ -4354,7 +4354,7 @@ int tpm2_tpm2b_public_to_openssl_pkey(const TPM2B_PUBLIC *public, EVP_PKEY **ret
* "name", because it would break unsealing of previously-sealed objects that used (for example) * "name", because it would break unsealing of previously-sealed objects that used (for example)
* tpm2_calculate_policy_authorize(). See bug #30546. */ * tpm2_calculate_policy_authorize(). See bug #30546. */
int tpm2_tpm2b_public_from_openssl_pkey(const EVP_PKEY *pkey, TPM2B_PUBLIC *ret) { int tpm2_tpm2b_public_from_openssl_pkey(const EVP_PKEY *pkey, TPM2B_PUBLIC *ret) {
int key_id, r; int r;
assert(pkey); assert(pkey);
assert(ret); assert(ret);
@ -4368,12 +4368,7 @@ int tpm2_tpm2b_public_from_openssl_pkey(const EVP_PKEY *pkey, TPM2B_PUBLIC *ret)
}, },
}; };
#if OPENSSL_VERSION_MAJOR >= 3 int key_id = EVP_PKEY_get_id(pkey);
key_id = EVP_PKEY_get_id(pkey);
#else
key_id = EVP_PKEY_id(pkey);
#endif
switch (key_id) { switch (key_id) {
case EVP_PKEY_EC: { case EVP_PKEY_EC: {
public.type = TPM2_ALG_ECC; public.type = TPM2_ALG_ECC;

View File

@ -543,7 +543,7 @@ static int job_start(Job *j) {
r = sd_event_source_set_child_process_own(j->child, true); r = sd_event_source_set_child_process_own(j->child, true);
if (r < 0) if (r < 0)
return log_error_errno(r, "Event loop failed to take ownership of child process: %m"); return log_error_errno(r, "Event loop failed to take ownership of child process: %m");
TAKE_PIDREF(pid); pidref_done(&pid); /* disarm sigkill_wait */
j->stdout_fd = TAKE_FD(stdout_fd); j->stdout_fd = TAKE_FD(stdout_fd);

View File

@ -103,15 +103,12 @@ static const struct {
} digest_size_table[] = { } digest_size_table[] = {
/* SHA1 "family" */ /* SHA1 "family" */
{ "sha1", 20, }, { "sha1", 20, },
#if OPENSSL_VERSION_MAJOR >= 3
{ "sha-1", 20, }, { "sha-1", 20, },
#endif
/* SHA2 family */ /* SHA2 family */
{ "sha224", 28, }, { "sha224", 28, },
{ "sha256", 32, }, { "sha256", 32, },
{ "sha384", 48, }, { "sha384", 48, },
{ "sha512", 64, }, { "sha512", 64, },
#if OPENSSL_VERSION_MAJOR >= 3
{ "sha-224", 28, }, { "sha-224", 28, },
{ "sha2-224", 28, }, { "sha2-224", 28, },
{ "sha-256", 32, }, { "sha-256", 32, },
@ -120,7 +117,6 @@ static const struct {
{ "sha2-384", 48, }, { "sha2-384", 48, },
{ "sha-512", 64, }, { "sha-512", 64, },
{ "sha2-512", 64, }, { "sha2-512", 64, },
#endif
/* SHA3 family */ /* SHA3 family */
{ "sha3-224", 28, }, { "sha3-224", 28, },
{ "sha3-256", 32, }, { "sha3-256", 32, },
@ -296,7 +292,6 @@ TEST(hmac_many) {
} }
TEST(kdf_kb_hmac_derive) { TEST(kdf_kb_hmac_derive) {
#if OPENSSL_VERSION_MAJOR >= 3
_cleanup_free_ void *derived_key = NULL; _cleanup_free_ void *derived_key = NULL;
DEFINE_HEX_PTR(key, "d7ac57124f28371eacaec475b74869d26b4cd64586412a607ce0a9e0c63d468c"); DEFINE_HEX_PTR(key, "d7ac57124f28371eacaec475b74869d26b4cd64586412a607ce0a9e0c63d468c");
@ -306,12 +301,8 @@ TEST(kdf_kb_hmac_derive) {
assert_se(kdf_kb_hmac_derive("COUNTER", "SHA256", key, key_len, salt, strlen(salt), info, info_len, /* seed= */ NULL, /* seed_size= */ 0, 64, &derived_key) >= 0); assert_se(kdf_kb_hmac_derive("COUNTER", "SHA256", key, key_len, salt, strlen(salt), info, info_len, /* seed= */ NULL, /* seed_size= */ 0, 64, &derived_key) >= 0);
assert_se(memcmp_nn(derived_key, 64, expected_derived_key, expected_derived_key_len) == 0); assert_se(memcmp_nn(derived_key, 64, expected_derived_key, expected_derived_key_len) == 0);
#else
log_tests_skipped("KDF-KB requires OpenSSL >= 3");
#endif
} }
#if OPENSSL_VERSION_MAJOR >= 3
static void check_ss_derive(const char *hex_key, const char *hex_salt, const char *hex_info, const char *hex_expected) { static void check_ss_derive(const char *hex_key, const char *hex_salt, const char *hex_info, const char *hex_expected) {
DEFINE_HEX_PTR(key, hex_key); DEFINE_HEX_PTR(key, hex_key);
DEFINE_HEX_PTR(salt, hex_salt); DEFINE_HEX_PTR(salt, hex_salt);
@ -322,10 +313,8 @@ static void check_ss_derive(const char *hex_key, const char *hex_salt, const cha
assert_se(kdf_ss_derive("SHA256", key, key_len, salt, salt_len, info, info_len, expected_len, &derived_key) >= 0); assert_se(kdf_ss_derive("SHA256", key, key_len, salt, salt_len, info, info_len, expected_len, &derived_key) >= 0);
assert_se(memcmp_nn(derived_key, expected_len, expected, expected_len) == 0); assert_se(memcmp_nn(derived_key, expected_len, expected, expected_len) == 0);
} }
#endif
TEST(kdf_ss_derive) { TEST(kdf_ss_derive) {
#if OPENSSL_VERSION_MAJOR >= 3
check_ss_derive( check_ss_derive(
"01166ad6b05d1fad8cdb50d1902170e9", "01166ad6b05d1fad8cdb50d1902170e9",
"feea805789dc8d0b57da5d4d61886b1a", "feea805789dc8d0b57da5d4d61886b1a",
@ -343,9 +332,6 @@ TEST(kdf_ss_derive) {
"b75e3b65d1bb845dee581c7e14cfebc6e882946e90273b77ebe289faaf7de248", "b75e3b65d1bb845dee581c7e14cfebc6e882946e90273b77ebe289faaf7de248",
"ed25a0043d6c1eb28296da1f9ab138dafee18f4c937bfc43601d4ee6e7634199", "ed25a0043d6c1eb28296da1f9ab138dafee18f4c937bfc43601d4ee6e7634199",
"30EB1A1E9DEA7DE4DDB8F3FDF50A01E30581D606C1228D98AFF691DF743AC2EE9D99EFD2AE1946C079AA18C9524877FA65D5065F0DAED058AB3416AF80EB2B73"); "30EB1A1E9DEA7DE4DDB8F3FDF50A01E30581D606C1228D98AFF691DF743AC2EE9D99EFD2AE1946C079AA18C9524877FA65D5065F0DAED058AB3416AF80EB2B73");
#else
log_tests_skipped("KDF-SS requires OpenSSL >= 3");
#endif
} }
static void check_cipher( static void check_cipher(

View File

@ -682,7 +682,7 @@ TEST(load_syscall_filter_set_raw) {
assert_se(access("/", F_OK) >= 0); assert_se(access("/", F_OK) >= 0);
assert_se(poll(NULL, 0, 0) == 0); assert_se(poll(NULL, 0, 0) == 0);
assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, NULL, scmp_act_kill_process(), true) >= 0); assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, NULL, SCMP_ACT_KILL_PROCESS, true) >= 0);
assert_se(access("/", F_OK) >= 0); assert_se(access("/", F_OK) >= 0);
assert_se(poll(NULL, 0, 0) == 0); assert_se(poll(NULL, 0, 0) == 0);
@ -791,7 +791,7 @@ TEST(native_syscalls_filtered) {
assert_se(access("/", F_OK) >= 0); assert_se(access("/", F_OK) >= 0);
assert_se(poll(NULL, 0, 0) == 0); assert_se(poll(NULL, 0, 0) == 0);
assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, NULL, scmp_act_kill_process(), true) >= 0); assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, NULL, SCMP_ACT_KILL_PROCESS, true) >= 0);
assert_se(access("/", F_OK) >= 0); assert_se(access("/", F_OK) >= 0);
assert_se(poll(NULL, 0, 0) == 0); assert_se(poll(NULL, 0, 0) == 0);

View File

@ -1144,7 +1144,7 @@ static void check_get_or_create_srk(Tpm2Context *c) {
assert_se(memcmp_nn(qname->name, qname->size, qname2->name, qname2->size) == 0); assert_se(memcmp_nn(qname->name, qname->size, qname2->name, qname2->size) == 0);
} }
#if HAVE_OPENSSL && OPENSSL_VERSION_MAJOR >= 3 #if HAVE_OPENSSL
static void calculate_seal_and_unseal( static void calculate_seal_and_unseal(
Tpm2Context *c, Tpm2Context *c,
TPM2_HANDLE parent_index, TPM2_HANDLE parent_index,
@ -1228,7 +1228,7 @@ static int check_calculate_seal(Tpm2Context *c) {
return 0; return 0;
} }
#endif /* HAVE_OPENSSL && OPENSSL_VERSION_MAJOR >= 3 */ #endif /* HAVE_OPENSSL */
static void check_seal_unseal_for_handle(Tpm2Context *c, TPM2_HANDLE handle) { static void check_seal_unseal_for_handle(Tpm2Context *c, TPM2_HANDLE handle) {
TPM2B_DIGEST policy = TPM2B_DIGEST_MAKE(NULL, TPM2_SHA256_DIGEST_SIZE); TPM2B_DIGEST policy = TPM2B_DIGEST_MAKE(NULL, TPM2_SHA256_DIGEST_SIZE);
@ -1330,7 +1330,7 @@ TEST_RET(tests_which_require_tpm) {
check_get_or_create_srk(c); check_get_or_create_srk(c);
check_seal_unseal(c); check_seal_unseal(c);
#if HAVE_OPENSSL && OPENSSL_VERSION_MAJOR >= 3 /* calculating sealed object requires openssl >= 3 */ #if HAVE_OPENSSL
r = check_calculate_seal(c); r = check_calculate_seal(c);
#endif #endif

View File

@ -458,21 +458,11 @@ static int builtin_blkid(UdevEvent *event, int argc, char *argv[]) {
switch (option) { switch (option) {
case 'H': case 'H':
#if HAVE_BLKID_PROBE_SET_HINT
errno = 0; errno = 0;
r = sym_blkid_probe_set_hint(pr, optarg, 0); r = sym_blkid_probe_set_hint(pr, optarg, 0);
if (r < 0) if (r < 0)
return log_device_error_errno(dev, errno_or_else(ENOMEM), "Failed to use '%s' probing hint: %m", optarg); return log_device_error_errno(dev, errno_or_else(ENOMEM), "Failed to use '%s' probing hint: %m", optarg);
break; break;
#else
/* Use the hint <name>=<offset> as probing offset for old versions */
optarg = strchr(optarg, '=');
if (!optarg)
/* no value means 0, do nothing for old versions */
break;
++optarg;
_fallthrough_;
#endif
case 'o': case 'o':
r = safe_atoi64(optarg, &offset); r = safe_atoi64(optarg, &offset);
if (r < 0) if (r < 0)
@ -489,7 +479,7 @@ static int builtin_blkid(UdevEvent *event, int argc, char *argv[]) {
sym_blkid_probe_set_superblocks_flags(pr, sym_blkid_probe_set_superblocks_flags(pr,
BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID |
BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE | BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE |
#ifdef BLKID_SUBLKS_FSINFO #ifdef BLKID_SUBLKS_FSINFO /* since util-linux 2.39 */
BLKID_SUBLKS_FSINFO | BLKID_SUBLKS_FSINFO |
#endif #endif
BLKID_SUBLKS_USAGE | BLKID_SUBLKS_VERSION); BLKID_SUBLKS_USAGE | BLKID_SUBLKS_VERSION);

View File

@ -208,11 +208,6 @@ static int synthesize_change(Manager *manager, sd_device *dev) {
return 0; return 0;
} }
r = sd_event_source_set_child_pidfd_own(s, true);
if (r < 0)
return r;
TAKE_PIDREF(pidref);
r = set_ensure_put(&manager->synthesize_change_child_event_sources, &event_source_hash_ops, s); r = set_ensure_put(&manager->synthesize_change_child_event_sources, &event_source_hash_ops, s);
if (r < 0) if (r < 0)
return r; return r;

View File

@ -161,14 +161,10 @@ static int parse_options(const char *options) {
arg_activate_flags |= CRYPT_ACTIVATE_RESTART_ON_CORRUPTION; arg_activate_flags |= CRYPT_ACTIVATE_RESTART_ON_CORRUPTION;
else if (streq(word, "ignore-zero-blocks")) else if (streq(word, "ignore-zero-blocks"))
arg_activate_flags |= CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS; arg_activate_flags |= CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS;
#ifdef CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE
else if (streq(word, "check-at-most-once")) else if (streq(word, "check-at-most-once"))
arg_activate_flags |= CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE; arg_activate_flags |= CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE;
#endif
#ifdef CRYPT_ACTIVATE_PANIC_ON_CORRUPTION
else if (streq(word, "panic-on-corruption")) else if (streq(word, "panic-on-corruption"))
arg_activate_flags |= CRYPT_ACTIVATE_PANIC_ON_CORRUPTION; arg_activate_flags |= CRYPT_ACTIVATE_PANIC_ON_CORRUPTION;
#endif
else if ((val = startswith(word, "superblock="))) { else if ((val = startswith(word, "superblock="))) {
r = parse_boolean(val); r = parse_boolean(val);

View File

@ -12,6 +12,7 @@
#include "errno-util.h" #include "errno-util.h"
#include "json-util.h" #include "json-util.h"
#include "log.h" #include "log.h"
#include "path-lookup.h"
#include "pidref.h" #include "pidref.h"
#include "socket-util.h" #include "socket-util.h"
#include "string-util.h" #include "string-util.h"
@ -29,7 +30,8 @@ int register_machine(
unsigned cid, unsigned cid,
const char *address, const char *address,
const char *key_path, const char *key_path,
bool keep_unit) { bool allocate_unit,
RuntimeScope scope) {
_cleanup_(sd_varlink_unrefp) sd_varlink *vl = NULL; _cleanup_(sd_varlink_unrefp) sd_varlink *vl = NULL;
int r; int r;
@ -38,7 +40,12 @@ int register_machine(
assert(service); assert(service);
/* First try to use varlink, as it provides more features (such as SSH support). */ /* First try to use varlink, as it provides more features (such as SSH support). */
r = sd_varlink_connect_address(&vl, "/run/systemd/machine/io.systemd.Machine"); _cleanup_free_ char *p = NULL;
r = runtime_directory_generic(scope, "systemd/machine/io.systemd.Machine", &p);
if (r < 0)
return r;
r = sd_varlink_connect_address(&vl, p);
if (r == -ENOENT || ERRNO_IS_DISCONNECT(r)) { if (r == -ENOENT || ERRNO_IS_DISCONNECT(r)) {
_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;
@ -64,7 +71,7 @@ int register_machine(
return 0; return 0;
} }
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to connect to machined on /run/systemd/machine/io.systemd.Machine: %m"); return log_error_errno(r, "Failed to connect to machined on %p: %m", p);
return varlink_callbo_and_log( return varlink_callbo_and_log(
vl, vl,
@ -79,7 +86,7 @@ int register_machine(
SD_JSON_BUILD_PAIR_CONDITION(!!address, "sshAddress", SD_JSON_BUILD_STRING(address)), SD_JSON_BUILD_PAIR_CONDITION(!!address, "sshAddress", SD_JSON_BUILD_STRING(address)),
SD_JSON_BUILD_PAIR_CONDITION(!!key_path, "sshPrivateKeyPath", SD_JSON_BUILD_STRING(key_path)), SD_JSON_BUILD_PAIR_CONDITION(!!key_path, "sshPrivateKeyPath", SD_JSON_BUILD_STRING(key_path)),
SD_JSON_BUILD_PAIR_CONDITION(isatty_safe(STDIN_FILENO), "allowInteractiveAuthentication", SD_JSON_BUILD_BOOLEAN(true)), SD_JSON_BUILD_PAIR_CONDITION(isatty_safe(STDIN_FILENO), "allowInteractiveAuthentication", SD_JSON_BUILD_BOOLEAN(true)),
SD_JSON_BUILD_PAIR_CONDITION(!keep_unit, "allocateUnit", SD_JSON_BUILD_BOOLEAN(true)), SD_JSON_BUILD_PAIR_CONDITION(allocate_unit, "allocateUnit", SD_JSON_BUILD_BOOLEAN(true)),
SD_JSON_BUILD_PAIR_CONDITION(pidref_is_set(pidref), "leaderProcessId", JSON_BUILD_PIDREF(pidref))); SD_JSON_BUILD_PAIR_CONDITION(pidref_is_set(pidref), "leaderProcessId", JSON_BUILD_PIDREF(pidref)));
} }

View File

@ -13,6 +13,7 @@ int register_machine(
unsigned cid, unsigned cid,
const char *address, const char *address,
const char *key_path, const char *key_path,
bool keep_unit); bool allocate_unit,
RuntimeScope scope);
int unregister_machine(sd_bus *bus, const char *machine_name); int unregister_machine(sd_bus *bus, const char *machine_name);

View File

@ -123,7 +123,6 @@ static uid_t arg_uid_shift = UID_INVALID, arg_uid_range = 0x10000U;
static RuntimeMountContext arg_runtime_mounts = {}; static RuntimeMountContext arg_runtime_mounts = {};
static char *arg_firmware = NULL; static char *arg_firmware = NULL;
static char *arg_forward_journal = NULL; static char *arg_forward_journal = NULL;
static bool arg_privileged = false;
static bool arg_register = true; static bool arg_register = true;
static bool arg_keep_unit = false; static bool arg_keep_unit = false;
static sd_id128_t arg_uuid = {}; static sd_id128_t arg_uuid = {};
@ -144,6 +143,7 @@ static char **arg_bind_user = NULL;
static char *arg_bind_user_shell = NULL; static char *arg_bind_user_shell = NULL;
static bool arg_bind_user_shell_copy = false; static bool arg_bind_user_shell_copy = false;
static char **arg_bind_user_groups = NULL; static char **arg_bind_user_groups = NULL;
static RuntimeScope arg_runtime_scope = _RUNTIME_SCOPE_INVALID;
STATIC_DESTRUCTOR_REGISTER(arg_directory, freep); STATIC_DESTRUCTOR_REGISTER(arg_directory, freep);
STATIC_DESTRUCTOR_REGISTER(arg_image, freep); STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
@ -184,6 +184,8 @@ static int help(void) {
" -q --quiet Do not show status information\n" " -q --quiet Do not show status information\n"
" --no-pager Do not pipe output into a pager\n" " --no-pager Do not pipe output into a pager\n"
" --no-ask-password Do not prompt for password\n" " --no-ask-password Do not prompt for password\n"
" --user Interact with user manager\n"
" --system Interact with system manager\n"
"\n%3$sImage:%4$s\n" "\n%3$sImage:%4$s\n"
" -D --directory=PATH Root directory for the VM\n" " -D --directory=PATH Root directory for the VM\n"
" -i --image=FILE|DEVICE Root file system disk image or device for the VM\n" " -i --image=FILE|DEVICE Root file system disk image or device for the VM\n"
@ -308,6 +310,8 @@ static int parse_argv(int argc, char *argv[]) {
ARG_BIND_USER, ARG_BIND_USER,
ARG_BIND_USER_SHELL, ARG_BIND_USER_SHELL,
ARG_BIND_USER_GROUP, ARG_BIND_USER_GROUP,
ARG_SYSTEM,
ARG_USER,
}; };
static const struct option options[] = { static const struct option options[] = {
@ -360,6 +364,8 @@ static int parse_argv(int argc, char *argv[]) {
{ "bind-user", required_argument, NULL, ARG_BIND_USER }, { "bind-user", required_argument, NULL, ARG_BIND_USER },
{ "bind-user-shell", required_argument, NULL, ARG_BIND_USER_SHELL }, { "bind-user-shell", required_argument, NULL, ARG_BIND_USER_SHELL },
{ "bind-user-group", required_argument, NULL, ARG_BIND_USER_GROUP }, { "bind-user-group", required_argument, NULL, ARG_BIND_USER_GROUP },
{ "system", no_argument, NULL, ARG_SYSTEM },
{ "user", no_argument, NULL, ARG_USER },
{} {}
}; };
@ -730,6 +736,14 @@ static int parse_argv(int argc, char *argv[]) {
break; break;
case ARG_SYSTEM:
arg_runtime_scope = RUNTIME_SCOPE_SYSTEM;
break;
case ARG_USER:
arg_runtime_scope = RUNTIME_SCOPE_USER;
break;
case '?': case '?':
return -EINVAL; return -EINVAL;
@ -1808,7 +1822,7 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
/* Registration always happens on the system bus */ /* Registration always happens on the system bus */
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *system_bus = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *system_bus = NULL;
if (arg_register || arg_privileged) { if (arg_register || arg_runtime_scope == RUNTIME_SCOPE_SYSTEM) {
r = sd_bus_default_system(&system_bus); r = sd_bus_default_system(&system_bus);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to open system bus: %m"); return log_error_errno(r, "Failed to open system bus: %m");
@ -1823,7 +1837,7 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
/* Scope allocation happens on the user bus if we are unpriv, otherwise system bus. */ /* Scope allocation happens on the user bus if we are unpriv, otherwise system bus. */
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *user_bus = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *user_bus = NULL;
_cleanup_(sd_bus_unrefp) sd_bus *runtime_bus = NULL; _cleanup_(sd_bus_unrefp) sd_bus *runtime_bus = NULL;
if (arg_privileged) if (arg_runtime_scope == RUNTIME_SCOPE_SYSTEM)
runtime_bus = sd_bus_ref(system_bus); runtime_bus = sd_bus_ref(system_bus);
else { else {
r = sd_bus_default_user(&user_bus); r = sd_bus_default_user(&user_bus);
@ -1949,10 +1963,7 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
if (asprintf(&subdir, "systemd/vmspawn.%" PRIx64, random_u64()) < 0) if (asprintf(&subdir, "systemd/vmspawn.%" PRIx64, random_u64()) < 0)
return log_oom(); return log_oom();
r = runtime_directory( r = runtime_directory(arg_runtime_scope, subdir, &runtime_dir);
arg_privileged ? RUNTIME_SCOPE_SYSTEM : RUNTIME_SCOPE_USER,
subdir,
&runtime_dir);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to lookup runtime directory: %m"); return log_error_errno(r, "Failed to lookup runtime directory: %m");
if (r > 0) { /* We need to create our own runtime dir */ if (r > 0) { /* We need to create our own runtime dir */
@ -2762,7 +2773,7 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
} }
bool scope_allocated = false; bool scope_allocated = false;
if (!arg_keep_unit && (!arg_register || !arg_privileged)) { if (!arg_keep_unit && (!arg_register || arg_runtime_scope != RUNTIME_SCOPE_SYSTEM)) {
r = allocate_scope( r = allocate_scope(
runtime_bus, runtime_bus,
arg_machine, arg_machine,
@ -2778,7 +2789,7 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
scope_allocated = true; scope_allocated = true;
} else { } else {
if (arg_privileged) if (arg_runtime_scope == RUNTIME_SCOPE_SYSTEM)
r = cg_pid_get_unit(0, &unit); r = cg_pid_get_unit(0, &unit);
else else
r = cg_pid_get_user_unit(0, &unit); r = cg_pid_get_user_unit(0, &unit);
@ -2786,7 +2797,7 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
return log_error_errno(r, "Failed to get our own unit: %m"); return log_error_errno(r, "Failed to get our own unit: %m");
} }
bool registered = false; bool registered_system = false, registered_runtime = false;
if (arg_register) { if (arg_register) {
char vm_address[STRLEN("vsock/") + DECIMAL_STR_MAX(unsigned)]; char vm_address[STRLEN("vsock/") + DECIMAL_STR_MAX(unsigned)];
xsprintf(vm_address, "vsock/%u", child_cid); xsprintf(vm_address, "vsock/%u", child_cid);
@ -2800,11 +2811,38 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
child_cid, child_cid,
child_cid != VMADDR_CID_ANY ? vm_address : NULL, child_cid != VMADDR_CID_ANY ? vm_address : NULL,
ssh_private_key_path, ssh_private_key_path,
arg_keep_unit || !arg_privileged); !arg_keep_unit && arg_runtime_scope == RUNTIME_SCOPE_SYSTEM,
if (r < 0) RUNTIME_SCOPE_SYSTEM);
if (r < 0) {
/* if privileged the request to register definitely failed */
if (arg_runtime_scope == RUNTIME_SCOPE_SYSTEM)
return r; return r;
registered = true; log_notice_errno(r, "Failed to register machine in system context, will try in user context.");
} else
registered_system = true;
if (arg_runtime_scope == RUNTIME_SCOPE_USER) {
r = register_machine(
runtime_bus,
arg_machine,
arg_uuid,
"systemd-vmspawn",
&child_pidref,
arg_directory,
child_cid,
child_cid != VMADDR_CID_ANY ? vm_address : NULL,
ssh_private_key_path,
!arg_keep_unit,
RUNTIME_SCOPE_USER);
if (r < 0) {
if (!registered_system) /* neither registration worked: fail */
return r;
log_notice_errno(r, "Failed to register machine in user context, but succeeded in system context, will proceed.");
} else
registered_runtime = true;
}
} }
/* Report that the VM is now set up */ /* Report that the VM is now set up */
@ -2905,8 +2943,10 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
if (scope_allocated) if (scope_allocated)
terminate_scope(runtime_bus, arg_machine); terminate_scope(runtime_bus, arg_machine);
if (registered) if (registered_system)
(void) unregister_machine(system_bus, arg_machine); (void) unregister_machine(system_bus, arg_machine);
if (registered_runtime)
(void) unregister_machine(runtime_bus, arg_machine);
if (use_vsock) { if (use_vsock) {
if (exit_status == INT_MAX) { if (exit_status == INT_MAX) {
@ -2928,8 +2968,12 @@ static int determine_names(void) {
if (arg_machine) { if (arg_machine) {
_cleanup_(image_unrefp) Image *i = NULL; _cleanup_(image_unrefp) Image *i = NULL;
r = image_find(arg_privileged ? RUNTIME_SCOPE_SYSTEM : RUNTIME_SCOPE_USER, /* Use both user and system images in user mode, use only system images in system mode. */
IMAGE_MACHINE, arg_machine, NULL, &i); r = image_find(arg_runtime_scope == RUNTIME_SCOPE_USER ? _RUNTIME_SCOPE_INVALID : arg_runtime_scope,
IMAGE_MACHINE,
arg_machine,
/* root= */ NULL,
&i);
if (r == -ENOENT) if (r == -ENOENT)
return log_error_errno(r, "No image for machine '%s'.", arg_machine); return log_error_errno(r, "No image for machine '%s'.", arg_machine);
if (r < 0) if (r < 0)
@ -2993,7 +3037,7 @@ static int run(int argc, char *argv[]) {
log_setup(); log_setup();
arg_privileged = getuid() == 0; arg_runtime_scope = getuid() == 0 ? RUNTIME_SCOPE_SYSTEM : RUNTIME_SCOPE_USER;
r = parse_environment(); r = parse_environment();
if (r < 0) if (r < 0)

View File

@ -115,3 +115,8 @@ Peer=1.1.8.104/31
[Route] [Route]
Gateway=1.1.8.104 Gateway=1.1.8.104
[Route]
Destination=192.168.20.0/24
MultiPathRoute=@test1 15
MultiPathRoute=@dummy98 25

View File

@ -4392,6 +4392,13 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
self.assertIn('via 2001:1234:5:8fff:ff:ff:ff:ff dev dummy98', output) self.assertIn('via 2001:1234:5:8fff:ff:ff:ff:ff dev dummy98', output)
self.assertIn('via 2001:1234:5:9fff:ff:ff:ff:ff dev dummy98', output) self.assertIn('via 2001:1234:5:9fff:ff:ff:ff:ff dev dummy98', output)
print('### ip route show 192.168.20.0/24')
output = check_output('ip route show 192.168.20.0/24')
print(output)
self.assertIn('192.168.20.0/24 proto static', output)
self.assertIn('nexthop dev test1 weight 15', output)
self.assertIn('nexthop dev dummy98 weight 25', output)
check_json(networkctl_json()) check_json(networkctl_json())
def _check_unreachable_routes_removed(self): def _check_unreachable_routes_removed(self):

View File

@ -310,7 +310,7 @@ units = [
{ {
'file' : 'systemd-coredump.socket', 'file' : 'systemd-coredump.socket',
'conditions' : ['ENABLE_COREDUMP'], 'conditions' : ['ENABLE_COREDUMP'],
'symlinks' : ['sockets.target.wants/'], 'symlinks' : ['sockets.target.wants/', 'system-update-pre.target.wants/'],
}, },
{ {
'file' : 'systemd-coredump@.service.in', 'file' : 'systemd-coredump@.service.in',