Skip to content
GoogleGHSA-jxxm-gxxf-64mg

TrustZone Break-in Vulnerabilities in Ampere UEFI MM Drivers (Arbitrary Out-of-Bounds Write)

Medium4.6CVE-2025-62863 · Published Jan 6, 2026

#### Summary Multiple arbitrary Out-of-Bounds (OOB) `'\0'` byte write vulnerabilities affecting the ARM Ampere Management Mode (MM) PCIe driver were discovered. This code is bundled into the ARM Unified Extensible Firmware Interface (UEFI) firmware and runs in the Secure world at Exception Level 0 (S-EL0). The PCIe driver is used to initialize the root complex, underlying controllers, logging facilities, and perform self tests during UEFI Driver Execution Environment (DXE) phase. After initialization a lock is used to limit the available interfaces to a few functions, which are accessible from Non-Secure EL1 (NS-EL1) using the Secure Monitor Call (SMC) instruction with a predefined shared buffer for message passing. It was found that the post initialization lock was never set leaving per-initialization interfaces available and multiple handlers use a `UIN64 size` from an NS-EL1 supplied buffer without proper bounds checking to index an array and writing a `'\0'` byte. Ampere has addressed the vulnerability and posted a [security bulletin](https://amperecomputing.com/products/security-bulletins/amp-sb-0007). #### Analysis NS-EL1 software interacts with the MM PCIe driver using th...

GitHub advisory

Affected versions

PackageAffectedFixed in
AmpereOne AC03
Product
< 3.5.9.33.5.9.3
AmpereOne AC04
Product
< 4.4.5.24.4.5.2
AmpereOne M
Product
< 5.4.5.15.4.5.1
Details and references

#### Summary Multiple arbitrary Out-of-Bounds (OOB) `'\0'` byte write vulnerabilities affecting the ARM Ampere Management Mode (MM) PCIe driver were discovered. This code is bundled into the ARM Unified Extensible Firmware Interface (UEFI) firmware and runs in the Secure world at Exception Level 0 (S-EL0). The PCIe driver is used to initialize the root complex, underlying controllers, logging facilities, and perform self tests during UEFI Driver Execution Environment (DXE) phase. After initialization a lock is used to limit the available interfaces to a few functions, which are accessible from Non-Secure EL1 (NS-EL1) using the Secure Monitor Call (SMC) instruction with a predefined shared buffer for message passing. It was found that the post initialization lock was never set leaving per-initialization interfaces available and multiple handlers use a `UIN64 size` from an NS-EL1 supplied buffer without proper bounds checking to index an array and writing a `'\0'` byte. Ampere has addressed the vulnerability and posted a [security bulletin](https://amperecomputing.com/products/security-bulletins/amp-sb-0007). #### Analysis NS-EL1 software interacts with the MM PCIe driver using the Firmware Framework for A-Profile (FFA) specification through the SMC instruction. The SMC instruction is used to switch to and from the Non-Secure and Secure worlds and FFA is used for dispatching to specific drivers and services. A shared buffer (initialized during the UEFI DXE phase as `mNsCommBufferMemRegion` in [ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.c](https://github.com/tianocore/edk2/blob/master/ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.c)) is used to communicate messages between NS-EL1 and the S-EL0 PCIe driver. The handler for the PCIe MM driver can be reached using the following GUID using the FFA specification. `PCIeMmHeader` and `PCIeMmBuffer` show the general layout of the communication buffer. Before the `PCIeMmHandler` dispatch routine is called the MM subsystem copies the shared message buffer to a private memory region to prevent Time-of-Check to Time-of-Use (TOCTOU) issues. As drivers uniquely define the underlying structures in the communicated messages each must perform validation before using the supplied data. *The code snippets included were created through analysis with Ghidra using names contained in string references from the UEFI image. Known functions and variables from the EDK2 repository were also applied.* ``` #define PCIE_MM_GUID \ {0xe49f1b7a, 0xd3c9, 0x44f4, { 0x9b, 0xc4, 0xd3, 0xb2, 0x9a, 0xcb, 0xb3, 0x20 }}; #define MAX_PCIE_MM_MAX_SIZE 0x10000 typedef struct { UINT64 FuncId; UINT8 data[1]; } PcieMmHeader; // ... typedef struct { UINT64 unknown_0; UINT64 size; UINT64 unknown_1; UINT8 data[1]; } PcieMmBuffer; ``` The `PCIeMmBuffer` structure includes a `FuncId` field for dispatching to specific sub-handlers and both `103` and `104` , shown in the code snippet below as `case 2` and `case 3`, include a `UINT64 size` to represent the size of a NS-EL1 supplied buffer. ``` EFI_STATUS PcieMmHandler(int DispatchHandle,void *RegisterContext,void *CommBuffer, uint64_t *CommBufferSize) { // ... PcieMmHeader *header; PcieMmBuffer *buffer; ASSERT(CommBuffer); ASSERT(CommBufferSize); if ((DebugLevel() & 0xff) != 0) { Debug(0x40,"%a \n","PcieMmHandler"); Debug(0x400000, "PcieMm Handler: CommBuffer - 0x%p, CommBufferSize - 0x%x\n", CommBuffer, *CommBufferSize); Debug(0x400000, "PcieMm Handler: FuncId - %d\n", CommBuffer->FuncId); } header = (PCIeMmHeader *)CommBuffer; FuncId = header->FuncId; buffer = header->data; if (pcie_mm_lock == '\0') { if (106 < function) { //... goto switchD_000077a8_caseD_4; } if (FuncId < 100) goto LAB_00007760; if (FuncId - 101 < 6) { switch(FuncId - 101 & 0xffffffff) { // ... case 1: // initialization lock

CVSS 3.1
CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:C/C:N/I:L/A:L
Severity from
GitHub (reviewed advisory)
Weakness
CWE-787

More Google advisories

All Google

Critical advisories by email

Wednesdays: the week’s critical and high advisories in the AI and data stack, with the fixed versions. Only in weeks that have some.

Double opt-in. Unsubscribe any time.