On Fri, Sep 04, 2026 at 01:42:56PM +0200, Luigi Leonardi wrote:
qigvm_directive_memory_map(), qigvm_directive_madt() and
qigvm_directive_device_tree() all wrote their data unconditionally at
the start of the parameter area's buffer, ignoring param->byte_offset
from the IGVM_VHS_PARAMETER header. This is harmless when a
directive's offset happens to be 0, but breaks for IGVM files that pack
multiple parameters into a single shared parameter area at different
offsets: a later directive would overwrite the data written by an earlier
one at the start of the buffer, corrupting it.

Switch these handlers to qigvm_find_param_validate(), introduced in
the previous patch, and use the offset-adjusted data pointer and
remaining size it returns instead of writing at param_entry->data and
sizing checks against param_entry->size directly. This both honors
byte_offset and validates it against the parameter area size before
it is used.

Do we need a Fixes tag?

The rest LGTM,
Stefano


Signed-off-by: Luigi Leonardi <[email protected]>
---
backends/igvm.c    | 24 ++++++++++++------------
target/i386/igvm.c | 12 ++++++------
2 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/backends/igvm.c b/backends/igvm.c
index 8c07f2ce5e..4d622eac6a 100644
--- a/backends/igvm.c
+++ b/backends/igvm.c
@@ -638,7 +638,8 @@ static int qigvm_directive_memory_map(QIgvm *ctx, const 
uint8_t *header_data,
    const IGVM_VHS_PARAMETER *param = (const IGVM_VHS_PARAMETER *)header_data;
    int (*get_mem_map_entry)(int index, ConfidentialGuestMemoryMapEntry *entry,
                             Error **errp) = NULL;
-    QIgvmParameterData *param_entry;
+    uint8_t *data;
+    uint32_t size;
    int max_entry_count;
    int entry = 0;
    IGVM_VHS_MEMORY_MAP_ENTRY *mm_entry;
@@ -659,14 +660,13 @@ static int qigvm_directive_memory_map(QIgvm *ctx, const 
uint8_t *header_data,
    }

    /* Find the parameter area that should hold the memory map */
-    param_entry = qigvm_find_param_entry(ctx,
-                                         param->parameter_area_index, errp);
-    if (param_entry == NULL) {
+    if (!qigvm_find_param_validate(ctx, param->parameter_area_index, param,
+                                   &data, &size, errp)) {
        return -1;
    }

-    max_entry_count = param_entry->size / sizeof(IGVM_VHS_MEMORY_MAP_ENTRY);
-    mm_entry = (IGVM_VHS_MEMORY_MAP_ENTRY *)param_entry->data;
+    max_entry_count = size / sizeof(IGVM_VHS_MEMORY_MAP_ENTRY);
+    mm_entry = (IGVM_VHS_MEMORY_MAP_ENTRY *)data;

    retval = get_mem_map_entry(entry, &cgmm_entry, errp);
    while (retval == 0) {
@@ -860,12 +860,12 @@ static int qigvm_directive_device_tree(QIgvm *ctx, const 
uint8_t *header_data,
{
    const IGVM_VHS_PARAMETER *param = (const IGVM_VHS_PARAMETER *)header_data;
    g_autofree void *fdt_packed = NULL;
-    QIgvmParameterData *param_entry;
+    uint8_t *data;
+    uint32_t size;
    uint32_t fdt_size;

-    param_entry = qigvm_find_param_entry(ctx,
-                                         param->parameter_area_index, errp);
-    if (param_entry == NULL) {
+    if (!qigvm_find_param_validate(ctx, param->parameter_area_index, param,
+                                   &data, &size, errp)) {
        return -1;
    }

@@ -883,14 +883,14 @@ static int qigvm_directive_device_tree(QIgvm *ctx, const 
uint8_t *header_data,
    }

    fdt_size = fdt_totalsize(fdt_packed);
-    if (fdt_size > param_entry->size) {
+    if (fdt_size > size) {
        error_setg(errp,
                   "IGVM: device tree size exceeds parameter area"
                   " defined in IGVM file");
        return -1;
    }

-    memcpy(param_entry->data, fdt_packed, fdt_size);
+    memcpy(data, fdt_packed, fdt_size);

    return 0;
}
diff --git a/target/i386/igvm.c b/target/i386/igvm.c
index ad9bf87761..db365cb80e 100644
--- a/target/i386/igvm.c
+++ b/target/i386/igvm.c
@@ -187,20 +187,20 @@ void qigvm_x86_bsp_reset(CPUX86State *env)
int qigvm_directive_madt(QIgvm *ctx, const uint8_t *header_data, Error **errp)
{
    const IGVM_VHS_PARAMETER *param = (const IGVM_VHS_PARAMETER *)header_data;
-    QIgvmParameterData *param_entry;
+    uint8_t *data;
+    uint32_t size;
    int result = 0;

    /* Find the parameter area that should hold the MADT data */
-    param_entry = qigvm_find_param_entry(ctx,
-                                         param->parameter_area_index, errp);
-    if (param_entry == NULL) {
+    if (!qigvm_find_param_validate(ctx, param->parameter_area_index, param,
+                                   &data, &size, errp)) {
        return -1;
    }

    GArray *madt = acpi_build_madt_standalone(ctx->machine_state);

-    if (madt->len <= param_entry->size) {
-        memcpy(param_entry->data, madt->data, madt->len);
+    if (madt->len <= size) {
+        memcpy(data, madt->data, madt->len);
    } else {
        error_setg(
            errp,

--
2.55.0



Reply via email to