From: Sam Leonard Date: Thu, 11 Apr 2024 11:26:10 +0000 (+0100) Subject: vmspawn: check firmware target architecture X-Git-Tag: v256-rc1~206 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=af49ea3371d54aecbfbfbbbe046b35040edcaaef;p=thirdparty%2Fsystemd.git vmspawn: check firmware target architecture Fixes issue #32026 by only finding firmwares which explicitly support the native architecture. --- diff --git a/src/vmspawn/vmspawn-util.c b/src/vmspawn/vmspawn-util.c index a98040a213a..9b2b45e1e63 100644 --- a/src/vmspawn/vmspawn-util.c +++ b/src/vmspawn/vmspawn-util.c @@ -26,6 +26,35 @@ #include "strv.h" #include "vmspawn-util.h" +static const char* const architecture_to_qemu_table[_ARCHITECTURE_MAX] = { + [ARCHITECTURE_ARM64] = "aarch64", /* differs from our name */ + [ARCHITECTURE_ARM] = "arm", + [ARCHITECTURE_ALPHA] = "alpha", + [ARCHITECTURE_X86_64] = "x86_64", /* differs from our name */ + [ARCHITECTURE_X86] = "i386", /* differs from our name */ + [ARCHITECTURE_LOONGARCH64] = "loongarch64", + [ARCHITECTURE_MIPS64_LE] = "mips", /* differs from our name */ + [ARCHITECTURE_MIPS_LE] = "mips", /* differs from our name */ + [ARCHITECTURE_PARISC] = "hppa", /* differs from our name */ + [ARCHITECTURE_PPC64_LE] = "ppc", /* differs from our name */ + [ARCHITECTURE_PPC64] = "ppc", /* differs from our name */ + [ARCHITECTURE_PPC] = "ppc", + [ARCHITECTURE_RISCV32] = "riscv32", + [ARCHITECTURE_RISCV64] = "riscv64", + [ARCHITECTURE_S390X] = "s390x", +}; + +static int native_arch_as_qemu(const char **ret) { + const char *s = architecture_to_qemu_table[native_architecture()]; + if (!s) + return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Architecture %s not supported by qemu", architecture_to_string(native_architecture())); + + if (ret) + *ret = s; + + return 0; +} + OvmfConfig* ovmf_config_free(OvmfConfig *config) { if (!config) return NULL; @@ -87,6 +116,7 @@ typedef struct FirmwareData { char *firmware_format; char *vars; char *vars_format; + char **architectures; } FirmwareData; static bool firmware_data_supports_sb(const FirmwareData *fwd) { @@ -104,6 +134,7 @@ static FirmwareData* firmware_data_free(FirmwareData *fwd) { free(fwd->firmware_format); free(fwd->vars); free(fwd->vars_format); + strv_free(fwd->architectures); return mfree(fwd); } @@ -140,6 +171,32 @@ static int firmware_mapping(const char *name, JsonVariant *v, JsonDispatchFlags return json_dispatch(v, table, flags, userdata); } +static int target_architecture(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + int r; + JsonVariant *e; + char ***supported_architectures = ASSERT_PTR(userdata); + + static const JsonDispatch table[] = { + { "architecture", JSON_VARIANT_STRING, json_dispatch_string, 0, JSON_MANDATORY }, + { "machines", JSON_VARIANT_ARRAY, NULL, 0, JSON_MANDATORY }, + {} + }; + + JSON_VARIANT_ARRAY_FOREACH(e, v) { + _cleanup_free_ char *arch = NULL; + + r = json_dispatch(e, table, flags, &arch); + if (r < 0) + return r; + + r = strv_consume(supported_architectures, TAKE_PTR(arch)); + if (r < 0) + return r; + } + + return 0; +} + static int get_firmware_search_dirs(char ***ret) { int r; @@ -206,12 +263,12 @@ static int load_firmware_data(const char *path, FirmwareData **ret) { return r; static const JsonDispatch table[] = { - { "description", JSON_VARIANT_STRING, NULL, 0, JSON_MANDATORY }, - { "interface-types", JSON_VARIANT_ARRAY, NULL, 0, JSON_MANDATORY }, - { "mapping", JSON_VARIANT_OBJECT, firmware_mapping, 0, JSON_MANDATORY }, - { "targets", JSON_VARIANT_ARRAY, NULL, 0, JSON_MANDATORY }, - { "features", JSON_VARIANT_ARRAY, json_dispatch_strv, offsetof(FirmwareData, features), JSON_MANDATORY }, - { "tags", JSON_VARIANT_ARRAY, NULL, 0, JSON_MANDATORY }, + { "description", JSON_VARIANT_STRING, NULL, 0, JSON_MANDATORY }, + { "interface-types", JSON_VARIANT_ARRAY, NULL, 0, JSON_MANDATORY }, + { "mapping", JSON_VARIANT_OBJECT, firmware_mapping, 0, JSON_MANDATORY }, + { "targets", JSON_VARIANT_ARRAY, target_architecture, offsetof(FirmwareData, architectures), JSON_MANDATORY }, + { "features", JSON_VARIANT_ARRAY, json_dispatch_strv, offsetof(FirmwareData, features), JSON_MANDATORY }, + { "tags", JSON_VARIANT_ARRAY, NULL, 0, JSON_MANDATORY }, {} }; @@ -266,10 +323,15 @@ int load_ovmf_config(const char *path, OvmfConfig **ret) { int find_ovmf_config(int search_sb, OvmfConfig **ret) { _cleanup_(ovmf_config_freep) OvmfConfig *config = NULL; _cleanup_strv_free_ char **conf_files = NULL; + const char* native_arch_qemu; int r; assert(ret); + r = native_arch_as_qemu(&native_arch_qemu); + if (r < 0) + return r; + /* Search in: * - $XDG_CONFIG_HOME/qemu/firmware * - /etc/qemu/firmware @@ -296,6 +358,11 @@ int find_ovmf_config(int search_sb, OvmfConfig **ret) { continue; } + if (!strv_contains(fwd->architectures, native_arch_qemu)) { + log_debug("Skipping %s, firmware doesn't support the native architecture.", *file); + continue; + } + /* exclude firmware which doesn't match our Secure Boot requirements */ if (search_sb >= 0 && !!search_sb != firmware_data_supports_sb(fwd)) { log_debug("Skipping %s, firmware doesn't fit required Secure Boot configuration.", *file); @@ -320,6 +387,7 @@ int find_ovmf_config(int search_sb, OvmfConfig **ret) { } int find_qemu_binary(char **ret_qemu_binary) { + const char *native_arch_qemu; int r; /* @@ -329,24 +397,6 @@ int find_qemu_binary(char **ret_qemu_binary) { * If the native architecture is not supported by qemu -EOPNOTSUPP will be returned; */ - static const char *architecture_to_qemu_table[_ARCHITECTURE_MAX] = { - [ARCHITECTURE_ARM64] = "aarch64", /* differs from our name */ - [ARCHITECTURE_ARM] = "arm", - [ARCHITECTURE_ALPHA] = "alpha", - [ARCHITECTURE_X86_64] = "x86_64", /* differs from our name */ - [ARCHITECTURE_X86] = "i386", /* differs from our name */ - [ARCHITECTURE_LOONGARCH64] = "loongarch64", - [ARCHITECTURE_MIPS64_LE] = "mips", /* differs from our name */ - [ARCHITECTURE_MIPS_LE] = "mips", /* differs from our name */ - [ARCHITECTURE_PARISC] = "hppa", /* differs from our name */ - [ARCHITECTURE_PPC64_LE] = "ppc", /* differs from our name */ - [ARCHITECTURE_PPC64] = "ppc", /* differs from our name */ - [ARCHITECTURE_PPC] = "ppc", - [ARCHITECTURE_RISCV32] = "riscv32", - [ARCHITECTURE_RISCV64] = "riscv64", - [ARCHITECTURE_S390X] = "s390x", - }; - FOREACH_STRING(s, "qemu", "qemu-kvm") { r = find_executable(s, ret_qemu_binary); if (r == 0) @@ -356,12 +406,12 @@ int find_qemu_binary(char **ret_qemu_binary) { return r; } - const char *arch_qemu = architecture_to_qemu_table[native_architecture()]; - if (!arch_qemu) - return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Architecture %s not supported by qemu", architecture_to_string(native_architecture())); + r = native_arch_as_qemu(&native_arch_qemu); + if (r < 0) + return r; _cleanup_free_ char *qemu_arch_specific = NULL; - qemu_arch_specific = strjoin("qemu-system-", arch_qemu); + qemu_arch_specific = strjoin("qemu-system-", native_arch_qemu); if (!qemu_arch_specific) return -ENOMEM;