backends/igvm.c | 89 +++++++++++++++++++++++++++++++----------- include/system/igvm-internal.h | 5 +++ target/i386/igvm.c | 12 +++--- 3 files changed, 77 insertions(+), 29 deletions(-)
None of the directive handlers that place data within a parameter area
validated that param->byte_offset actually falls within the parameter
area's size. A malformed IGVM file with byte_offset > size would
underflow the "size - byte_offset" computation used to determine
remaining space, wrapping to a huge value and defeating the size
check, then write out of bounds through param_entry->data +
byte_offset.
Separately, qigvm_directive_memory_map(), qigvm_directive_madt() and
qigvm_directive_device_tree() ignored param->byte_offset entirely and
always wrote at the start of the parameter area's buffer. 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, corrupting it.
Add qigvm_get_param_data(), which looks up the parameter area, checks
byte_offset against its size, and returns the offset-adjusted data
pointer directly (NULL on failure), with the remaining space returned
via an output parameter, instead of the raw QIgvmParameterData entry.
This keeps the byte_offset arithmetic and bounds check in one place
instead of repeating it at every call site.
Switch every directive handler that reads or writes parameter data
to use it, adding explicit checks that each fixed-size read/write fits in
the remaining space.
Fixes: c1d466d267 ("backends/igvm: Add IGVM loader and configuration")
Fixes: dea1f68a5c ("igvm: Fill MADT IGVM parameter field on x86_64")
Fixes: 1c4bd8f13c ("igvm: add device tree parameter support")
Signed-off-by: Luigi Leonardi <leonardi@redhat.com>
---
Several IGVM directives (memory map, vp-count, environment info, MADT,
device tree) _can_ place their data at a byte_offset within a shared
parameter area, letting multiple parameters be packed into one area.
Introduce qigvm_get_param_data(), which looks up a
parameter area and validates that byte_offset falls within it in one
step, and uses it in the vp-count and environment-info handlers, which
already relied on byte_offset.
Also fixes the memory map, MADT and device tree handlers, which
ignored byte_offset entirely and always wrote at the start of the
buffer, potentially corrupting earlier data when several parameters
share an area.
---
Changes in v4:
- Squashed two commits in one.
- Removed one parameter from `qigvm_get_param_data` [Stefano]
- Removed some useless variables [Stefano]
- Rebased to latest upstream
- Link to v3: https://lore.kernel.org/qemu-devel/20260907-fix_offset-v3-0-bcffcefc0985@redhat.com
Changes in v3:
- Renamed the function to `qigvm_get_param_data`. [Stefano]
- `qigvm_get_param_data` now returns the data pointer directly [Stefano]
- Added fixes tags. [Stefano]
- Renamed variables to param_data and param_size [Stefano]
- Link to v2: https://lore.kernel.org/qemu-devel/20260904-fix_offset-v2-0-f5bb4cf6d4b0@redhat.com
Changes in v2:
- Inverted commit order: first I introduce the helper and use it where
necessary, then in commit 2 I handle the `offset`. [Stefano]
- The helper now returns data and size, that already consider the byte
offset [Stefano]
- Link to v1: https://lore.kernel.org/qemu-devel/20260902-fix_offset-v1-0-04b18f7595b2@redhat.com
---
backends/igvm.c | 89 +++++++++++++++++++++++++++++++-----------
include/system/igvm-internal.h | 5 +++
target/i386/igvm.c | 12 +++---
3 files changed, 77 insertions(+), 29 deletions(-)
diff --git a/backends/igvm.c b/backends/igvm.c
index 7b7bdc72b7..9a2bafc0ca 100644
--- a/backends/igvm.c
+++ b/backends/igvm.c
@@ -101,6 +101,38 @@ qigvm_find_param_entry(QIgvm *igvm, uint32_t parameter_area_index,
return NULL;
}
+/*
+ * Get parameter area data at byte_offset with bounds validation.
+ * On success, returns offset-adjusted data pointer and sets param_size
+ * to remaining space.
+ * Returns NULL on failure.
+ */
+uint8_t *
+qigvm_get_param_data(QIgvm *igvm, const IGVM_VHS_PARAMETER *param,
+ uint32_t *param_size,
+ Error **errp)
+{
+ QIgvmParameterData *param_entry;
+
+ assert(param_size);
+
+ param_entry = qigvm_find_param_entry(igvm, param->parameter_area_index,
+ errp);
+ if (!param_entry) {
+ return NULL;
+ }
+
+ if (param->byte_offset > param_entry->size) {
+ error_setg(errp,
+ "IGVM: byte_offset 0x%x exceeds parameter area size 0x%x",
+ param->byte_offset, param_entry->size);
+ return NULL;
+ }
+
+ *param_size = param_entry->size - param->byte_offset;
+ return param_entry->data + param->byte_offset;
+}
+
static int qigvm_directive_page_data(QIgvm *ctx, const uint8_t *header_data,
Error **errp);
static int qigvm_directive_vp_context(QIgvm *ctx, const uint8_t *header_data,
@@ -605,7 +637,7 @@ 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;
+ uint32_t param_size;
int max_entry_count;
int entry = 0;
IGVM_VHS_MEMORY_MAP_ENTRY *mm_entry;
@@ -626,14 +658,14 @@ 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) {
+ mm_entry =
+ (IGVM_VHS_MEMORY_MAP_ENTRY *)qigvm_get_param_data(ctx, param,
+ ¶m_size, errp);
+ if (!mm_entry) {
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 = param_size / sizeof(IGVM_VHS_MEMORY_MAP_ENTRY);
retval = get_mem_map_entry(entry, &cgmm_entry, errp);
while (retval == 0) {
@@ -682,17 +714,22 @@ static int qigvm_directive_vp_count(QIgvm *ctx, const uint8_t *header_data,
Error **errp)
{
const IGVM_VHS_PARAMETER *param = (const IGVM_VHS_PARAMETER *)header_data;
- QIgvmParameterData *param_entry;
+ uint32_t param_size;
uint32_t *vp_count;
CPUState *cpu;
- param_entry = qigvm_find_param_entry(ctx,
- param->parameter_area_index, errp);
- if (param_entry == NULL) {
+ vp_count = (uint32_t *)qigvm_get_param_data(ctx, param, ¶m_size, errp);
+ if (!vp_count) {
+ return -1;
+ }
+
+ if (sizeof(*vp_count) > param_size) {
+ error_setg(errp,
+ "IGVM: vp-count parameter exceeds parameter area "
+ "defined in IGVM file");
return -1;
}
- vp_count = (uint32_t *)(param_entry->data + param->byte_offset);
*vp_count = 0;
CPU_FOREACH(cpu)
{
@@ -707,17 +744,23 @@ static int qigvm_directive_environment_info(QIgvm *ctx,
Error **errp)
{
const IGVM_VHS_PARAMETER *param = (const IGVM_VHS_PARAMETER *)header_data;
- QIgvmParameterData *param_entry;
+ uint32_t param_size;
IgvmEnvironmentInfo *environmental_state;
- param_entry = qigvm_find_param_entry(ctx,
- param->parameter_area_index, errp);
- if (param_entry == NULL) {
+ environmental_state =
+ (IgvmEnvironmentInfo *)qigvm_get_param_data(ctx, param, ¶m_size,
+ errp);
+ if (!environmental_state) {
+ return -1;
+ }
+
+ if (sizeof(*environmental_state) > param_size) {
+ error_setg(errp,
+ "IGVM: environment-info parameter exceeds parameter area "
+ "defined in IGVM file");
return -1;
}
- environmental_state =
- (IgvmEnvironmentInfo *)(param_entry->data + param->byte_offset);
environmental_state->memory_is_shared = 1;
return 0;
@@ -814,12 +857,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 *param_data;
+ uint32_t param_size;
uint32_t fdt_size;
- param_entry = qigvm_find_param_entry(ctx,
- param->parameter_area_index, errp);
- if (param_entry == NULL) {
+ param_data = qigvm_get_param_data(ctx, param, ¶m_size, errp);
+ if (!param_data) {
return -1;
}
@@ -837,14 +880,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 > param_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(param_data, fdt_packed, fdt_size);
return 0;
}
diff --git a/include/system/igvm-internal.h b/include/system/igvm-internal.h
index 9e9fa1d9af..0467eff0ce 100644
--- a/include/system/igvm-internal.h
+++ b/include/system/igvm-internal.h
@@ -81,4 +81,9 @@ QIgvmParameterData*
qigvm_find_param_entry(QIgvm *igvm, uint32_t parameter_area_index,
Error **errp);
+uint8_t *
+qigvm_get_param_data(QIgvm *igvm, const IGVM_VHS_PARAMETER *param,
+ uint32_t *param_size,
+ Error **errp);
+
#endif
diff --git a/target/i386/igvm.c b/target/i386/igvm.c
index ad9bf87761..9c2f8d5164 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 *param_data;
+ uint32_t param_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) {
+ param_data = qigvm_get_param_data(ctx, param, ¶m_size, errp);
+ if (!param_data) {
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 <= param_size) {
+ memcpy(param_data, madt->data, madt->len);
} else {
error_setg(
errp,
---
base-commit: 5f664cd37aec17e8145aa117d8da68f507edc8f1
change-id: 20260902-fix_offset-a268cb12aafc
Best regards,
--
Luigi Leonardi <leonardi@redhat.com>
On Mon, Sep 14, 2026 at 01:02:43PM +0200, Luigi Leonardi wrote:
>None of the directive handlers that place data within a parameter area
>validated that param->byte_offset actually falls within the parameter
>area's size. A malformed IGVM file with byte_offset > size would
>underflow the "size - byte_offset" computation used to determine
I'm a bit confused about this commit description. Before this patch,
where we did "size - byte_offset" computation ?
>remaining space, wrapping to a huge value and defeating the size
IIUC the size check was completely missing, no?
>check, then write out of bounds through param_entry->data +
>byte_offset.
>
>Separately, qigvm_directive_memory_map(), qigvm_directive_madt() and
>qigvm_directive_device_tree() ignored param->byte_offset entirely and
>always wrote at the start of the parameter area's buffer. 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, corrupting it.
>
>Add qigvm_get_param_data(), which looks up the parameter area, checks
>byte_offset against its size, and returns the offset-adjusted data
>pointer directly (NULL on failure), with the remaining space returned
>via an output parameter, instead of the raw QIgvmParameterData entry.
>This keeps the byte_offset arithmetic and bounds check in one place
>instead of repeating it at every call site.
>
>Switch every directive handler that reads or writes parameter data
>to use it, adding explicit checks that each fixed-size read/write fits in
>the remaining space.
IMO this descriptipn is unnecessarily lengthy, so here's a concise
version (IIUC the issue and what this patch does):
igvm: validate and honor byte_offset in parameter directives
Parameter directive handlers either ignore param->byte_offset,
overwriting each other when several parameters share one area, or use
it without validating it, letting a malformed IGVM file corrupt QEMU's
memory.
Add qigvm_get_param_data(), which validates byte_offset against the
parameter area size and returns the offset-adjusted pointer together
with the space left after it. Convert all parameter directive handlers
to use it and to check their writes against that remaining space, so
that no parameter can be written past the end of its area.
This is just an idea, and I'm not sure I've fully understood it. Feel
free to expand on it, change it, etc.
>
>Fixes: c1d466d267 ("backends/igvm: Add IGVM loader and configuration")
>Fixes: dea1f68a5c ("igvm: Fill MADT IGVM parameter field on x86_64")
>Fixes: 1c4bd8f13c ("igvm: add device tree parameter support")
>Signed-off-by: Luigi Leonardi <leonardi@redhat.com>
>---
>Several IGVM directives (memory map, vp-count, environment info, MADT,
>device tree) _can_ place their data at a byte_offset within a shared
>parameter area, letting multiple parameters be packed into one area.
This maybe can be introduced in the commit description.
>
>Introduce qigvm_get_param_data(), which looks up a
>parameter area and validates that byte_offset falls within it in one
>step, and uses it in the vp-count and environment-info handlers, which
>already relied on byte_offset.
>
>Also fixes the memory map, MADT and device tree handlers, which
>ignored byte_offset entirely and always wrote at the start of the
>buffer, potentially corrupting earlier data when several parameters
>share an area.
>---
>Changes in v4:
>- Squashed two commits in one.
>- Removed one parameter from `qigvm_get_param_data` [Stefano]
>- Removed some useless variables [Stefano]
>- Rebased to latest upstream
>- Link to v3: https://lore.kernel.org/qemu-devel/20260907-fix_offset-v3-0-bcffcefc0985@redhat.com
>
>Changes in v3:
>- Renamed the function to `qigvm_get_param_data`. [Stefano]
>- `qigvm_get_param_data` now returns the data pointer directly [Stefano]
>- Added fixes tags. [Stefano]
>- Renamed variables to param_data and param_size [Stefano]
>- Link to v2: https://lore.kernel.org/qemu-devel/20260904-fix_offset-v2-0-f5bb4cf6d4b0@redhat.com
>
>Changes in v2:
>- Inverted commit order: first I introduce the helper and use it where
> necessary, then in commit 2 I handle the `offset`. [Stefano]
>- The helper now returns data and size, that already consider the byte
> offset [Stefano]
>- Link to v1: https://lore.kernel.org/qemu-devel/20260902-fix_offset-v1-0-04b18f7595b2@redhat.com
>---
> backends/igvm.c | 89 +++++++++++++++++++++++++++++++-----------
> include/system/igvm-internal.h | 5 +++
> target/i386/igvm.c | 12 +++---
> 3 files changed, 77 insertions(+), 29 deletions(-)
>
>diff --git a/backends/igvm.c b/backends/igvm.c
>index 7b7bdc72b7..9a2bafc0ca 100644
>--- a/backends/igvm.c
>+++ b/backends/igvm.c
>@@ -101,6 +101,38 @@ qigvm_find_param_entry(QIgvm *igvm, uint32_t parameter_area_index,
> return NULL;
> }
>
>+/*
>+ * Get parameter area data at byte_offset with bounds validation.
>+ * On success, returns offset-adjusted data pointer and sets param_size
>+ * to remaining space.
>+ * Returns NULL on failure.
>+ */
>+uint8_t *
>+qigvm_get_param_data(QIgvm *igvm, const IGVM_VHS_PARAMETER *param,
>+ uint32_t *param_size,
>+ Error **errp)
>+{
>+ QIgvmParameterData *param_entry;
>+
>+ assert(param_size);
>+
>+ param_entry = qigvm_find_param_entry(igvm, param->parameter_area_index,
>+ errp);
>+ if (!param_entry) {
>+ return NULL;
>+ }
>+
>+ if (param->byte_offset > param_entry->size) {
>+ error_setg(errp,
>+ "IGVM: byte_offset 0x%x exceeds parameter area size 0x%x",
>+ param->byte_offset, param_entry->size);
>+ return NULL;
>+ }
>+
>+ *param_size = param_entry->size - param->byte_offset;
>+ return param_entry->data + param->byte_offset;
>+}
>+
> static int qigvm_directive_page_data(QIgvm *ctx, const uint8_t *header_data,
> Error **errp);
> static int qigvm_directive_vp_context(QIgvm *ctx, const uint8_t *header_data,
>@@ -605,7 +637,7 @@ 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;
>+ uint32_t param_size;
> int max_entry_count;
> int entry = 0;
> IGVM_VHS_MEMORY_MAP_ENTRY *mm_entry;
>@@ -626,14 +658,14 @@ 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) {
>+ mm_entry =
>+ (IGVM_VHS_MEMORY_MAP_ENTRY *)qigvm_get_param_data(ctx, param,
>+ ¶m_size, errp);
>+ if (!mm_entry) {
> 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 = param_size / sizeof(IGVM_VHS_MEMORY_MAP_ENTRY);
>
> retval = get_mem_map_entry(entry, &cgmm_entry, errp);
> while (retval == 0) {
>@@ -682,17 +714,22 @@ static int qigvm_directive_vp_count(QIgvm *ctx, const uint8_t *header_data,
> Error **errp)
> {
> const IGVM_VHS_PARAMETER *param = (const IGVM_VHS_PARAMETER *)header_data;
>- QIgvmParameterData *param_entry;
>+ uint32_t param_size;
> uint32_t *vp_count;
> CPUState *cpu;
>
>- param_entry = qigvm_find_param_entry(ctx,
>- param->parameter_area_index, errp);
>- if (param_entry == NULL) {
>+ vp_count = (uint32_t *)qigvm_get_param_data(ctx, param, ¶m_size, errp);
>+ if (!vp_count) {
>+ return -1;
>+ }
>+
>+ if (sizeof(*vp_count) > param_size) {
>+ error_setg(errp,
>+ "IGVM: vp-count parameter exceeds parameter area "
>+ "defined in IGVM file");
> return -1;
> }
>
>- vp_count = (uint32_t *)(param_entry->data + param->byte_offset);
> *vp_count = 0;
> CPU_FOREACH(cpu)
> {
>@@ -707,17 +744,23 @@ static int qigvm_directive_environment_info(QIgvm *ctx,
> Error **errp)
> {
> const IGVM_VHS_PARAMETER *param = (const IGVM_VHS_PARAMETER *)header_data;
>- QIgvmParameterData *param_entry;
>+ uint32_t param_size;
> IgvmEnvironmentInfo *environmental_state;
>
>- param_entry = qigvm_find_param_entry(ctx,
>- param->parameter_area_index, errp);
>- if (param_entry == NULL) {
>+ environmental_state =
>+ (IgvmEnvironmentInfo *)qigvm_get_param_data(ctx, param, ¶m_size,
>+ errp);
>+ if (!environmental_state) {
>+ return -1;
>+ }
>+
>+ if (sizeof(*environmental_state) > param_size) {
>+ error_setg(errp,
>+ "IGVM: environment-info parameter exceeds parameter area "
>+ "defined in IGVM file");
> return -1;
> }
>
>- environmental_state =
>- (IgvmEnvironmentInfo *)(param_entry->data + param->byte_offset);
> environmental_state->memory_is_shared = 1;
>
> return 0;
>@@ -814,12 +857,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 *param_data;
>+ uint32_t param_size;
> uint32_t fdt_size;
>
>- param_entry = qigvm_find_param_entry(ctx,
>- param->parameter_area_index, errp);
>- if (param_entry == NULL) {
>+ param_data = qigvm_get_param_data(ctx, param, ¶m_size, errp);
>+ if (!param_data) {
> return -1;
> }
>
>@@ -837,14 +880,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 > param_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(param_data, fdt_packed, fdt_size);
>
> return 0;
> }
>diff --git a/include/system/igvm-internal.h b/include/system/igvm-internal.h
>index 9e9fa1d9af..0467eff0ce 100644
>--- a/include/system/igvm-internal.h
>+++ b/include/system/igvm-internal.h
>@@ -81,4 +81,9 @@ QIgvmParameterData*
> qigvm_find_param_entry(QIgvm *igvm, uint32_t parameter_area_index,
> Error **errp);
qigvm_find_param_entry() is now used only in backends/igvm.c, so I think
we can make it static and remove from here, up to you if you prefer here
or in a cleanup patch.
The rest LGTM.
Stefano
>
>+uint8_t *
>+qigvm_get_param_data(QIgvm *igvm, const IGVM_VHS_PARAMETER *param,
>+ uint32_t *param_size,
>+ Error **errp);
>+
> #endif
>diff --git a/target/i386/igvm.c b/target/i386/igvm.c
>index ad9bf87761..9c2f8d5164 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 *param_data;
>+ uint32_t param_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) {
>+ param_data = qigvm_get_param_data(ctx, param, ¶m_size, errp);
>+ if (!param_data) {
> 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 <= param_size) {
>+ memcpy(param_data, madt->data, madt->len);
> } else {
> error_setg(
> errp,
>
>---
>base-commit: 5f664cd37aec17e8145aa117d8da68f507edc8f1
>change-id: 20260902-fix_offset-a268cb12aafc
>
>Best regards,
>--
>Luigi Leonardi <leonardi@redhat.com>
>
© 2016 - 2026 Red Hat, Inc.