mirror of
https://github.com/Lakr233/vphone-cli.git
synced 2026-04-05 13:09:06 +08:00
Apply whitespace and formatting cleanups across research/kernel_patch_jb/*.md: add missing blank lines for readability, remove extraneous trailing blank lines, and adjust a small inline spacing/punctuation in patch_vm_map_protect.md. No semantic changes to content.
6.8 KiB
6.8 KiB
B11 patch_mac_mount (2026-03-06 rework)
Verdict
- Final result: match upstream
/Users/qaq/Desktop/patch_fw.py. - Upstream reference patches the PCC 26.1 research kernel at:
0xFFFFFE0007CA9D54/ file offset0x00CA5D540xFFFFFE0007CA9D88/ file offset0x00CA5D88
- Reworked runtime matcher now lands on those same two sites again.
- Previous local drift to
0xFFFFFE0007CA8EAC/0x00CA4EACis now treated as wrong for this patch: that site is inside the lowerprepare_coveredvp()helper and corresponds to the ownership /EPERMgate, not the upstream mount-role wrapper gate.
Anchor class
- Primary runtime anchor class: string anchor.
- String used:
"mount_common()". - Why this anchor: it is present in the same VFS syscall compilation unit on the stripped PCC kernels, survives the empty embedded symtable case (
0 []), and gives a stable way to recover the localmount_commonfunction without IDA names or external symbol dumps. - Secondary discovery after the string anchor: semantic control-flow search over nearby callers of the recovered
mount_commonfunction.
Where the patch lands
Site 1 — preboot-role reject gate
- Match site:
0xFFFFFE0007CA9D54/0x00CA5D54 - Stock instruction:
tbnz w28, #5, ... - Patched instruction:
nop - Upstream relation: exact match to
/Users/qaq/Desktop/patch_fw.pypatch(0xCA5D54, 0xD503201F).
Site 2 — role-state byte gate
- Match site:
0xFFFFFE0007CA9D88/0x00CA5D88 - Stock instruction:
ldrb w8, [x8, #1] - Patched instruction:
mov x8, xzr - Upstream relation: exact match to
/Users/qaq/Desktop/patch_fw.pypatch(0xCA5D88, 0xAA1F03E8).
Why these are the correct semantic gates
Facts from IDA MCP on PCC 26.1 research
- The
mount_common()string xref recovers the main mount flow function at0xFFFFFE0007CA7868. - The upstream-matching wrapper candidate is a nearby caller that itself calls back into that
mount_commonfunction. - In that wrapper, the first patch site is the sequence:
tbnz w28, #5, loc_fail- then, on the fail target,
mov w25, #1 ; b ...
- In
research/reference/xnu/bsd/sys/mount_internal.h, bit0x20isKERNEL_MOUNT_PREBOOTVOL. - In the same wrapper, the second patch site is the sequence:
add x8, x16, #0x70ldrb w8, [x8, #1]tbz w8, #6, loc_continue_to_mount_commonorr w8, w28, #0x10000tbnz w28, #0, ...mov w25, #1
- The
tbz w8, #6target flows into the block that calls back into the recoveredmount_commonfunction.
Source-backed interpretation
- Fact:
KERNEL_MOUNT_PREBOOTVOLis bit 5 inmount_internal.h. - Inference: the first gate is the early Preboot-volume reject path in the mount-role wrapper; NOPing it matches the known-to-work upstream behavior.
- Fact: the second gate tests a byte-derived bit before the wrapper continues into the
mount_commoncall path. - Inference: forcing that loaded byte to zero reproduces the upstream intent of always taking the stock
tbz ..., #6, continuepath. - Because both patched sites are in the wrapper that selects whether execution can even reach
mount_common, they are a better semantic fit forpatch_mac_mountthan the previously drifted lower helper branch.
Why the previous local drift was rejected
- Previous local matcher patched
0xFFFFFE0007CA8EAC/0x00CA4EAC. - IDA + XNU correlation shows that sequence belongs to the lower
prepare_coveredvp()helper. - That helper sequence matches the source shape of the ownership /
EPERMpreflight:vnode_getattr(...)- compare owner uid vs credential uid / root
- on failure set
W0 = 1
- That is not the same gate as the upstream B11 design target.
- Since
/Users/qaq/Desktop/patch_fw.pyis known-to-work and the upstream sites still exist on PCC 26.1 research, keeping the drift would be a red flag; the rework therefore restores upstream semantics.
Runtime matcher design
- Step 1: recover
mount_commonvia the"mount_common()"string anchor. - Step 2: scan only a local window around that function for callers that branch-link into it.
- Step 3: among those callers, require the unique paired shape:
- a
tbnz <flags>, #5 -> mov #1reject gate, and - a later
add ..., #0x70 ; ldrb ; tbz #6 -> block that calls mount_commongate.
- a
- Step 4: patch exactly those two instructions.
Why this should generalize to PCC 26.1 release / likely 26.3 release
- It does not depend on IDA names, embedded symbols, or fixed addresses.
- The primary anchor is a diagnostic string already used elsewhere in the same VFS syscall unit and expected to survive stripped release kernels.
- The secondary matcher keys off stable semantics from XNU source and local control flow:
KERNEL_MOUNT_PREBOOTVOLbit test,- the nearby role-state byte test,
- and the wrapper-to-
mount_commoncall relationship.
- This is more likely to survive research vs release layout drift than the previous shallow “first callee with
bl ; cbnz w0” heuristic.
Performance notes
- Runtime cost stays bounded:
- one string lookup,
- one local scan window around the recovered
mount_commonfunction, - semantic inspection of only the small set of nearby caller functions.
- It avoids whole-kernel heuristic sweeps and does not require expensive external symbol processing.
Focused dry-run (2026-03-06)
- Kernel: extracted PCC 26.1 research raw Mach-O
/tmp/vphone-kcache-research-26.1.raw - Result:
method_return=True - Emitted writes:
0x00CA5D54—NOP [___mac_mount preboot-role reject]0x00CA5D88—mov x8, xzr [___mac_mount role-state gate]
- Upstream comparison: exact offset match with
/Users/qaq/Desktop/patch_fw.py.
2026-03-06 Rework
- Upstream target (
/Users/qaq/Desktop/patch_fw.py):match. - Final research sites:
0x00CA5D54(0xFFFFFE0007CA9D54) and0x00CA5D88(0xFFFFFE0007CA9D88). - Anchor class:
mixed string+heuristic. Runtime reveal uses the stable"mount_common()"string only to bound the surroundingvfs_syscalls.cneighborhood, then picks the unique nearby function that contains both upstream local gates: the earlytbnz wFlags,#5branch and the lateradd xN,#0x70 ; ldrb wN,[xN,#1] ; tbz wN,#6policy-byte test. - Why these sites: they are the exact upstream dual-site bypass. The earlier drift to
0x00CA4EACpatched a differentcbnz w0gate in another helper and is therefore rejected as an upstream mismatch. - Release/generalization rationale: the string keeps the search local to the right source module, while the paired semantic patterns identify the same function without relying on symbols. That combination should survive 26.1 release / likely 26.3 release better than a raw offset.
- Performance note: one string anchor plus a bounded neighborhood scan (~
0x9000bytes) instead of a whole-kernel semantic walk. - Focused PCC 26.1 research dry-run:
hit, 2 writes at0x00CA5D54and0x00CA5D88.