← ALL ADVISORIES

MEDIUM BYTERAY-2026-0252Disclosed

EDK II - NULL Pointer Dereference in QemuKernelFetchNamedBlobs

The function reads a host-controlled file-directory count from QEMU fw_cfg via QemuFwCfgRead32() and uses it to size an AllocatePool call without checking the return value for NULL.

Advisory
BYTERAY-2026-0252
CWE
CWE-690
Vendor
TianoCore
Product
EDK II
Reported
2026-06-25
Disclosure
2026-10-29
Affected
EDK II at commit 70741a15d9a714323a5598eac47727e60507e22f (master, 2026-06-21); affected code in OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c.
Credit
Argus-Systems

Executive Summary

The function reads a host-controlled file-directory count from QEMU fw_cfg via QemuFwCfgRead32() and uses it to size an AllocatePool call without checking the return value for NULL. The immediately following line passes the result to QemuFwCfgReadBytes, which, with fw_cfg present, calls InternalQemuFwCfgReadBytes. That function writes host data to the buffer through fw_cfg DMA when the size fits in 32 bits (QemuFwCfgLib.c:67-68) or through IoReadFifo8 otherwise (QemuFwCfgLib.c:72). A hostile hypervisor supplying a large fw_cfg QemuFwCfgItemFileDir count causes AllocatePool to fail and return NULL, and the read then targets address 0. On SEV/TDX guests the DMA path maps the buffer through the IOMMU protocol, and a failed Map() ends in CpuDeadLoop (QemuFwCfgDxe.c:321-331). For Count >= 2^26 the size (64 bytes per entry) exceeds MAX_UINT32, so IoReadFifo8 copies host-supplied bytes linearly into guest memory starting at address 0, which is mapped by default (PcdNullPointerDetectionPropertyMask = 0). This is an isolated miss: every sibling fw_cfg consumer in OvmfPkg correctly checks for NULL. The module is built in OvmfPkgX64, AmdSevX64, and IntelTdxX64 — the confidential-computing platforms where the hypervisor is the adversary (Model B).

This advisory is one of a set reported to VulnCheck on 2026-06-25 for coordinated disclosure to the EDK II maintainers. After several follow-ups over the following months no response was received. 126 days after the initial report, ByteRay is publishing the findings in good faith so that affected integrators can assess and remediate them. All findings were identified against EDK II commit 70741a15d9a714323a5598eac47727e60507e22f (master, 2026-06-21).

Affected Products and Versions

  • Vendor: TianoCore
  • Product: EDK II (OvmfPkg)
  • Affected commit: 70741a15d9a714323a5598eac47727e60507e22f (master, 2026-06-21). The code is present on that commit and later revisions that have not changed it.
  • Location: OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c:1123
  • Function: QemuKernelFetchNamedBlobs
  • Category: error_handling

Technical Details

Controllability: SEMI_TRUSTED — confidence: high. On OvmfPkgX64/AmdSevX64/IntelTdxX64 confidential-computing builds, the hypervisor is the threat model (Model B). The fw_cfg file directory count is fully controlled by the hypervisor.

Data Flow

The hypervisor fw_cfg interface (QemuFwCfgItemFileDir) is selected at line 1120. A host-controlled count is read at line 1121 via Count = SwapBytes32(QemuFwCfgRead32()). This count sizes the allocation at line 1123: DirEntry = AllocatePool(sizeof(*DirEntry) * Count) with no NULL check. The NULL DirEntry is passed to QemuFwCfgReadBytes at line 1124, which writes host data through the pointer in InternalQemuFwCfgReadBytes (fw_cfg DMA at QemuFwCfgLib.c:68, or IoReadFifo8 at QemuFwCfgLib.c:72 when the size exceeds MAX_UINT32). Every sibling fw_cfg consumer (e.g., PciHostBridgeUtilityLib.c:531, QemuFwCfgAcpi.c:1137) correctly checks for NULL, confirming this is an isolated miss.

Affected Callers

  • QemuKernelLoaderFsDxeEntrypoint

Sanitization / Security Controls

  • None. No bounds check on Count; sibling consumers check NULL but this site does not.

Reachability and Preconditions

Attacker position and trust level for this issue are stated in the Controllability line and Data Flow above, and the concrete trigger is in Reproduction below.

Exploitability: Medium
Realism: Medium

Reproduction

  1. Attacker controls the hypervisor (QEMU/KVM) hosting a confidential-computing guest (SEV/TDX); guest firmware includes QemuKernelLoaderFsDxe.
  2. Host sets the fw_cfg file directory count to a value causing allocation failure (e.g., QemuFwCfgItemFileDir selector with count = 0xFFFFFFFF).
  3. Guest boots and calls QemuKernelFetchNamedBlobs.
  4. AllocatePool fails and returns NULL.
  5. QemuFwCfgReadBytes reads 64 * Count bytes into the NULL buffer: since the size exceeds MAX_UINT32, IoReadFifo8 writes host-supplied bytes into guest memory from address 0 upward. With a count below 2^26 whose allocation still fails, the DMA mapping fails instead and the firmware hangs in CpuDeadLoop.

Impact

On a confidential-computing guest (SEV/TDX), a hostile host can either hang the guest firmware during boot (failed DMA mapping) or, with a count of 2^26 or more, make the firmware copy host-supplied bytes over low guest memory starting at address 0. The second case is a host-driven overwrite of guest memory, which the confidential-computing model is meant to prevent; whether it can be steered to something useful before the write faults is not shown.

Remediation and Mitigation

As of commit 70741a15d9a714323a5598eac47727e60507e22f this issue is unfixed upstream and no CVE has been assigned. Check the allocation result for NULL before dereferencing it and fail the operation cleanly when allocation fails. The specific control that is absent or ineffective is identified in the Sanitization / Security Controls list under Technical Details.

Timeline

  • 2026-06-25 - Reported to VulnCheck for coordinated disclosure to the TianoCore / EDK II security team.
  • 2026-07 to 2026-10 - Several follow-ups sent; no response received.
  • 2026-10-29 - Public disclosure in good faith, 126 days after the initial report.

Credits

Discovered and reported by Argus-Systems.

References