DynamicTablesPkg/AmiLib: Fix stack corruption in AmlCodeGenRdInterrupt

In AmlCodeGenRdInterrupt(), the IRQ list was copied directly into an
EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR structure allocated on the stack.
Since the structure only contains storage for the first interrupt entry,
copying multiple IRQs would write beyond the allocated buffer and corrupt
the stack.

Fix this issue by allocating the descriptor dynamically with sufficient
space to accommodate the entire IRQ list. This ensures all interrupt entries
are copied safely without overwriting adjacent stack memory.

Signed-off-by: Tuan Phan <tuan.phan@oss.qualcomm.com>
This commit is contained in:
Tuan Phan 2026-07-23 21:49:37 -07:00 committed by mergify[bot]
parent 4d92f22a5c
commit 82dd8ab1b3

View file

@ -1266,7 +1266,8 @@ AmlCodeGenRdInterrupt (
EFI_STATUS Status;
AML_DATA_NODE *RdNode;
EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR RdInterrupt;
EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR *RdInterrupt;
UINT16 RdInterruptSize;
UINT32 *FirstInterrupt;
if ((IrqList == NULL) ||
@ -1277,32 +1278,40 @@ AmlCodeGenRdInterrupt (
return EFI_INVALID_PARAMETER;
}
// EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR already includes the first interrupt
RdInterruptSize = sizeof (EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR) + (IrqCount - 1) * sizeof (UINT32);
RdInterrupt = (EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR *)AllocateZeroPool (RdInterruptSize);
if (RdInterrupt == NULL) {
ASSERT_EFI_ERROR (EFI_OUT_OF_RESOURCES);
return EFI_OUT_OF_RESOURCES;
}
// Header
RdInterrupt.Header.Header.Bits.Name =
RdInterrupt->Header.Header.Bits.Name =
ACPI_LARGE_EXTENDED_IRQ_DESCRIPTOR_NAME;
RdInterrupt.Header.Header.Bits.Type = ACPI_LARGE_ITEM_FLAG;
RdInterrupt.Header.Length = sizeof (EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR) -
sizeof (ACPI_LARGE_RESOURCE_HEADER);
RdInterrupt->Header.Header.Bits.Type = ACPI_LARGE_ITEM_FLAG;
RdInterrupt->Header.Length = RdInterruptSize - sizeof (ACPI_LARGE_RESOURCE_HEADER);
// Body
RdInterrupt.InterruptVectorFlags = (ResourceConsumer ? BIT0 : 0) |
(EdgeTriggered ? BIT1 : 0) |
(ActiveLow ? BIT2 : 0) |
(Shared ? BIT3 : 0);
RdInterrupt.InterruptTableLength = IrqCount;
RdInterrupt->InterruptVectorFlags = (ResourceConsumer ? BIT0 : 0) |
(EdgeTriggered ? BIT1 : 0) |
(ActiveLow ? BIT2 : 0) |
(Shared ? BIT3 : 0);
RdInterrupt->InterruptTableLength = IrqCount;
// Get the address of the first interrupt field.
FirstInterrupt = RdInterrupt.InterruptNumber;
FirstInterrupt = RdInterrupt->InterruptNumber;
// Copy the list of interrupts.
CopyMem (FirstInterrupt, IrqList, (sizeof (UINT32) * IrqCount));
Status = AmlCreateDataNode (
EAmlNodeDataTypeResourceData,
(UINT8 *)&RdInterrupt,
sizeof (EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR),
(UINT8 *)RdInterrupt,
RdInterruptSize,
&RdNode
);
FreePool (RdInterrupt);
if (EFI_ERROR (Status)) {
ASSERT (0);
return Status;