From 82dd8ab1b374a907bff6a009d5f0efc510d53a98 Mon Sep 17 00:00:00 2001 From: Tuan Phan Date: Thu, 23 Jul 2026 21:49:37 -0700 Subject: [PATCH] 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 --- .../AmlLib/CodeGen/AmlResourceDataCodeGen.c | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.c b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.c index 4b5e100209..cc94521e86 100644 --- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.c +++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.c @@ -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;