Files
vphone-cli/sources/FirmwarePatcher/Kernel/JBPatches/KernelJBPatchProcSecurity.swift
Managed via Tart d042596cc0 Complete Swift firmware patcher parity and CLI wiring
Run SwiftFormat on firmware patcher

Remove legacy Python firmware patchers

Fix compare pipeline pyimg4 PATH handling

Restore Python patchers and prefer fresh restore

Update BinaryBuffer.swift

Avoid double scanning in patcher apply

Prefer Python TXM site before fallback

Retarget TXM trustcache finder for 26.1

Remove legacy Python firmware patchers

Fail fast on nested virtualization hosts

Return nonzero on fatal boot startup

Add amfidont helper for signed boot binary

Stage AMFI boot args for next host reboot

Add host preflight for boot entitlements

Fail fast when boot entitlements are unavailable

Switch firmware patch targets to Swift CLI

Record real Swift firmware parity results

Verify Swift firmware pipeline end-to-end parity

Fix Swift firmware pipeline JB dry-run
2026-03-11 15:05:49 +08:00

87 lines
3.5 KiB
Swift

// KernelJBPatchProcSecurity.swift JB: stub _proc_security_policy with mov x0,#0; ret.
//
// Historical note: derived from the legacy Python firmware patcher during the Swift migration.
//
// Reveal: find _proc_info by `sub wN,wM,#1 ; cmp wN,#0x21` switch pattern,
// then identify _proc_security_policy among BL targets called 2+ times,
// with function size in [0x40, 0x200].
import Foundation
extension KernelJBPatcher {
/// Stub _proc_security_policy: mov x0,#0; ret.
@discardableResult
func patchProcSecurityPolicy() -> Bool {
log("\n[JB] _proc_security_policy: mov x0,#0; ret")
guard let (procInfoFunc, switchOff) = findProcInfoAnchor() else {
log(" [-] _proc_info function not found")
return false
}
let ksStart = codeRanges.first?.start ?? 0
let ksEnd = codeRanges.first?.end ?? buffer.count
let procInfoEnd = findFuncEnd(procInfoFunc, maxSize: 0x4000)
log(" [+] _proc_info at 0x\(String(format: "%X", procInfoFunc)) (size 0x\(String(format: "%X", procInfoEnd - procInfoFunc)))")
// Count BL targets after switch dispatch within _proc_info.
var blTargetCounts: [Int: Int] = [:]
for off in stride(from: switchOff, to: procInfoEnd, by: 4) {
guard off + 4 <= buffer.count else { break }
let insn = buffer.readU32(at: off)
// BL: [31:26] = 0b100101
guard insn >> 26 == 0b100101 else { continue }
let imm26 = insn & 0x03FF_FFFF
let signedImm = Int32(bitPattern: imm26 << 6) >> 6
let target = off + Int(signedImm) * 4
guard target >= ksStart, target < ksEnd else { continue }
blTargetCounts[target, default: 0] += 1
}
guard !blTargetCounts.isEmpty else {
log(" [-] no BL targets found in _proc_info switch cases")
return false
}
// Sort by count descending, then by address ascending (to match Python
// Counter.most_common() insertion-order tie-breaking from the forward scan).
let sorted = blTargetCounts.sorted {
if $0.value != $1.value { return $0.value > $1.value }
return $0.key < $1.key
}
for (foff, count) in sorted {
guard count >= 2 else { break }
let funcEnd = findFuncEnd(foff, maxSize: 0x400)
let funcSize = funcEnd - foff
log(" [*] candidate 0x\(String(format: "%X", foff)): \(count) calls, size 0x\(String(format: "%X", funcSize))")
if funcSize > 0x200 {
log(" [-] skipped (too large, likely utility)")
continue
}
if funcSize < 0x40 {
log(" [-] skipped (too small)")
continue
}
log(" [+] identified _proc_security_policy at 0x\(String(format: "%X", foff)) (\(count) calls, size 0x\(String(format: "%X", funcSize)))")
emit(foff, ARM64.movX0_0,
patchID: "jb.proc_security_policy.mov_x0_0",
virtualAddress: fileOffsetToVA(foff),
description: "mov x0,#0 [_proc_security_policy]")
emit(foff + 4, ARM64.ret,
patchID: "jb.proc_security_policy.ret",
virtualAddress: fileOffsetToVA(foff + 4),
description: "ret [_proc_security_policy]")
return true
}
log(" [-] _proc_security_policy not identified among BL targets")
return false
}
}