- docs/IOS27.2-KERNEL-DIFF.md: 27.0.1 vs 27.2 (iPhone19,7), 162 advisory CVEs, 93 size-changed kexts; confirmed fix sites for 112705 (NTL 0..7 assertion), 113910 (produced vs expected chunk bytes), 112507 (ipr/table NULL checks in ipc_misc.c); __DATA_SPTM byte-identical, no PPL/SPTM/MIE code change or bypass fix - tools/ipsw/: Range-based IPSW reader, IM4P/LZFSE + fileset parser, kext extractor, llvm-objdump diff, advisory mapper - CVE-2026-112705: --sweep mode (0..12, no frame) in both POCs; app module now sweeps 0/1/7/8/64/1024/16462/16463 - app 2.3 build 7
7.9 KiB
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:
__TEXT_EXECsize change (layout-independent),__cstring/__oslogstringset difference (new checks usually add a message),llvm-objdumpinstruction 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_SPTMis byte-identical in both builds: 311,296 bytes, SHA-256f4bc1e5e95f61af5…. 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.
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
python3 tools/ipsw/remote_ipsw.py extract <ipsw-url> 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.