From d6601a7e1c2452100ed7e4b1d74a70b9acc0abe6 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 26 May 2026 15:59:48 +0200 Subject: [PATCH 1/3] hw/uefi: fix parse_hexstr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure we actually have two input characters available before going to parse two hex digits. Fixes one byte buffer overflow of the output buffer in case the input string has an odd number of characters. Fixes: CVE-2026-48915 Fixes: 12058948abdf ("hw/uefi: add var-service-json.c + qapi for NV vars.") Reported-by: Feifan Qian Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Gerd Hoffmann Message-ID: <20260526135948.599148-1-kraxel@redhat.com> --- hw/uefi/var-service-json.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/uefi/var-service-json.c b/hw/uefi/var-service-json.c index f5f1556833..8621b86c5c 100644 --- a/hw/uefi/var-service-json.c +++ b/hw/uefi/var-service-json.c @@ -98,7 +98,7 @@ static void parse_hexstr(void *dest, char *src, int len) uint8_t *data = dest; size_t i; - for (i = 0; i < len; i += 2) { + for (i = 0; i + 1 < len; i += 2) { *(data++) = parse_hexchar(src[i]) << 4 | parse_hexchar(src[i + 1]); From f3285143059400f85d70c34b62460dac6c86c8de Mon Sep 17 00:00:00 2001 From: Luigi Leonardi Date: Tue, 9 Jun 2026 14:29:03 +0200 Subject: [PATCH 2/3] igvm: replace raw uint32_t with igvm library types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use IgvmVariableHeaderType and IgvmHeaderSection in QIGVMHandler and qigvm_handler() instead of plain uint32_t, so that each field's purpose is clear from its type. Reviewed-by: Stefano Garzarella Reviewed-by: Ani Sinha Signed-off-by: Luigi Leonardi Reviewed-by: Philippe Mathieu-Daudé Message-ID: <20260609-igvm_optional-v2-1-b1f1f08dc40e@redhat.com> Signed-off-by: Gerd Hoffmann --- backends/igvm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backends/igvm.c b/backends/igvm.c index 9b889f0428..3ccbafe9b9 100644 --- a/backends/igvm.c +++ b/backends/igvm.c @@ -102,8 +102,8 @@ static int qigvm_initialization_guest_policy(QIgvm *ctx, Error **errp); struct QIGVMHandler { - uint32_t type; - uint32_t section; + IgvmVariableHeaderType type; + IgvmHeaderSection section; int (*handler)(QIgvm *ctx, const uint8_t *header_data, Error **errp); }; @@ -132,7 +132,7 @@ static struct QIGVMHandler handlers[] = { qigvm_directive_madt }, }; -static int qigvm_handler(QIgvm *ctx, uint32_t type, Error **errp) +static int qigvm_handler(QIgvm *ctx, IgvmVariableHeaderType type, Error **errp) { size_t handler; IgvmHandle header_handle; From 3f24c8a74ce89686143be2517b4c1e98651bb913 Mon Sep 17 00:00:00 2001 From: Luigi Leonardi Date: Tue, 9 Jun 2026 14:29:04 +0200 Subject: [PATCH 3/3] igvm: fix handling of optional variable header types The IGVM spec defines bit 31 of the variable header type as an optional flag: if set, a loader that does not recognize the header type may safely skip it. If clear, the loader must reject the file. Currently, the optional bit is not stripped before comparing header types, so headers with the bit set fail to match any known type and are rejected. Mask bit 31 before comparing header types throughout the IGVM loader, and skip with a warning any unrecognized header that has the optional bit set. Fixes: c1d466d267cf ("backends/igvm: Add IGVM loader and configuration") Signed-off-by: Luigi Leonardi Message-ID: <20260609-igvm_optional-v2-2-b1f1f08dc40e@redhat.com> Signed-off-by: Gerd Hoffmann --- backends/igvm.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/backends/igvm.c b/backends/igvm.c index 3ccbafe9b9..3f4b97a5d4 100644 --- a/backends/igvm.c +++ b/backends/igvm.c @@ -26,6 +26,25 @@ #include #include +#ifndef IGVM_VHT_OPTIONAL_BIT +#define IGVM_VHT_OPTIONAL_BIT (1U << 31) +#endif + +/* + * Bit 31 of the variable header type indicates that the header is + * optional and can be safely ignored by a loader that does not + * support it. If the bit is clear, the file cannot be loaded. + * https://docs.rs/igvm_defs/0.4.0/igvm_defs/struct.IgvmVariableHeaderType.html + */ +static IgvmVariableHeaderType igvm_vht_type(IgvmVariableHeaderType type) +{ + return type & ~IGVM_VHT_OPTIONAL_BIT; +} + +static bool igvm_vht_optional(IgvmVariableHeaderType type) +{ + return !!(type & IGVM_VHT_OPTIONAL_BIT); +} /* * Some directives are specific to particular confidential computing platforms. @@ -132,12 +151,14 @@ static struct QIGVMHandler handlers[] = { qigvm_directive_madt }, }; -static int qigvm_handler(QIgvm *ctx, IgvmVariableHeaderType type, Error **errp) +static int qigvm_handler(QIgvm *ctx, IgvmVariableHeaderType raw_type, + Error **errp) { size_t handler; IgvmHandle header_handle; const uint8_t *header_data; int result; + IgvmVariableHeaderType type = igvm_vht_type(raw_type); for (handler = 0; handler < G_N_ELEMENTS(handlers); handler++) { if (handlers[handler].type != type) { @@ -166,6 +187,13 @@ static int qigvm_handler(QIgvm *ctx, IgvmVariableHeaderType type, Error **errp) igvm_free_buffer(ctx->file, header_handle); return result; } + + if (igvm_vht_optional(raw_type)) { + warn_report("IGVM: Skipping unsupported optional header type 0x%" + PRIX32, type); + return 0; + } + error_setg(errp, "IGVM: Unknown header type encountered when processing file: " "(type 0x%X)", @@ -787,6 +815,7 @@ static int qigvm_supported_platform_compat_mask(QIgvm *ctx, Error **errp) header_index++) { IgvmVariableHeaderType typ = igvm_get_header_type( ctx->file, IGVM_HEADER_SECTION_PLATFORM, header_index); + typ = igvm_vht_type(typ); if (typ == IGVM_VHT_SUPPORTED_PLATFORM) { header_handle = igvm_get_header( ctx->file, IGVM_HEADER_SECTION_PLATFORM, header_index); @@ -945,10 +974,10 @@ int qigvm_process_file(IgvmCfg *cfg, MachineState *machine_state, for (ctx.current_header_index = 0; ctx.current_header_index < (unsigned)header_count; ctx.current_header_index++) { - IgvmVariableHeaderType type = igvm_get_header_type( + IgvmVariableHeaderType raw_type = igvm_get_header_type( ctx.file, IGVM_HEADER_SECTION_DIRECTIVE, ctx.current_header_index); - if (!onlyVpContext || (type == IGVM_VHT_VP_CONTEXT)) { - if (qigvm_handler(&ctx, type, errp) < 0) { + if (!onlyVpContext || igvm_vht_type(raw_type) == IGVM_VHT_VP_CONTEXT) { + if (qigvm_handler(&ctx, raw_type, errp) < 0) { goto cleanup_parameters; } }