diff --git a/README b/README index 84f2b3ae41f25..9492d717dec06 100644 --- a/README +++ b/README @@ -216,11 +216,10 @@ REQUIREMENTS: libmount >= 2.30 (from util-linux) (util-linux *must* be built without --enable-libmount-support-mtab) libseccomp >= 2.3.1 (optional) - libblkid >= 2.24 (from util-linux) (optional) + libblkid >= 2.37 (from util-linux) (optional) libkmod >= 15 (optional) PAM >= 1.1.2 (optional) - libcryptsetup >= 2.0.1 (optional), - >= 2.3.0 is required for signed Verity images support + libcryptsetup >= 2.4.0 (optional), libaudit (optional) libacl (optional) libbpf >= 0.1.0 (optional), @@ -243,11 +242,11 @@ REQUIREMENTS: libcurl >= 7.32.0 (optional) libidn2 or libidn (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) libfido2 (optional) tpm2-tss (optional) - elfutils >= 158 (optional) + elfutils >= 177 (optional) polkit (optional) tzdata >= 2014f (optional) pkg-config diff --git a/docs/PASSWORD_AGENTS.md b/docs/PASSWORD_AGENTS.md index b6c0f051c21c5..7460409d1f4bb 100644 --- a/docs/PASSWORD_AGENTS.md +++ b/docs/PASSWORD_AGENTS.md @@ -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 (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) -* `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. * 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. @@ -100,4 +102,4 @@ now available, with the same protocol as the system-wide counterpart. Unprivileged, per-directory agents should watch this directory in 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 -files in. +files in. If the directory does not exist, agents may create it. diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml index 466e98aa519f3..708793d7d1bed 100644 --- a/man/org.freedesktop.systemd1.xml +++ b/man/org.freedesktop.systemd1.xml @@ -12664,8 +12664,8 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \ LogsDirectoryQuotaUsage, LogsDirectoryAccounting, and KillSubgroup() were added in version 258. - OOMKills, and - UserNamespacePath, and + UserNamespacePath, + OOMKills, and ManagedOOMKills were added in 259. BindNetworkInterface was added in version 260. diff --git a/man/systemd-vmspawn.xml b/man/systemd-vmspawn.xml index 7fd19671cbcc4..e51b7e8b6934b 100644 --- a/man/systemd-vmspawn.xml +++ b/man/systemd-vmspawn.xml @@ -69,6 +69,18 @@ + + + + + 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. + + + + diff --git a/man/systemd.network.xml b/man/systemd.network.xml index b9f49a43a804a..b00c2c6795702 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -2325,13 +2325,20 @@ NFTSet=prefix:netdev:filter:eth_ipv4_prefix - MultiPathRoute=address[@name] [weight] + MultiPathRoute= Configures multipath route. Multipath routing is the technique of using multiple - alternative paths through a network. Takes gateway address. Optionally, takes a network - interface name or index separated with @, and a weight in 1..256 for this - multipath route separated with whitespace. This setting can be specified multiple times. If - an empty string is assigned, then the all previous assignments are cleared. + alternative paths through a network. Takes a gateway address and/or a network interface + name or index (prefixed with @). At least one of these must be specified. + Optionally, a weight in 1..256 can be specified, separated with whitespace. This setting + can be specified multiple times. If an empty string is assigned, then all previous + assignments are cleared. + + Examples: + MultiPathRoute=10.0.0.1@eth0 20 +MultiPathRoute=192.168.1.1 50 +MultiPathRoute=@wg0 15 +MultiPathRoute=2001:db8::1@eth0 diff --git a/meson.build b/meson.build index bcf1ff2df592d..26b6fea22ca50 100644 --- a/meson.build +++ b/meson.build @@ -1229,10 +1229,9 @@ conf.set10('HAVE_AUDIT', libaudit.found()) libaudit_cflags = libaudit.partial_dependency(includes: true, compile_args: true) libblkid = dependency('blkid', + version : '>=2.37.0', required : get_option('blkid')) 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) libkmod = dependency('libkmod', @@ -1277,19 +1276,16 @@ if libcryptsetup_plugins.enabled() endif libcryptsetup = dependency('libcryptsetup', - version : libcryptsetup_plugins.enabled() ? '>= 2.4.0' : '>= 2.0.1', + version : '>= 2.4.0', required : libcryptsetup) libcryptsetup_cflags = libcryptsetup.partial_dependency(includes: true, compile_args: true) have = libcryptsetup.found() conf.set10('HAVE_LIBCRYPTSETUP', have) +conf.set10('HAVE_LIBCRYPTSETUP_PLUGINS', + libcryptsetup_plugins.allowed() and have) 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_token_set_external_path', # 2.7 ] @@ -1301,12 +1297,6 @@ foreach ident : [ conf.set10('HAVE_' + ident.to_upper(), have_ident) 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', version : '>= 7.32.0', required : get_option('libcurl')) @@ -1355,7 +1345,7 @@ libgnutls = dependency('gnutls', conf.set10('HAVE_GNUTLS', libgnutls.found()) libopenssl = dependency('openssl', - version : '>= 1.1.0', + version : '>= 3.0.0', required : get_option('openssl')) 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')) libdw = dependency('libdw', + version : '>=0.177', required : get_option('elfutils')) libdw_cflags = libdw.partial_dependency(includes: true, compile_args: true) libelf = dependency('libelf', @@ -1388,10 +1379,6 @@ libelf = dependency('libelf', libelf_cflags = libelf.partial_dependency(includes: true, compile_args: true) 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 conf.set10('HAVE_DWFL_SET_SYSROOT', libdw.found() and cc.has_function('dwfl_set_sysroot', dependencies : libdw)) diff --git a/shell-completion/bash/systemd-vmspawn b/shell-completion/bash/systemd-vmspawn index 7043ce2c89a47..52c3a84e36c07 100644 --- a/shell-completion/bash/systemd-vmspawn +++ b/shell-completion/bash/systemd-vmspawn @@ -29,7 +29,7 @@ _systemd_vmspawn() { local i verb comps 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' [BOOL]='--kvm --vsock --tpm --secure-boot --discard-disk --register --pass-ssh-key' [FIRMWARE]='--firmware' diff --git a/src/basic/unit-def.h b/src/basic/unit-def.h index d346174d56fcf..0324dc5a37433 100644 --- a/src/basic/unit-def.h +++ b/src/basic/unit-def.h @@ -317,7 +317,6 @@ DECLARE_STRING_TABLE_LOOKUP(unit_type, UnitType); void unit_types_list(void); DECLARE_STRING_TABLE_LOOKUP(unit_load_state, UnitLoadState); - DECLARE_STRING_TABLE_LOOKUP(unit_active_state, UnitActiveState); 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_; DECLARE_STRING_TABLE_LOOKUP(unit_marker, UnitMarker); - DECLARE_STRING_TABLE_LOOKUP(automount_state, AutomountState); - DECLARE_STRING_TABLE_LOOKUP(device_state, DeviceState); - DECLARE_STRING_TABLE_LOOKUP(mount_state, MountState); - DECLARE_STRING_TABLE_LOOKUP(path_state, PathState); - DECLARE_STRING_TABLE_LOOKUP(scope_state, ScopeState); - DECLARE_STRING_TABLE_LOOKUP(service_state, ServiceState); - DECLARE_STRING_TABLE_LOOKUP(slice_state, SliceState); - DECLARE_STRING_TABLE_LOOKUP(socket_state, SocketState); - DECLARE_STRING_TABLE_LOOKUP(swap_state, SwapState); - DECLARE_STRING_TABLE_LOOKUP(target_state, TargetState); - DECLARE_STRING_TABLE_LOOKUP(timer_state, TimerState); - DECLARE_STRING_TABLE_LOOKUP(unit_dependency, UnitDependency); - DECLARE_STRING_TABLE_LOOKUP(notify_access, NotifyAccess); - DECLARE_STRING_TABLE_LOOKUP(job_mode, JobMode); - DECLARE_STRING_TABLE_LOOKUP(exec_directory_type, ExecDirectoryType); Glyph unit_active_state_to_glyph(UnitActiveState state); diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index eb545fd0234ff..e61f4b4606ac5 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -331,11 +331,8 @@ static int parse_one_option(const char *option) { arg_no_write_workqueue = true; else if (streq(option, "luks")) arg_type = ANY_LUKS; -/* since cryptsetup 2.3.0 (Feb 2020) */ -#ifdef CRYPT_BITLK else if (streq(option, "bitlk")) arg_type = CRYPT_BITLK; -#endif else if (streq(option, "tcrypt")) arg_type = CRYPT_TCRYPT; else if (STR_IN_SET(option, "tcrypt-hidden", "tcrypthidden")) { @@ -2492,11 +2489,9 @@ static uint32_t determine_flags(void) { if (arg_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 */ /* https://gitlab.com/cryptsetup/cryptsetup/issues/446/ */ flags |= CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF; -#endif 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)) { r = crypt_load(cd, CRYPT_BITLK, NULL); if (r < 0) 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; const char *discovered_key_fn = strjoina(volume, ".key"); diff --git a/src/network/networkd-route-nexthop.c b/src/network/networkd-route-nexthop.c index 9f5970270e069..bebb401b3395f 100644 --- a/src/network/networkd-route-nexthop.c +++ b/src/network/networkd-route-nexthop.c @@ -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. */ siphash24_compress_typesafe(nh->family, state); - if (!IN_SET(nh->family, AF_INET, AF_INET6)) - return; - in_addr_hash_func(&nh->gw, nh->family, state); + /* 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); + if (with_weight) siphash24_compress_typesafe(nh->weight, 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) return r; - if (!IN_SET(a->family, AF_INET, AF_INET6)) - return 0; - - r = memcmp(&a->gw, &b->gw, FAMILY_ADDRESS_SIZE(a->family)); - if (r != 0) - return r; + /* For device-only nexthops parsed from config, family is AF_UNSPEC until verification. + * 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)); + if (r != 0) + return r; + } if (with_weight) { r = CMP(a->weight, b->weight); @@ -553,30 +556,34 @@ static int append_nexthop_one(const Route *route, const RouteNextHop *nh, struct (*rta)->rta_len += sizeof(struct rtnexthop); - if (nh->family == route->family) { - r = rtattr_append_attribute(rta, RTA_GATEWAY, &nh->gw, FAMILY_ADDRESS_SIZE(nh->family)); - if (r < 0) - goto clear; + /* 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) { + r = rtattr_append_attribute(rta, RTA_GATEWAY, &nh->gw, FAMILY_ADDRESS_SIZE(nh->family)); + if (r < 0) + goto clear; - rtnh = (struct rtnexthop *)((uint8_t *) *rta + offset); - rtnh->rtnh_len += RTA_SPACE(FAMILY_ADDRESS_SIZE(nh->family)); + rtnh = (struct rtnexthop *)((uint8_t *) *rta + offset); + rtnh->rtnh_len += RTA_SPACE(FAMILY_ADDRESS_SIZE(nh->family)); - } else if (nh->family == AF_INET6) { - assert(route->family == AF_INET); + } else if (nh->family == AF_INET6) { + assert(route->family == AF_INET); - r = rtattr_append_attribute(rta, RTA_VIA, - &(RouteVia) { - .family = nh->family, - .address = nh->gw, - }, sizeof(RouteVia)); - if (r < 0) - goto clear; + r = rtattr_append_attribute(rta, RTA_VIA, + &(RouteVia) { + .family = nh->family, + .address = nh->gw, + }, sizeof(RouteVia)); + if (r < 0) + goto clear; - rtnh = (struct rtnexthop *)((uint8_t *) *rta + offset); - rtnh->rtnh_len += RTA_SPACE(sizeof(RouteVia)); + rtnh = (struct rtnexthop *)((uint8_t *) *rta + offset); + rtnh->rtnh_len += RTA_SPACE(sizeof(RouteVia)); - } else if (nh->family == AF_INET) - assert_not_reached(); + } else if (nh->family == AF_INET) + assert_not_reached(); + } return 0; @@ -1080,11 +1087,16 @@ int config_parse_multipath_route( } } - r = in_addr_from_string_auto(word, &nh->family, &nh->gw); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, - "Invalid multipath route gateway '%s', ignoring assignment: %m", rvalue); - return 0; + 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); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Invalid multipath route gateway '%s', ignoring assignment: %m", rvalue); + return 0; + } } if (!isempty(p)) { diff --git a/src/network/test-networkd-conf.c b/src/network/test-networkd-conf.c index ddb8fcaa36ae7..00791cea91335 100644 --- a/src/network/test-networkd-conf.c +++ b/src/network/test-networkd-conf.c @@ -6,6 +6,8 @@ #include "networkd-address.h" #include "networkd-manager.h" #include "networkd-network.h" +#include "networkd-route-nexthop.h" +#include "ordered-set.h" #include "set.h" #include "strv.h" #include "tests.h" @@ -263,4 +265,163 @@ TEST(config_parse_match_strv) { "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); diff --git a/src/repart/repart.c b/src/repart/repart.c index e3a6e7efafe8b..706349a2cf4e1 100644 --- a/src/repart/repart.c +++ b/src/repart/repart.c @@ -5442,11 +5442,7 @@ static int partition_encrypt(Context *context, Partition *p, PartitionTarget *ta if (r < 0) return log_error_errno(r, "Failed to load reencryption context: %m"); -#if HAVE_CRYPT_REENCRYPT_RUN r = sym_crypt_reencrypt_run(cd, NULL, NULL); -#else - r = sym_crypt_reencrypt(cd, NULL); -#endif if (r < 0) return log_error_errno(r, "Failed to encrypt %s: %m", node); } else { @@ -5507,7 +5503,7 @@ static int partition_encrypt(Context *context, Partition *p, PartitionTarget *ta return 0; #else 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 } diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c index 537370f0a9c87..ced874e2ba9f2 100644 --- a/src/resolve/resolved-dns-dnssec.c +++ b/src/resolve/resolved-dns-dnssec.c @@ -17,7 +17,7 @@ #include "string-util.h" #include "time-util.h" -#if HAVE_OPENSSL && OPENSSL_VERSION_MAJOR >= 3 +#if HAVE_OPENSSL DISABLE_WARNING_DEPRECATED_DECLARATIONS; DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(RSA*, RSA_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EC_KEY*, EC_KEY_free, NULL); diff --git a/src/shared/cryptsetup-util.c b/src/shared/cryptsetup-util.c index 90e98c1b8370e..5d99edd52d106 100644 --- a/src/shared/cryptsetup-util.c +++ b/src/shared/cryptsetup-util.c @@ -39,11 +39,7 @@ DLSYM_PROTOTYPE(crypt_keyslot_max) = NULL; DLSYM_PROTOTYPE(crypt_load) = NULL; DLSYM_PROTOTYPE(crypt_metadata_locking) = NULL; DLSYM_PROTOTYPE(crypt_reencrypt_init_by_passphrase) = NULL; -#if HAVE_CRYPT_REENCRYPT_RUN DLSYM_PROTOTYPE(crypt_reencrypt_run); -#else -DLSYM_PROTOTYPE(crypt_reencrypt); -#endif DLSYM_PROTOTYPE(crypt_resize) = NULL; DLSYM_PROTOTYPE(crypt_resume_by_volume_key) = 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_token_json_get) = NULL; DLSYM_PROTOTYPE(crypt_token_json_set) = NULL; -#if HAVE_CRYPT_TOKEN_MAX 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 DLSYM_PROTOTYPE(crypt_token_set_external_path) = NULL; #endif @@ -252,11 +240,7 @@ int dlopen_cryptsetup(void) { DLSYM_ARG(crypt_load), DLSYM_ARG(crypt_metadata_locking), DLSYM_ARG(crypt_reencrypt_init_by_passphrase), -#if HAVE_CRYPT_REENCRYPT_RUN DLSYM_ARG(crypt_reencrypt_run), -#else - DLSYM_ARG(crypt_reencrypt), -#endif DLSYM_ARG(crypt_resize), DLSYM_ARG(crypt_resume_by_volume_key), DLSYM_ARG(crypt_set_data_device), @@ -268,9 +252,7 @@ int dlopen_cryptsetup(void) { DLSYM_ARG(crypt_suspend), DLSYM_ARG(crypt_token_json_get), DLSYM_ARG(crypt_token_json_set), -#if HAVE_CRYPT_TOKEN_MAX DLSYM_ARG(crypt_token_max), -#endif #if HAVE_CRYPT_TOKEN_SET_EXTERNAL_PATH DLSYM_ARG(crypt_token_set_external_path), #endif diff --git a/src/shared/cryptsetup-util.h b/src/shared/cryptsetup-util.h index 7c520497967c2..e42debeeb464f 100644 --- a/src/shared/cryptsetup-util.h +++ b/src/shared/cryptsetup-util.h @@ -7,14 +7,6 @@ #if HAVE_LIBCRYPTSETUP #include /* 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_signed_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_metadata_locking); extern DLSYM_PROTOTYPE(crypt_reencrypt_init_by_passphrase); -#if HAVE_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_resume_by_volume_key); 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_token_json_get); extern DLSYM_PROTOTYPE(crypt_token_json_set); -#if HAVE_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 extern DLSYM_PROTOTYPE(crypt_token_set_external_path); #endif diff --git a/src/shared/elf-util.c b/src/shared/elf-util.c index a8cfb8cd22cb4..9a09352ca7fea 100644 --- a/src/shared/elf-util.c +++ b/src/shared/elf-util.c @@ -47,9 +47,7 @@ static DLSYM_PROTOTYPE(dwarf_formstring) = NULL; static DLSYM_PROTOTYPE(dwarf_getscopes) = NULL; static DLSYM_PROTOTYPE(dwarf_getscopes_die) = NULL; static DLSYM_PROTOTYPE(dwelf_elf_begin) = NULL; -#if HAVE_DWELF_ELF_E_MACHINE_STRING static DLSYM_PROTOTYPE(dwelf_elf_e_machine_string) = NULL; -#endif static DLSYM_PROTOTYPE(dwelf_elf_gnu_build_id) = NULL; static DLSYM_PROTOTYPE(dwarf_tag) = NULL; static DLSYM_PROTOTYPE(dwfl_addrmodule) = NULL; @@ -111,9 +109,7 @@ int dlopen_dw(void) { DLSYM_ARG(dwarf_diename), DLSYM_ARG(dwelf_elf_gnu_build_id), DLSYM_ARG(dwelf_elf_begin), -#if HAVE_DWELF_ELF_E_MACHINE_STRING DLSYM_ARG(dwelf_elf_e_machine_string), -#endif DLSYM_ARG(dwfl_addrmodule), DLSYM_ARG(dwfl_frame_pc), DLSYM_ARG(dwfl_module_addrdie), @@ -773,7 +769,6 @@ static int parse_elf( if (r < 0) 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); if (elf_architecture) { r = sd_json_variant_merge_objectbo( @@ -785,7 +780,6 @@ static int parse_elf( if (ret) 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). */ r = sd_json_variant_merge_object(&elf_metadata, package_metadata); diff --git a/src/shared/openssl-util.c b/src/shared/openssl-util.c index 0e54ae527af00..e564c2cb7b4e7 100644 --- a/src/shared/openssl-util.c +++ b/src/shared/openssl-util.c @@ -97,21 +97,12 @@ int openssl_digest_size(const char *digest_alg, size_t *ret_digest_size) { assert(digest_alg); assert(ret_digest_size); -#if OPENSSL_VERSION_MAJOR >= 3 _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) return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Digest algorithm '%s' not supported.", digest_alg); - size_t digest_size; -#if OPENSSL_VERSION_MAJOR >= 3 - digest_size = EVP_MD_get_size(md); -#else - digest_size = EVP_MD_size(md); -#endif + size_t digest_size = EVP_MD_get_size(md); if (digest_size == 0) return log_openssl_errors("Failed to get Digest size"); @@ -136,11 +127,7 @@ int openssl_digest_many( assert(ret_digest); /* 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); -#else - const EVP_MD *md = EVP_get_digestbyname(digest_alg); -#endif if (!md) return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Digest algorithm '%s' not supported.", digest_alg); @@ -196,16 +183,11 @@ int openssl_hmac_many( assert(ret_digest); /* 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); -#else - const EVP_MD *md = EVP_get_digestbyname(digest_alg); -#endif if (!md) return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "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); if (!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)) 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++) -#if OPENSSL_VERSION_MAJOR >= 3 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"); - size_t digest_size; -#if OPENSSL_VERSION_MAJOR >= 3 - digest_size = EVP_MAC_CTX_get_mac_size(ctx); -#else - digest_size = HMAC_size(ctx); -#endif + size_t digest_size = EVP_MAC_CTX_get_mac_size(ctx); if (digest_size == 0) return log_openssl_errors("Failed to get HMAC digest size"); @@ -257,13 +222,8 @@ int openssl_hmac_many( if (!buf) return log_oom_debug(); -#if OPENSSL_VERSION_MAJOR >= 3 size_t 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"); assert(size == digest_size); @@ -306,11 +266,7 @@ int openssl_cipher_many( if (asprintf(&cipher_alg, "%s-%zu-%s", alg, bits, mode) < 0) return log_oom_debug(); -#if OPENSSL_VERSION_MAJOR >= 3 _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) return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Cipher algorithm '%s' not supported.", cipher_alg); @@ -391,7 +347,6 @@ int kdf_ss_derive( size_t derive_size, void **ret) { -#if OPENSSL_VERSION_MAJOR >= 3 assert(digest); assert(key); assert(derive_size > 0); @@ -437,9 +392,6 @@ int kdf_ss_derive( *ret = TAKE_PTR(buf); 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 @@ -461,7 +413,6 @@ int kdf_kb_hmac_derive( size_t derive_size, void **ret) { -#if OPENSSL_VERSION_MAJOR >= 3 assert(mode); assert(strcaseeq(mode, "COUNTER") || strcaseeq(mode, "FEEDBACK")); assert(digest); @@ -523,9 +474,6 @@ int kdf_kb_hmac_derive( *ret = TAKE_PTR(buf); return 0; -#else - return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "KDF-KB requires OpenSSL >= 3."); -#endif } int rsa_encrypt_bytes( @@ -583,11 +531,7 @@ int rsa_oaep_encrypt_bytes( assert(ret_encrypt_key); assert(ret_encrypt_key_size); -#if OPENSSL_VERSION_MAJOR >= 3 _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) return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "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(ret); -#if OPENSSL_VERSION_MAJOR >= 3 _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); if (!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) 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); @@ -749,7 +664,6 @@ int rsa_pkey_to_n_e( assert(ret_e); assert(ret_e_size); -#if OPENSSL_VERSION_MAJOR >= 3 _cleanup_(BN_freep) BIGNUM *bn_n = NULL; if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &bn_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; if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &bn_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); _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)) return log_openssl_errors("Failed to set ECC coordinates"); -#if OPENSSL_VERSION_MAJOR >= 3 if (EVP_PKEY_fromdata_init(ctx) <= 0) 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; if (EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0) 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); return 0; @@ -888,7 +768,6 @@ int ecc_pkey_to_curve_x_y( assert(pkey); -#if OPENSSL_VERSION_MAJOR >= 3 size_t 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"); @@ -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)) 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); _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_free_ unsigned char *saved_key = NULL; size_t decrypted_key_size, saved_key_size; - int nid = NID_undef; int r; -#if OPENSSL_VERSION_MAJOR >= 3 _cleanup_free_ char *curve_name = NULL; 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) return log_openssl_errors("Failed to get PKEY group name"); - nid = OBJ_sn2nid(curve_name); -#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); + r = ecc_pkey_new(OBJ_sn2nid(curve_name), &pkey_new); if (r < 0) 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) 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. See https://github.com/openssl/openssl/discussions/22835 */ saved_key_size = EVP_PKEY_get1_encoded_public_key(pkey_new, &saved_key); if (saved_key_size == 0) 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_size = decrypted_key_size; @@ -1375,11 +1188,7 @@ int pkey_generate_volume_keys( assert(ret_saved_key); assert(ret_saved_key_size); -#if OPENSSL_VERSION_MAJOR >= 3 int type = EVP_PKEY_get_base_id(pkey); -#else - int type = EVP_PKEY_base_id(pkey); -#endif switch (type) { case EVP_PKEY_RSA: @@ -1405,7 +1214,6 @@ static int load_key_from_provider( assert(private_key_uri); assert(ret); -#if OPENSSL_VERSION_MAJOR >= 3 /* 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. */ 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); return 0; -#else - return -EOPNOTSUPP; -#endif } 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(ret); -#if OPENSSL_VERSION_MAJOR >= 3 /* 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. */ 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); return 0; -#else - return -EOPNOTSUPP; -#endif } OpenSSLAskPasswordUI* openssl_ask_password_ui_free(OpenSSLAskPasswordUI *ui) { @@ -1712,17 +1513,20 @@ int openssl_load_private_key( 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(request); assert(ret_private_key); + assert(ret_user_interface); if (private_key_source_type == OPENSSL_KEY_SOURCE_FILE) { r = openssl_load_private_key_from_file(private_key, ret_private_key); if (r < 0) return r; - if (ret_user_interface) - *ret_user_interface = NULL; + *ret_user_interface = NULL; } else { _cleanup_(openssl_ask_password_ui_freep) OpenSSLAskPasswordUI *ui = NULL; r = openssl_ask_password_ui_new(request, &ui); @@ -1747,8 +1551,7 @@ int openssl_load_private_key( private_key, private_key_source); - if (ret_user_interface) - *ret_user_interface = TAKE_PTR(ui); + *ret_user_interface = TAKE_PTR(ui); } return 0; diff --git a/src/shared/openssl-util.h b/src/shared/openssl-util.h index cb48ea8bfd320..218641e06fe61 100644 --- a/src/shared/openssl-util.h +++ b/src/shared/openssl-util.h @@ -32,27 +32,21 @@ int parse_openssl_key_source_argument(const char *argument, char **private_key_s #if HAVE_OPENSSL # include /* IWYU pragma: export */ # include /* IWYU pragma: export */ +# include /* IWYU pragma: export */ # include /* IWYU pragma: export */ # include /* IWYU pragma: export */ # include /* IWYU pragma: export */ +# include /* IWYU pragma: export */ # include /* IWYU pragma: export */ +# include /* IWYU pragma: export */ # include /* IWYU pragma: export */ +# include /* IWYU pragma: export */ # include /* IWYU pragma: export */ +# include /* IWYU pragma: export */ # ifndef OPENSSL_NO_UI_CONSOLE # include /* IWYU pragma: export */ # endif # include /* 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 /* IWYU pragma: export */ -# include /* IWYU pragma: export */ -# include /* IWYU pragma: export */ -# include /* IWYU pragma: export */ -# include /* IWYU pragma: export */ -# endif DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_MACRO(void*, OPENSSL_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_POINT*, EC_POINT_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_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_PKEY*, EVP_PKEY_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_SIGNER_INFO*, PKCS7_SIGNER_INFO_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); -#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) { if (!sk || !*sk) return; diff --git a/src/shared/pkcs11-util.c b/src/shared/pkcs11-util.c index 2111e4b966c47..3062bcc554196 100644 --- a/src/shared/pkcs11-util.c +++ b/src/shared/pkcs11-util.c @@ -546,7 +546,6 @@ int pkcs11_token_read_public_key( if (!os) 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); if (!ctx) 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) 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; } default: diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c index e089cfbc5eaff..4ba83a47ae0dc 100644 --- a/src/shared/tpm2-util.c +++ b/src/shared/tpm2-util.c @@ -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) * tpm2_calculate_policy_authorize(). See bug #30546. */ int tpm2_tpm2b_public_from_openssl_pkey(const EVP_PKEY *pkey, TPM2B_PUBLIC *ret) { - int key_id, r; + int r; assert(pkey); 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 - key_id = EVP_PKEY_get_id(pkey); -#else - key_id = EVP_PKEY_id(pkey); -#endif - + int key_id = EVP_PKEY_get_id(pkey); switch (key_id) { case EVP_PKEY_EC: { public.type = TPM2_ALG_ECC; diff --git a/src/sysupdate/sysupdated.c b/src/sysupdate/sysupdated.c index a9740ee854237..4eeaf3a706213 100644 --- a/src/sysupdate/sysupdated.c +++ b/src/sysupdate/sysupdated.c @@ -543,7 +543,7 @@ static int job_start(Job *j) { r = sd_event_source_set_child_process_own(j->child, true); if (r < 0) 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); diff --git a/src/test/test-openssl.c b/src/test/test-openssl.c index d4c254e50ad8a..a09484a2ba8ad 100644 --- a/src/test/test-openssl.c +++ b/src/test/test-openssl.c @@ -103,15 +103,12 @@ static const struct { } digest_size_table[] = { /* SHA1 "family" */ { "sha1", 20, }, -#if OPENSSL_VERSION_MAJOR >= 3 { "sha-1", 20, }, -#endif /* SHA2 family */ { "sha224", 28, }, { "sha256", 32, }, { "sha384", 48, }, { "sha512", 64, }, -#if OPENSSL_VERSION_MAJOR >= 3 { "sha-224", 28, }, { "sha2-224", 28, }, { "sha-256", 32, }, @@ -120,7 +117,6 @@ static const struct { { "sha2-384", 48, }, { "sha-512", 64, }, { "sha2-512", 64, }, -#endif /* SHA3 family */ { "sha3-224", 28, }, { "sha3-256", 32, }, @@ -296,7 +292,6 @@ TEST(hmac_many) { } TEST(kdf_kb_hmac_derive) { -#if OPENSSL_VERSION_MAJOR >= 3 _cleanup_free_ void *derived_key = NULL; 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(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) { DEFINE_HEX_PTR(key, hex_key); 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(memcmp_nn(derived_key, expected_len, expected, expected_len) == 0); } -#endif TEST(kdf_ss_derive) { -#if OPENSSL_VERSION_MAJOR >= 3 check_ss_derive( "01166ad6b05d1fad8cdb50d1902170e9", "feea805789dc8d0b57da5d4d61886b1a", @@ -343,9 +332,6 @@ TEST(kdf_ss_derive) { "b75e3b65d1bb845dee581c7e14cfebc6e882946e90273b77ebe289faaf7de248", "ed25a0043d6c1eb28296da1f9ab138dafee18f4c937bfc43601d4ee6e7634199", "30EB1A1E9DEA7DE4DDB8F3FDF50A01E30581D606C1228D98AFF691DF743AC2EE9D99EFD2AE1946C079AA18C9524877FA65D5065F0DAED058AB3416AF80EB2B73"); -#else - log_tests_skipped("KDF-SS requires OpenSSL >= 3"); -#endif } static void check_cipher( diff --git a/src/test/test-tpm2.c b/src/test/test-tpm2.c index 94a92fd2c6e96..a6164f2677d52 100644 --- a/src/test/test-tpm2.c +++ b/src/test/test-tpm2.c @@ -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); } -#if HAVE_OPENSSL && OPENSSL_VERSION_MAJOR >= 3 +#if HAVE_OPENSSL static void calculate_seal_and_unseal( Tpm2Context *c, TPM2_HANDLE parent_index, @@ -1228,7 +1228,7 @@ static int check_calculate_seal(Tpm2Context *c) { return 0; } -#endif /* HAVE_OPENSSL && OPENSSL_VERSION_MAJOR >= 3 */ +#endif /* HAVE_OPENSSL */ static void check_seal_unseal_for_handle(Tpm2Context *c, TPM2_HANDLE handle) { 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_seal_unseal(c); -#if HAVE_OPENSSL && OPENSSL_VERSION_MAJOR >= 3 /* calculating sealed object requires openssl >= 3 */ +#if HAVE_OPENSSL r = check_calculate_seal(c); #endif diff --git a/src/udev/udev-builtin-blkid.c b/src/udev/udev-builtin-blkid.c index 5e7f78eebced8..6ec02674b9fd6 100644 --- a/src/udev/udev-builtin-blkid.c +++ b/src/udev/udev-builtin-blkid.c @@ -458,21 +458,11 @@ static int builtin_blkid(UdevEvent *event, int argc, char *argv[]) { switch (option) { case 'H': -#if HAVE_BLKID_PROBE_SET_HINT errno = 0; r = sym_blkid_probe_set_hint(pr, optarg, 0); if (r < 0) return log_device_error_errno(dev, errno_or_else(ENOMEM), "Failed to use '%s' probing hint: %m", optarg); break; -#else - /* Use the hint = 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': r = safe_atoi64(optarg, &offset); if (r < 0) @@ -489,7 +479,7 @@ static int builtin_blkid(UdevEvent *event, int argc, char *argv[]) { sym_blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE | -#ifdef BLKID_SUBLKS_FSINFO +#ifdef BLKID_SUBLKS_FSINFO /* since util-linux 2.39 */ BLKID_SUBLKS_FSINFO | #endif BLKID_SUBLKS_USAGE | BLKID_SUBLKS_VERSION); diff --git a/src/udev/udev-watch.c b/src/udev/udev-watch.c index 76de67733f458..10cbc848460db 100644 --- a/src/udev/udev-watch.c +++ b/src/udev/udev-watch.c @@ -208,11 +208,6 @@ static int synthesize_change(Manager *manager, sd_device *dev) { 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); if (r < 0) return r; diff --git a/src/veritysetup/veritysetup.c b/src/veritysetup/veritysetup.c index 586af5c62383f..91b5bcaaa28d3 100644 --- a/src/veritysetup/veritysetup.c +++ b/src/veritysetup/veritysetup.c @@ -161,14 +161,10 @@ static int parse_options(const char *options) { arg_activate_flags |= CRYPT_ACTIVATE_RESTART_ON_CORRUPTION; else if (streq(word, "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")) arg_activate_flags |= CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE; -#endif -#ifdef CRYPT_ACTIVATE_PANIC_ON_CORRUPTION else if (streq(word, "panic-on-corruption")) arg_activate_flags |= CRYPT_ACTIVATE_PANIC_ON_CORRUPTION; -#endif else if ((val = startswith(word, "superblock="))) { r = parse_boolean(val); diff --git a/src/vmspawn/vmspawn-register.c b/src/vmspawn/vmspawn-register.c index b33f86becf094..46f292ce49525 100644 --- a/src/vmspawn/vmspawn-register.c +++ b/src/vmspawn/vmspawn-register.c @@ -12,6 +12,7 @@ #include "errno-util.h" #include "json-util.h" #include "log.h" +#include "path-lookup.h" #include "pidref.h" #include "socket-util.h" #include "string-util.h" @@ -29,7 +30,8 @@ int register_machine( unsigned cid, const char *address, const char *key_path, - bool keep_unit) { + bool allocate_unit, + RuntimeScope scope) { _cleanup_(sd_varlink_unrefp) sd_varlink *vl = NULL; int r; @@ -38,7 +40,12 @@ int register_machine( assert(service); /* 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)) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; @@ -59,12 +66,12 @@ int register_machine( (uint32_t) (pidref_is_set(pidref) ? pidref->pid : 0), strempty(directory)); if (r < 0) - return log_error_errno(r, "Failed to register machine: %s", bus_error_message(&error, r)); + return log_error_errno(r, "Failed to register machine: %s", bus_error_message(&error, r)); return 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( 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(!!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(!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))); } diff --git a/src/vmspawn/vmspawn-register.h b/src/vmspawn/vmspawn-register.h index eeee16f701156..de118b7492fa2 100644 --- a/src/vmspawn/vmspawn-register.h +++ b/src/vmspawn/vmspawn-register.h @@ -13,6 +13,7 @@ int register_machine( unsigned cid, const char *address, const char *key_path, - bool keep_unit); + bool allocate_unit, + RuntimeScope scope); int unregister_machine(sd_bus *bus, const char *machine_name); diff --git a/src/vmspawn/vmspawn.c b/src/vmspawn/vmspawn.c index 291cac3be1525..8951e19704a77 100644 --- a/src/vmspawn/vmspawn.c +++ b/src/vmspawn/vmspawn.c @@ -123,7 +123,6 @@ static uid_t arg_uid_shift = UID_INVALID, arg_uid_range = 0x10000U; static RuntimeMountContext arg_runtime_mounts = {}; static char *arg_firmware = NULL; static char *arg_forward_journal = NULL; -static bool arg_privileged = false; static bool arg_register = true; static bool arg_keep_unit = false; static sd_id128_t arg_uuid = {}; @@ -144,6 +143,7 @@ static char **arg_bind_user = NULL; static char *arg_bind_user_shell = NULL; static bool arg_bind_user_shell_copy = false; 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_image, freep); @@ -184,6 +184,8 @@ static int help(void) { " -q --quiet Do not show status information\n" " --no-pager Do not pipe output into a pager\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" " -D --directory=PATH Root directory 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_SHELL, ARG_BIND_USER_GROUP, + ARG_SYSTEM, + ARG_USER, }; 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-shell", required_argument, NULL, ARG_BIND_USER_SHELL }, { "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; + case ARG_SYSTEM: + arg_runtime_scope = RUNTIME_SCOPE_SYSTEM; + break; + + case ARG_USER: + arg_runtime_scope = RUNTIME_SCOPE_USER; + break; + case '?': 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 */ _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); if (r < 0) 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. */ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *user_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); else { 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) return log_oom(); - r = runtime_directory( - arg_privileged ? RUNTIME_SCOPE_SYSTEM : RUNTIME_SCOPE_USER, - subdir, - &runtime_dir); + r = runtime_directory(arg_runtime_scope, subdir, &runtime_dir); if (r < 0) return log_error_errno(r, "Failed to lookup runtime directory: %m"); 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; - if (!arg_keep_unit && (!arg_register || !arg_privileged)) { + if (!arg_keep_unit && (!arg_register || arg_runtime_scope != RUNTIME_SCOPE_SYSTEM)) { r = allocate_scope( runtime_bus, arg_machine, @@ -2778,7 +2789,7 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) { scope_allocated = true; } else { - if (arg_privileged) + if (arg_runtime_scope == RUNTIME_SCOPE_SYSTEM) r = cg_pid_get_unit(0, &unit); else 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"); } - bool registered = false; + bool registered_system = false, registered_runtime = false; if (arg_register) { char vm_address[STRLEN("vsock/") + DECIMAL_STR_MAX(unsigned)]; 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 != VMADDR_CID_ANY ? vm_address : NULL, ssh_private_key_path, - arg_keep_unit || !arg_privileged); - if (r < 0) - return r; + !arg_keep_unit && arg_runtime_scope == RUNTIME_SCOPE_SYSTEM, + RUNTIME_SCOPE_SYSTEM); + if (r < 0) { + /* if privileged the request to register definitely failed */ + if (arg_runtime_scope == RUNTIME_SCOPE_SYSTEM) + return r; + + 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; - registered = true; + 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 */ @@ -2905,8 +2943,10 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) { if (scope_allocated) terminate_scope(runtime_bus, arg_machine); - if (registered) + if (registered_system) (void) unregister_machine(system_bus, arg_machine); + if (registered_runtime) + (void) unregister_machine(runtime_bus, arg_machine); if (use_vsock) { if (exit_status == INT_MAX) { @@ -2928,8 +2968,12 @@ static int determine_names(void) { if (arg_machine) { _cleanup_(image_unrefp) Image *i = NULL; - r = image_find(arg_privileged ? RUNTIME_SCOPE_SYSTEM : RUNTIME_SCOPE_USER, - IMAGE_MACHINE, arg_machine, NULL, &i); + /* Use both user and system images in user mode, use only system images in system mode. */ + 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) return log_error_errno(r, "No image for machine '%s'.", arg_machine); if (r < 0) @@ -2993,7 +3037,7 @@ static int run(int argc, char *argv[]) { log_setup(); - arg_privileged = getuid() == 0; + arg_runtime_scope = getuid() == 0 ? RUNTIME_SCOPE_SYSTEM : RUNTIME_SCOPE_USER; r = parse_environment(); if (r < 0) diff --git a/test/test-network/conf/25-route-static.network b/test/test-network/conf/25-route-static.network index 5ddd7de61a5b1..8e0578f0584dc 100644 --- a/test/test-network/conf/25-route-static.network +++ b/test/test-network/conf/25-route-static.network @@ -115,3 +115,8 @@ Peer=1.1.8.104/31 [Route] Gateway=1.1.8.104 + +[Route] +Destination=192.168.20.0/24 +MultiPathRoute=@test1 15 +MultiPathRoute=@dummy98 25 diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index eb3911e066eaf..2843be3e2a297 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -4392,6 +4392,13 @@ def _check_route_static(self, test1_is_managed: bool): 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) + 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()) def _check_unreachable_routes_removed(self): diff --git a/units/meson.build b/units/meson.build index 2e04c4aa2b2c8..ddaefc56e8cc5 100644 --- a/units/meson.build +++ b/units/meson.build @@ -310,7 +310,7 @@ units = [ { 'file' : 'systemd-coredump.socket', 'conditions' : ['ENABLE_COREDUMP'], - 'symlinks' : ['sockets.target.wants/'], + 'symlinks' : ['sockets.target.wants/', 'system-update-pre.target.wants/'], }, { 'file' : 'systemd-coredump@.service.in',