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.
5.6 KiB
B15 patch_task_for_pid
Goal
Keep the jailbreak task_for_pid patch aligned with the known-good upstream design in /Users/qaq/Desktop/patch_fw.py unless IDA + XNU clearly prove that upstream is wrong.
- Preferred upstream target:
patch(0xFC383C, 0xD503201F). - Final rework result:
match. - PCC 26.1 research hit: file offset
0x00FC383C, VA0xFFFFFE0007FC783C. - PCC 26.1 release hit: file offset
0x00F8783C.
What Gets Patched
The patch NOPs the early pid == 0 reject gate in task_for_pid, before the call that resolves the target task port.
On PCC 26.1 research the validated sequence is:
0xFFFFFE0007FC7828 ldr w23, [x8, #8]
0xFFFFFE0007FC782C ldr x19, [x8, #0x10]
0xFFFFFE0007FC783C cbz w23, 0xFFFFFE0007FC79CC ; patched
0xFFFFFE0007FC7840 mov w1, #0
0xFFFFFE0007FC7844 mov w2, #0
0xFFFFFE0007FC7848 mov w3, #0
0xFFFFFE0007FC784C mov x4, #0
0xFFFFFE0007FC7850 bl <helper>
0xFFFFFE0007FC7854 cbz x0, 0xFFFFFE0007FC79CC
Upstream Match vs Divergence
Final status: match
- Upstream
patch_fw.pyuses file offset0xFC383C. - The reworked matcher now emits exactly
0xFC383Con PCC 26.1 research. - The corresponding PCC 26.1 release hit is
0xF8783C, which is the expected variant-shifted analogue of the same in-function gate.
Rejected drift design
The previous local rework had diverged to two later deny-return rewrites in small helper functions.
That divergence is rejected because:
- it does not match the known-good upstream site,
- the XNU source still explicitly says
/* Always check if pid == 0 */and immediately returns failure, - IDA on PCC 26.1 research still shows the same early
cbz wPid, failgate at the exact upstream offset, - the helper-rewrite path broadens behavior more than necessary and is computationally more expensive at runtime.
XNU Cross-Reference
Source: research/reference/xnu/bsd/kern/kern_proc.c:5715
/* Always check if pid == 0 */
if (pid == 0) {
(void) copyout((char *)&tret, task_addr, sizeof(mach_port_name_t));
AUDIT_MACH_SYSCALL_EXIT(KERN_FAILURE);
return KERN_FAILURE;
}
Fact
- The source-level first authorization gate in
task_for_pid()is thepid == 0rejection. - The validated PCC 26.1 research instruction at
0xFFFFFE0007FC783Cis the direct binary analogue of that source gate.
Inference
NOPing this early cbz is the narrowest upstream-compatible jailbreak bypass because it removes only the unconditional pid == 0 failure gate, while leaving the later proc_find(), task_for_pid_posix_check(), and task lookup flow structurally intact.
Anchor Class
- Primary runtime anchor class:
string + heuristic. - Concrete string anchor:
"proc_ro_ref_task", which lives inside the same stripped function body on PCC 26.1 research. - Why this anchor was chosen: the embedded symtable is effectively empty, IDA names are not stable, but this in-function string reliably recovers the enclosing function so the heuristic scan stays local instead of walking the whole kernel.
Runtime Matcher Design
The runtime matcher is intentionally single-path and upstream-aligned:
- Recover the enclosing function from the in-image string
"proc_ro_ref_task". - Scan only that function for the unique local sequence:
ldr wPid, [xArgs, #8]ldr xTaskPtr, [xArgs, #0x10]cbz wPid, failmov w1, #0mov w2, #0mov w3, #0mov x4, #0blcbz x0, fail
- Patch the first
cbzwithNOP.
This avoids unstable IDA naming while keeping the reveal logic close to the exact upstream gate.
Why This Should Generalize
This matcher should survive PCC 26.1 research, PCC 26.1 release, and likely nearby release variants such as 26.3 because it relies on:
- the stable syscall argument layout (
pidat+8, task port output at+0x10), - the narrow early-failure ABI shape around
port_name_to_task(), and - a single local fail target shared by
cbz wPidand the post-helpercbz x0.
Runtime cost remains reasonable:
- one full sequential decode of
kern_text, - no repeated nested scans,
- one exact candidate accepted.
Validation
Focused dry-run
Validated locally on extracted raw kernels:
- PCC 26.1 research:
hitat0x00FC383C - PCC 26.1 release:
hitat0x00F8783C
Both variants emit exactly one patch:
NOP [_task_for_pid pid==0 gate]
Match verdict
- Upstream reference
/Users/qaq/Desktop/patch_fw.py:match - IDA PCC 26.1 research control-flow:
match - XNU
task_for_pidearly gate semantics:match
Files
- Patcher:
scripts/patchers/kernel_jb_patch_task_for_pid.py - Analysis doc:
research/kernel_patch_jb/patch_task_for_pid.md
2026-03-06 Rework
- Upstream target (
/Users/qaq/Desktop/patch_fw.py):match. - Final research site:
0x00FC383C(0xFFFFFE0007FC783C). - Anchor class:
string + heuristic. Runtime reveal recovers the enclosing function from the in-image"proc_ro_ref_task"string, then finds the unique upstream localldr pid ; ldr task_ptr ; cbz pid ; mov w1/w2/w3,#0 ; mov x4,#0 ; bl ; cbz x0pattern. - Why this site: it is the exact known-good upstream
pid == 0reject gate, and XNU still models it as the first unconditional failure path intask_for_pid(). - Release/generalization rationale: the local ABI/control-flow pattern is narrow and stable across stripped kernels, while avoiding reliance on symbol names.
- Performance note: one string-xref resolution plus a single bounded local scan (
+0x800window) because the stripped-function end detector truncates this function too early on current PCC 26.1 images; still no whole-kernel repeated semantic rescans. - Focused PCC 26.1 research dry-run: pending main-agent validation.