Hacktricks-skills cve-2021-30807-analysis
Analyze and understand CVE-2021-30807, an iOS kernel out-of-bounds read vulnerability in IOMobileFramebuffer/AppleCLCD. Use this skill when researching iOS kernel exploits, studying IOMobileFramebuffer vulnerabilities, analyzing selector 83 exploitation, understanding IOSurface heap spraying techniques, or examining the OOB pointer read + type confusion primitive. Trigger for any questions about this specific CVE, iOS kernel user client exploitation, or when analyzing the Saar Amar PoC code.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/binary-exploitation/ios-exploiting/CVE-2021-30807-IOMobileFrameBuffer/SKILL.MDCVE-2021-30807: IOMobileFramebuffer OOB Analysis
A skill for understanding and analyzing CVE-2021-30807, an out-of-bounds read vulnerability in iOS kernel's IOMobileFramebuffer/AppleCLCD that enables arbitrary kernel reads.
Vulnerability Overview
Affected Versions:
- iOS/iPadOS < 14.7.1
- macOS Big Sur < 11.5.1
- watchOS < 7.6.1
Vulnerability Type: Out-of-bounds pointer read + type confusion
Impact: Arbitrary kernel read primitive (can lead to LPE with additional techniques)
Entitlement Required:
com.apple.private.allow-explicit-graphics-priority (available to WebKit.WebContent)
The Bug Mechanics
Vulnerable Code Path
Userland → IOMobileFramebufferUserClient::s_displayed_fb_surface(...) → IOMobileFramebufferLegacy::get_displayed_surface(this, task*, out_id, scalar0) → ptr = *(this + 0xA58 + scalar0 * 8) // OOB READ → IOSurfaceRoot::copyPortNameForSurfaceInTask(task, (IOSurface*)ptr, &out)
Key Details
-
User-controlled index:
is a 32-bit value passed from userland with no bounds checkingscalar0 -
OOB pointer fetch: The kernel reads from
wherethis + 0xA58 + index*8index = scalar0 -
Type confusion: The fetched pointer is cast to
and passed to IOSurface codeIOSurface* -
Result:
- If pointer is invalid → kernel panic (DoS)
- If pointer is valid IOSurface → returns Mach port name (arbitrary read primitive)
Exploitation Flow
Step 1: Open the User Client
// Find AppleCLCD service in IORegistry io_service_t service = IOServiceGetMatchingService( kIOMasterPortDefault, IOServiceMatching("AppleCLCD")); // Open user client type 2 (exposes selector 83) IOServiceOpen(service, mach_task_self(), 2, &user_client_conn);
Why type 2? This user client variant exposes the external methods table containing selector 83.
Step 2: Heap Spray with IOSurfaces
The spray populates kernel heap with valid IOSurface objects so the OOB read hits something legitimate:
// Create many IOSurfaces for (size_t i = 0; i < SURFACES_COUNT; ++i) { surface_ids[i] = create_surface(iosurface_uc); // Spray small values to fill kalloc regions IOSurface_spray_with_gc(iosurface_uc, surface_ids[i], 20, 200, data, sizeof(data), NULL); }
Goal: When selector 83 reads past the legitimate array, it likely hits a pointer to one of your sprayed IOSurfaces.
Step 3: Trigger the OOB Read
// Convert byte offset to pointer slot index (8 bytes per slot on 64-bit) uint64_t scalars[1] = { offset / 8 }; // Call selector 83 IOConnectCallMethod(appleclcd_uc, 83, scalars, 1, NULL, 0, output_scalars, &output_scalars_size, NULL, NULL); // Returns Mach port name (u32 handle) to the IOSurface at OOB slot
The offset/8 trick: The kernel computes
base + index*8, so you specify slot number, not byte offset.
Step 4: Use the Returned Port
The call returns a Mach port name (not a raw address). You can then:
(method 34) → convert port to surface IDs_lookup_surface_from_port
(method 35) → inverse operations_create_port_from_surface
Key Technical Concepts
Why IOSurface?
IOSurface is a classic kernel spray primitive because:
- Well-documented allocation patterns
- Predictable kalloc bucket sizes
- Many methods for creating/manipulating surfaces
- Accessible from sandboxed processes (WebKit.WebContent)
The Type Confusion
The vulnerability doesn't just read OOB—it misinterprets what it reads:
- Reads arbitrary pointer from kernel memory
- Casts it to
IOSurface* - Passes it to
IOSurfaceRoot::copyPortNameForSurfaceInTask() - If the pointer happens to be a valid IOSurface, the call succeeds
- Returns a legitimate Mach port to that IOSurface
This is more powerful than a simple OOB read because it gives you a handle to kernel memory.
Entitlement Bypass
The vulnerable method requires
com.apple.private.allow-explicit-graphics-priority, but:
- WebKit.WebContent has this entitlement
- WebKit runs in a sandbox but can still trigger the vulnerability
- This makes the vulnerability exploitable from web context
Analysis Checklist
When analyzing this CVE or similar vulnerabilities:
- Identify the user-controlled parameter (scalar0)
- Trace the code path to find where it's used as an index
- Check for bounds validation (there isn't any here)
- Determine what the OOB read returns (pointer, not data)
- Understand how the returned value is used (type confusion)
- Identify available spray primitives (IOSurface)
- Map the entitlement requirements
- Determine exploitation context (WebKit.WebContent)
References
- Original writeup by Saar Amar
- Exploit PoC code
- Research from jsherman212
- Apple Security Advisory
- NVD CVE Entry
Related Vulnerabilities
This vulnerability is part of a pattern of IOMobileFramebuffer exploits:
- Similar OOB read primitives in other selectors
- Heap spraying with IOSurface is a common iOS kernel exploitation technique
- User client external methods are a frequent attack surface
Research Notes
For security researchers studying this CVE:
-
Understand the primitive: This is an arbitrary read, not arbitrary write. LPE requires additional techniques.
-
Study the spray: The IOSurface spray is critical—without it, the OOB read hits garbage and causes DoS.
-
Port names matter: The return value is a Mach port, not an address. This affects how you use the primitive.
-
Context is key: The entitlement requirement limits exploitation to WebKit.WebContent context.
-
Patch analysis: Compare vulnerable vs. patched code to understand the fix (bounds checking added).
Use this skill when:
- Analyzing CVE-2021-30807 specifically
- Studying iOS kernel user client vulnerabilities
- Understanding IOSurface heap spraying
- Researching selector 83 exploitation
- Learning about OOB read + type confusion primitives
- Analyzing the Saar Amar PoC code
- Preparing for iOS security research or CTF challenges