Files
vphone-cli/research/kernel_patch_jb/patch_proc_security_policy.md
T
Lakr 5388e0c9c5 Squash merge startup-hang-fix into main
Prefix research patch comparison doc and normalize root markdown names

Rename research root markdown files to scoped topic names
2026-03-06 02:42:12 +08:00

11 KiB

B6 patch_proc_security_policy (re-validated)

What was re-checked

  • Re-done from static analysis in IDA MCP only (no trust in previous notes).
  • Verified call graph, callers, argument flow, and failure mode for wrong target.
  • Marked IDA names in two groups:
    • patched function group:
      • 0xFFFFFE0008067148 -> jb_patched_proc_security_policy
      • 0xFFFFFE000806714C -> jb_patchpoint_B6_ret0_step2
    • supplement group:
      • 0xFFFFFE0008064034 -> jb_supp_proc_info_syscall_entry_args
      • 0xFFFFFE0008064078 -> jb_supp_proc_info_syscall_mux
      • 0xFFFFFE0008064A30 -> jb_supp_proc_info_core_switch
      • 0xFFFFFE0008065540 -> jb_supp_proc_listpids_handler
      • 0xFFFFFE0008065F6C -> jb_supp_proc_pidinfo_handler
      • 0xFFFFFE0008066624 -> jb_supp_proc_setcontrol_handler
      • 0xFFFFFE0008066C9C -> jb_supp_proc_pidfdinfo_handler (label in mux body)
      • 0xFFFFFE00082D5104 -> jb_supp_mac_proc_check_proc_info
      • 0xFFFFFE00082ED7B8 -> jb_supp_priv_check_cred
      • 0xFFFFFE00082EDA8C -> jb_supp_priv_check_cred_visible
      • 0xFFFFFE0007C4DD48 -> jb_supp_copyio_common_helper

Real patch target and bytes

  • Target: jb_patched_proc_security_policy (VA 0xFFFFFE0008067148, file 0x1063148, size 0x134).
  • Patch action: overwrite function entry with:
    • mov x0, #0
    • ret
  • Effect: force this policy routine to return success immediately.

Full static call trace (why this function is reached)

  1. Syscall table data entry points to jb_supp_proc_info_syscall_entry_args (xrefs @ 0xFFFFFE00077417D8).
  2. jb_supp_proc_info_syscall_entry_args forwards to jb_supp_proc_info_syscall_mux.
  3. Mux dispatches to proc-info family handlers; those call jb_patched_proc_security_policy before serving data:
    • jb_supp_proc_info_core_switch callsites:
      • 0xFFFFFE0008064BD4: args (proc, 2, flavor, 0/1)
      • 0xFFFFFE0008065098: args (proc, 3, 1, flag)
    • jb_supp_proc_listpids_handler @ 0xFFFFFE0008065658: (proc, 3, list_flavor, 1)
    • jb_supp_proc_pidinfo_handler @ 0xFFFFFE0008066248: (proc, 6, pidinfo_flavor, 1)
    • jb_supp_proc_setcontrol_handler @ 0xFFFFFE0008066678: (proc, 9, selector, 1)
    • mux-internal path @ 0xFFFFFE0008066CE4: (proc, 0xD, 0, 1)
  4. Non-zero return from jb_patched_proc_security_policy branches directly to error paths in these handlers.

What jb_patched_proc_security_policy enforces (unpatched behavior)

Unpatched flow (from disasm/decompile):

  1. Calls jb_supp_mac_proc_check_proc_info(caller_cred, target_proc, policy_class, flavor).
    • If non-zero, returns that error.
  2. If arg4/check flag is zero, returns success.
  3. Otherwise compares caller and target identities (uid field compare).
  4. If identities differ, enforces privilege gate with constant 0x3EA (1002):
    • jb_supp_priv_check_cred(caller_cred, 1002)
    • and conditional jb_supp_priv_check_cred_visible(caller_cred, 1002) path.
  5. Any failure returns denial to caller.

Why this patch is required for unsigned binaries and launchd dylib workflow

