← ALL ADVISORIES

MEDIUM BYTERAY-2026-0279Disclosed

EDK II - Out-of-Bounds Read in GetLongAdFromAds

GetLongAdFromAds loops over a file entry's allocation descriptor sequence, advancing a byte cursor (*Offset) and casting it to a UDF_LONG_ALLOCATION_DESCRIPTOR pointer.

Advisory
BYTERAY-2026-0279
CWE
CWE-125
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 MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c.
Credit
Argus-Systems

Executive Summary

GetLongAdFromAds loops over a file entry's allocation descriptor sequence, advancing a byte cursor (*Offset) and casting it to a UDF_LONG_ALLOCATION_DESCRIPTOR pointer. It then reads the ExtentLength field (4 bytes at offset 0) via GET_EXTENT_FLAGS without first verifying that *Offset + sizeof(UDF_LONG_ALLOCATION_DESCRIPTOR) (16 bytes) <= Length. The only bounds check (line 662: *Offset >= Length) guarantees the cursor merely starts in bounds. *Offset starts at 0 and only advances in steps of 16 (lines 687, 1207, 1254, 1378), but Length is never required to be a multiple of 16. When Length % 16 != 0, the last descriptor starts inside the region and extends up to 15 bytes past it: the ExtentLength read at line 676, and the later reads by the caller ReadFile of ExtentLength (GET_EXTENT_LENGTH, line 1258) and ExtentLocation (via GetAllocationDescriptorLsn → GetLongAdLsn, lines 1260 and 827), go past the AD region bound. For the File Entry, GetAdsInformation only bounds the AD region inside the FE buffer (AllocateCopyPool (Volume->FileEntrySize, ...), line 512), so the OOB reads attacker-controlled FE tail bytes, or crosses into adjacent heap when the AD region ends at the FE buffer end. The Allocation Extent Descriptor path is stronger: GetAedAdsData allocates exactly *Length bytes (line 1002), where *Length is the AED's attacker-controlled LengthOfAllocationDescriptors (line 940), so for example Length = 1 makes the descriptor read at offset 0 run 15 bytes past the heap block.

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 (MdeModulePkg)
  • Affected commit: 70741a15d9a714323a5598eac47727e60507e22f (master, 2026-06-21). The code is present on that commit and later revisions that have not changed it.
  • Location: MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c:662
  • Function: GetLongAdFromAds
  • Category: Out-of-bounds read (CWE-125/126)

Technical Details

Controllability: EXTERNAL_UNTRUSTED — Confidence: High

Data Flow

The vulnerability originates from an external UDF disk image. UdfRead/UdfOpen (File.c:317/164) are EFI entry points invoked when firmware reads or opens a file on the mounted UDF volume. GetAdsInformation (FileSystemOperations.c:601–626) sets *Length = FileEntry->LengthOfAllocationDescriptors and *AdsData = FileEntry->Data + LengthOfExtendedAttributes — both derived from attacker-controlled File Entry fields. This function is explicitly annotated as a boundary receiving untrusted filesystem input. GetAdsInformation validates that Length <= FileEntrySize (line 628), which caps but does not prevent the OOB. GetAllocationDescriptor (line 768) forwards Data/Offset/Length directly with no additional check. GetLongAdFromAds checks only *Offset >= Length (line 662), then casts to (UDF_LONG_ALLOCATION_DESCRIPTOR*)((UINT8*)Data + *Offset) and reads ExtentLength (4 bytes at offset 0) via GET_EXTENT_FLAGS — an OOB read for the last descriptor when Length is not a multiple of 16. The subsequent reads of ExtentLocation@4-9 by ReadFile (via GetAllocationDescriptorLsn, line 1260) are also OOB. When ReadFile follows an indirect AD, GetAedAdsData (line 1231) replaces Data/Length with a buffer of exactly the AED's LengthOfAllocationDescriptors bytes (lines 940, 1002), and the same walk over-reads that heap block.

Affected Callers

  • GetAllocationDescriptor
  • ReadFile
  • GetAedAdsData (supplies the exact-size AED buffer to ReadFile)

Sanitization / Security Controls

Two bounds checks exist: (1) GetAdsInformation validates Length <= FileEntrySize (line 628) — classified as partial (caps the OOB to FE tail bytes or adjacent heap but does not prevent the within-region OOB read; it does not apply to AED buffers, and it does not require Length to be a multiple of the descriptor size); (2) *Offset >= Length (line 662) — classified as ineffective (cursor-start only, no 16-byte remaining-size guard). No other security controls are present.

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. Physical or media access; target firmware includes UdfDxe and mounts/reads UDF volumes; no authentication of disk content before parsing.
  2. Craft a UDF File Entry using Long ADs with LengthOfAllocationDescriptors not a multiple of 16 (or an indirect AD pointing to an Allocation Extent Descriptor whose LengthOfAllocationDescriptors is, for example, 1).
  3. Mark the earlier descriptors as not recorded so the GET_EXTENT_FLAGS skip logic advances *Offset in 16-byte steps to the last, partial descriptor.
  4. Attach the medium and trigger a file read/open.
  5. GetLongAdFromAds passes the cursor-start check, casts the partial position, and reads ExtentLength (and subsequently ExtentLocation) OOB.

Impact

Heap over-read of up to 15 bytes past the AD buffer. The bytes read are not returned to the attacker; they are used as extent flags, extent length and extent location, so they can steer later disk reads to wrong extents or lengths and cause misbehaviour, or a firmware fault if the read crosses into unmapped memory. There is no write.

Remediation and Mitigation

As of commit 70741a15d9a714323a5598eac47727e60507e22f this issue is unfixed upstream and no CVE has been assigned. Before reading each field, validate that its full width fits within the remaining bytes derived from the packet or record size, and stop parsing or reject the input when it does not. 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