# iOS 27.2 kernel differential — 27.0.1 vs 27.2 (iPhone19,7) Scope: the iOS 27.2 security update (24B119) against 27.0.1 (24A446) for iPhone 18 Pro Max (`iPhone19,7`). The question: what does the update actually change in the kernel, which of the 162 advisory CVEs can be tied to a fix site, and does anything in the diff look like a PPL / SPTM / MIE bypass. ## How the images were obtained Both restore images are the production IPSWs from Apple's CDN: | Build | Version | Size | Kernelcache member | |---|---|---|---| | 24A446 | 27.0.1 | 12,728,434,807 B | `kernelcache.release.v6x-pandia` | | 24B119 | 27.2 | 13,722,855,612 B | `kernelcache.release.v6x-pandia` | The kernelcache was pulled straight out of the ZIP with HTTP Range requests, so the analysis did not wait for the full 26 GB. The container is IM4P; the payload is LZFSE. | Build | Kernelcache (decoded) | SHA-256 (first 16) | |---|---|---| | 27.0.1 | 78,315,520 B | `dec73956a9a443c5` | | 27.2 | 79,167,488 B | `9a6efbc4be67319a` | Both are `MH_FILESET` images with a `__DATA_SPTM` segment, carrying 303 (27.0.1) and 305 (27.2) fileset entries. Two kexts are new: `com.apple.driver.ApplePencilDriver`, `com.apple.iokit.AppleSecurityResearch`; none were removed. ## Reading the diff Raw text-segment hashes are useless here: the fileset is relinked, so branch displacements and absolute literal pools move in almost every kext even when the code is unchanged. The diff therefore keys on: 1. `__TEXT_EXEC` size change (layout-independent), 2. `__cstring` / `__oslogstring` set difference (new checks usually add a message), 3. `llvm-objdump` instruction diff for the kexts that survive both filters. 93 of 303 common kexts changed text size. The largest are the ones the advisory points at: | Delta | Kext | Advisory component | |---|---|---| | +115,472 | `com.apple.driver.ASIOKit` | IOKit / audio | | +39,624 | `com.apple.driver.AppleH16ANEInterface` | Apple Neural Engine | | +29,376 | `com.apple.kernel` | Kernel | | +16,080 | `com.apple.driver.AppleAVE2` | AVEVideoEncoder | | +9,572 | `com.apple.driver.FairPlayIOKit` | Security | | +9,316 | `com.apple.driver.AppleDisplayCrossbar` | IOMobileFrameBuffer | | +8,304 | `com.apple.AGXG19P` | GPU | | +4,712 | `com.apple.driver.AppleMobileDispH19P-DCP` | IOMobileFrameBuffer | | +4,480 | `com.apple.driver.RTBuddy` | Kernel / RTKit | | +4,152 | `com.apple.driver.AppleSARService` | Kernel | ## Fix sites that are confirmed by strings ### CVE-2026-112705 — AppleAVE2 temporal layers 27.2 adds the upper bound that 27.0.1 lacks: ``` number of temporal layers (prop) is out of range %d %d %d 0 <= pInfo->uPropCfg.sHEVC.iNumberOfTemporalLayers && pInfo->uPropCfg.sHEVC.iNumberOfTemporalLayers <= 7 0 < pInfo->sSessionCfg.sEnc.sAlgCfg.sGOP.iNumOfTemporalLayer && (... <= 7) AVE_HEVC_CheckVPSExtBounds HEVC VPS vps_max_layers_minus1 is out of range HEVC VPS layer_id_in_nuh is out of range HEVC VPS layer-set total is out of range ``` The property is now clamped to **0…7**. The trigger in the 27.0.1 dossier (`NumberOfTemporalLayers = 16463`, first frame → AppleAVE2 +0xDA78) is exactly the value this assertion rejects. A `--sweep` mode was added to both POCs: it sets 0…12 and submits no frame. On macOS 27.0 it accepts 1…12 (and 16463); on 27.2 the >7 rungs must return an error. ### CVE-2026-113910 — decmpfs chunked zlib 27.2 adds the produced-vs-expected check in `AppleFSCompression/Common/ChunkCompression.cpp`: ``` %s:%d: chunk %u produced %lld of %lld expected bytes ``` That is the exact under-production condition the leak harness drives. The C POC's `--loop` / `--keep` collector now sits on a documented fix site. ### CVE-2026-112507 — ipc_port request table 27.2 adds the checks the 27.0.1 code was missing: ``` ipr != ((void*)0) table != ((void*)0) ipc_misc.c ``` This is a **NULL-check fix**, not a reclaimable-object fix. It matches the device result already recorded: `mach_port_request_notification` returns -300 (MIG_TYPE_ERROR) for every type/right combination, 0 of 12,288 registrations armed, so the request-table path is never entered from an unentitled app. ### Other kernel changes The core kernel gains 62 meaningful strings (build paths and UUIDs excluded). The security-relevant ones: - `VM entry %p lock shared lock overflow` — a new vm_map lock-overflow panic, consistent with the COW / vm_map CVEs (112474 / 112576). - `Page modified after framebank withdraw %p` — page-lifecycle check. - `size <= sdl->sdl_alen` — sockaddr_dl bounds check in the network stack. - `speculative_pages_freed` / `_demoted` / `_requeued_inactive` — pageout counters. - `FilterDropBadDirection`, `nx_netif_filter_pkt_to_mbuf`, `pktap != NULL`, `ret == TB_ERROR_SUCCESS` — network filter validation. - `ipr != NULL`, `table != NULL`, `ipc_misc.c` — the 112507 fix. - New entitlements: `com.apple.private.verified-jit-mode`, `com.apple.private.vfs.unmunged-access-time`, `com.apple.security.cs.debugger`. These line up with the 15 Kernel entries in the advisory (UAF, OOB read/write, race, type confusion, COW integrity, kernel-layout disclosure). The advisory does not assign individual functions, so the mapping above is evidence-based, not a per-CVE signature. ## PPL / SPTM / MIE This is the part the request specifically asked to dig into. - `__DATA_SPTM` is **byte-identical** in both builds: 311,296 bytes, SHA-256 `f4bc1e5e95f61af5…`. No SPTM code or data changed. - The PPL token strings (`UAT_PPL_IOCTL_*`, `PPL map operation failed`, `PPL state object`) are unchanged; no new PPL checks or messages. - No MIE / Memory Integrity / mtag / page-protection strings were added or removed. - The only SPTM-related additions are boot-time memory-size validation: `memsize=%u MB leaves no memory for XNU/SPTM to manage`, `Mismatch of ARM_LARGE_MEMORY in SPTM/XNU`, and iBoot DRAM-size checks. These are configuration checks, not a permission bypass. - The 27.2 advisory contains no component named PPL, SPTM, MIE, or Page Protection, and no CVE description mentions them. **Verdict: no PPL, SPTM, or MIE bypass is fixed in iOS 27.2, and the firmware diff shows no change in the SPTM/PPL/MIE code paths.** A bypass PoC for any of the three would have to come from a different bug, not from this update. The kernel CVEs with "write kernel memory" impacts are ordinary kernel memory-safety bugs; none of them is a page-table / monitor bypass on its own, and exploiting one would still have to defeat SPTM/PPL/MIE at runtime. ## The 15 Kernel CVEs — what the advisory claims vs. what the binary shows | CVE | Advisory impact | Description | Binary evidence | R/W potential | |---|---|---|---|---| | 2026-112474 | terminate or **write kernel memory** | UAF | vm_map / lock-overflow strings (candidate) | theoretical UAF→R/W, no trigger | | 2026-112476 | terminate | OOB read | kmalloc/zone paths, no unique string | read/DoS only | | 2026-112501 | terminate | race | — | DoS | | 2026-112507 | terminate or **write kernel memory** | OOB write | `ipr != NULL`, `table != NULL`, `ipc_misc.c` | **not reachable** from an unentitled app (-300) | | 2026-112514 | terminate or corrupt kernel memory | UAF | framebank / page-lifecycle strings (candidate) | theoretical | | 2026-112516 | terminate | UAF | — | DoS | | 2026-112517 | terminate or corrupt kernel memory | UAF | — | theoretical | | 2026-112576 | unexpected COW memory changes | memory integrity | `VM entry ... lock shared lock overflow` (candidate) | data-corruption primitive | | 2026-112606 | terminate | type confusion | — | theoretical | | 2026-112624 | bypass Privacy preferences | improved checks | new `com.apple.private.*` / TCC-adjacent strings (candidate) | privacy bypass, not kernel R/W | | 2026-112665 | determine kernel memory layout | info disclosure | `size <= sdl->sdl_alen` (candidate) | KASLR leak candidate | | 2026-112679 | terminate or corrupt kernel memory | UAF | — | theoretical | | 2026-112698 | terminate | memory handling | — | DoS | | 2026-65350 | terminate or corrupt kernel memory | UAF | — | theoretical | | 2026-84495 | terminate or **write kernel memory** | UAF | — | theoretical | "Advisory impact" is Apple's wording. "Binary evidence" is what the 27.2 kernel actually adds; where no unique string exists, the CVE cannot be pinned to a function from the image alone. "Theoretical" means the primitive class can lead to R/W, not that a working trigger is known. No trigger code for these 15 was recovered from the diff, and no PoC was fabricated. Note the discrepancy on 112507: Apple calls it an out-of-bounds write, while the 27.2 fix is a NULL-check pair (`ipr`, `table`) plus a new `ipc_misc.c` string. A NULL dereference is a DoS, not a reclaimable out-of-bounds object; this matches the device result. ## What can be turned into a PoC | CVE | Primitive | PoC status | |---|---|---| | 2026-112705 | fixed-offset constant fill in AppleAVE2 | existing Swift/C POC + new `--sweep`; kernel panic on 27.0.1, property refused on 27.2 | | 2026-113910 | kernel heap disclosure through decmpfs | existing C collector (`--loop`, `--keep`, pointer classes); read-only | | 2026-112507 | request-table NULL check / race | existing harness; unreachable from an unentitled app (-300) | | 2026-112696 | ANE validation, +39 KB | no trigger in the diff; ANE kext strings show resource/scheduler validation, not a user-reachable entry | | 2026-65385 | IOHIDEvent fixed-offset write | IOHIDFamily grew only 236 B (+ `TCCService`); the advisory's IOKit fix is likely in the userland IOKit.framework (DSC), not this kext | | other Kernel CVEs | UAF/OOB/race | fix sites visible as strings, but no trigger or reclaim strategy; writing a PoC would be guesswork | The WebKit, ImageIO, CoreMedia and other userland components live in the dyld shared cache inside the root filesystem image, which is not part of the ZIP's plain files; those were not diffed here. ## Reproduce ```bash python3 tools/ipsw/remote_ipsw.py extract kernelcache work/kernel/27.2.im4p python3 tools/ipsw/ipswlib.py kernel ... # decode + list python3 tools/ipsw/extract_kext.py work/kernel/27.2.kernel \ work/kernel/27.2-entries.json com.apple.driver.AppleAVE2 out.macho python3 tools/ipsw/disasm_diff.py a.macho b.macho ``` The tools are read-only: no device is touched, and no firmware is modified.