Static facts:

  • This function is the shared gate for proc_info/proc_listpids/proc_pidinfo/proc_setcontrol style paths.
  • Those paths are widely used by libproc-driven process enumeration/introspection/control.
  • Cross-identity queries require passing the 1002 privilege gate above.

Inference from those facts:

  • Unsigned/non-platform processes (including early injected launchd hook context) are much more likely to fail this gate, especially on cross-uid targets.
  • When that happens, proc-info-family syscalls return denial, which breaks process introspection/control flows needed by jailbreak userland and launchd hook behavior.
  • Stubbing this function to return 0 removes that choke point and lets those flows proceed.

Why previous wrong patch caused launchd exec failure

  • Wrong target was jb_supp_copyio_common_helper (VA 0xFFFFFE0007C4DD48, file 0xC49D48, size 0x28C, 619 xrefs).
  • In _proc_info BL-count scan, copyio appears 4 times vs policy function 2 times.
  • Patching copyio globally breaks copyin/copyout semantics across kernel paths.
  • Static proof: launchd bootstrap path (sub_FFFFFE0007FADC68) directly uses jb_supp_copyio_common_helper while preparing /sbin/launchd, and contains log string:
    • "Process 1 exec of %s failed, errno %d @%s:%d"
  • So the old false hit explains the observed launchd exec failure.

Practical patcher implications

  • Do not pick target by BL frequency alone inside jb_supp_proc_info_core_switch.
  • Required disambiguation is validated:
    • same anchor (sub wN,wM,#1; cmp wN,#0x21)
    • count BLs after switch dispatch
    • size gate excludes copyio (0x28C) and keeps policy target (0x134)
    • optionally require xref set to proc-info-family handlers only.

Symbol Consistency Audit (2026-03-05)

  • Status: partial
  • Direct recovered symbol proc_security_policy is not present in current kernel_info JSON.
  • However, anchor-chain symbols proc_info (0xfffffe000806d4dc) and proc_info_internal (0xfffffe000806d520) are recovered and consistent with this document's call-path placement.
  • Function labels in this doc remain analyst-derived for the inner policy helper layer.

Patch Metadata

  • Patch document: patch_proc_security_policy.md (B6).
  • Primary patcher module: scripts/patchers/kernel_jb_patch_proc_security.py.
  • Analysis mode: static binary analysis (IDA-MCP + disassembly + recovered symbols), no runtime patch execution.

Patch Goal

Stub proc-security policy helper to success to avoid proc-info/proc-control authorization denials.

Target Function(s) and Binary Location

  • Primary target: policy helper at 0xfffffe0008067148 (analyst label jb_patched_proc_security_policy).
  • Patchpoint: function entry overwritten with mov x0,#0; ret.

Kernel Source File Location

  • Expected XNU source family: bsd/kern/proc_info.c / proc-info authorization helpers.
  • Confidence: medium.

Function Call Stack

  • Primary traced chain (from Full static call trace (why this function is reached)):
    1. Syscall table data entry points to jb_supp_proc_info_syscall_entry_args (xrefs @ 0xFFFFFE00077417D8).
    1. jb_supp_proc_info_syscall_entry_args forwards to jb_supp_proc_info_syscall_mux.
    1. Mux dispatches to proc-info family handlers; those call jb_patched_proc_security_policy before serving data:
  • jb_supp_proc_info_core_switch callsites:
  • 0xFFFFFE0008064BD4: args (proc, 2, flavor, 0/1)
  • The upstream entry(s) and patched decision node are linked by direct xref/callsite evidence in this file.

Patch Hit Points

  • Key patchpoint evidence (from Real patch target and bytes):
  • Target: jb_patched_proc_security_policy (VA 0xFFFFFE0008067148, file 0x1063148, size 0x134).
  • The before/after instruction transform is constrained to this validated site.

Current Patch Search Logic

  • Implemented in scripts/patchers/kernel_jb_patch_proc_security.py.
  • Site resolution uses anchor + opcode-shape + control-flow context; ambiguous candidates are rejected.
  • The patch is applied only after a unique candidate is confirmed in-function.
  • same anchor (sub wN,wM,#1; cmp wN,#0x21)
  • However, anchor-chain symbols proc_info (0xfffffe000806d4dc) and proc_info_internal (0xfffffe000806d520) are recovered and consistent with this document's call-path placement.

Pseudocode (Before)

if (mac_proc_check_proc_info(...) != 0) return EPERM;
if (!cred_visible_or_privileged(..., 1002)) return EPERM;
return 0;

Pseudocode (After)

/* policy helper is stubbed */
int proc_security_policy(...) {
    return 0;
}

Validation (Static Evidence)

  • Verified with IDA-MCP disassembly/decompilation, xrefs, and callgraph context for the selected site.
  • Cross-checked against recovered symbols in research/kernel_info/json/kernelcache.research.vphone600.bin.symbols.json.
  • Address-level evidence in this document is consistent with patcher matcher intent.

Expected Failure/Panic if Unpatched

  • Proc-info/proc-control authorization stays enforced and returns denial for cross-identity operations required by tooling.

Risk / Side Effects

  • This patch weakens a kernel policy gate by design and can broaden behavior beyond stock security assumptions.
  • Potential side effects include reduced diagnostics fidelity and wider privileged surface for patched workflows.

Symbol Consistency Check

  • Recovered-symbol status in kernelcache.research.vphone600.bin.symbols.json: partial.
  • Canonical symbol hit(s): none (alias-based static matching used).
  • Where canonical names are absent, this document relies on address-level control-flow and instruction evidence; analyst aliases are explicitly marked as aliases.
  • IDA-MCP lookup snapshot (2026-03-05): 0xfffffe0008067148 currently resolves to sub_FFFFFE0008067104 (size 0x130).

Open Questions and Confidence

  • Open question: symbol recovery is incomplete for this path; aliases are still needed for parts of the call chain.
  • Overall confidence for this patch analysis: medium (address-level semantics are stable, symbol naming is partial).

Evidence Appendix

  • Detailed addresses, xrefs, and rationale are preserved in the existing analysis sections above.
  • For byte-for-byte patch details, refer to the patch-site and call-trace subsections in this file.

Runtime + IDA Verification (2026-03-05)

  • Verification timestamp (UTC): 2026-03-05T14:55:58.795709+00:00
  • Kernel input: /Users/qaq/Documents/Firmwares/PCC-CloudOS-26.3-23D128/kernelcache.research.vphone600
  • Base VA: 0xFFFFFE0007004000
  • Runtime status: hit (2 patch writes, method_return=True)
  • Included in KernelJBPatcher.find_all(): True
  • IDA mapping: 2/2 points in recognized functions; 0 points are code-cave/data-table writes.
  • IDA mapping status: ok (IDA runtime mapping loaded.)
  • Call-chain mapping status: ok (IDA call-chain report loaded.)
  • Call-chain validation: 1 function nodes, 2 patch-point VAs.
  • IDA function sample: sub_FFFFFE00080705F0
  • Chain function sample: sub_FFFFFE00080705F0
  • Caller sample: proc_info_internal, sub_FFFFFE000806DED8, sub_FFFFFE000806E9E8, sub_FFFFFE000806F414, sub_FFFFFE000806FACC
  • Callee sample: _enable_preemption_underflow, sub_FFFFFE0007B84334, sub_FFFFFE0007C64A3C, sub_FFFFFE0007FCA008, sub_FFFFFE00080705F0, sub_FFFFFE00082DD990
  • Verdict: valid
  • Recommendation: Keep enabled for this kernel build; continue monitoring for pattern drift.
  • Key verified points:
  • 0xFFFFFE00080705F0 (sub_FFFFFE00080705F0): mov x0,#0 [_proc_security_policy] | 7f2303d5 -> 000080d2
  • 0xFFFFFE00080705F4 (sub_FFFFFE00080705F0): ret [_proc_security_policy] | f85fbca9 -> c0035fd6
  • Artifacts: research/kernel_patch_jb/runtime_verification/runtime_verification_report.json
  • Artifacts: research/kernel_patch_jb/runtime_verification/ida_runtime_patch_points.json
  • Artifacts: research/kernel_patch_jb/runtime_verification/ida_patch_chain_report.json
  • Artifacts: research/kernel_patch_jb/runtime_verification/ida_patch_chain_report.md