Files
vphone-cli/VPhoneGuestComponents
LakrandClaude Opus 5 922e78f895 Fall through to the next libmisfix config when one cannot be read
The config search picked the first path that `stat`ed, then read it and,
if the read failed, reported no override. So the /usr/lib copy only ever
acted as a fallback when `stat` itself failed.

Its whole documented purpose is the case where that is not true. The
header says it is "the fallback if a daemon's sandbox turns out not to
reach /var/db", and a sandbox that allows metadata while denying read
leaves `stat` succeeding and `open` failing — which selected
/var/db/vphone/misfix.plist, read nothing from it, and returned no
override. That is the one result indistinguishable from the hook working
correctly and finding nothing configured, so the failure it was built to
survive was also the failure it could not report.

A candidate is now adopted only when it reads and parses; anything else
falls through to the next. A file that parses but sets no UniqueDeviceID
still counts as adopted, because an explicitly present, valid, empty
configuration means "no override" rather than "keep looking".

The mtime+size cache is kept and still costs one `stat` on the common
path — misagent asks once per profile and installd once per bundle — by
re-checking the file already chosen before searching again. Reading every
candidate on every query would have been the obvious way to write this
and would have reparsed the plist on every MIS call.

Found while verifying the override end to end on test-26.4, where
/usr/lib/libmisfix.plist is an empty dict and /var/db/vphone/misfix.plist
carries the UDID, so the two paths give different answers and picking
the wrong one is silent.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-30 18:28:11 +09:00
..

Sibling guest components

make -C VPhoneGuestComponents package cross-compiles guest components with Xcode's iPhoneOS SDK. The archive contains signed arm64e binaries, two camera tweak filter plists, and the GPU provenance note:

Component Archive contents
Camera app hook camfix/libcamfix.dylib, camfix/libcamfix.plist
Camera daemon hook vcamcaptured/libvcamcaptured.dylib, vcamcaptured/libvcamcaptured.plist
Launchd hook launchhook/launchdhook-vphone.dylib
Process injection bridge systemhook/SystemHook-vphone.dylib
iOS 27 app registrar vpregister/vpregister
PCC GPU driver gpu/README.md (source and extraction flow; no Apple binary)

The archive is a local build artifact, not a VM bootstrap. cfw install places the launchd hook, SystemHook, and camera hooks in /usr/lib, and the vphoned environment update replaces changed copies in a running guest. SystemHook loads libvcamcaptured.dylib into /usr/libexec/cameracaptured and libcamfix.dylib into apps that have AVFoundation loaded; neither camera hook needs ElleKit or a bootstrap. After a bootstrap installs ElleKit, the launchd hook inserts SystemHook into xpcproxy, bootstrap executables, and apps started directly by launchd. Inside xpcproxy, SystemHook carries itself into the final executable through posix_spawnp. Injected App and bootstrap processes carry the hook to their child executables through posix_spawn, posix_spawnp, and execve. SystemHook loads the selected bootstrap's usr/lib/TweakLoader.dylib in App and bootstrap processes when it exists; ElleKit owns tweak selection and loading. It logs PID and executable path to /var/mobile/Library/Caches/vphone-systemhook.log, falling back to the app's own Library/Caches when sandboxed. DISABLE_TWEAKS=1 and the safe-mode flags skip injection. Irisin installs ElleKit's own TweakLoader.dylib in the selected bootstrap. The required GPU bundle is extracted from the selected PCC firmware by vphone-cli fw prepare and copied into the VM during JB installation. No Apple GPU binary is stored in this directory, the archive, or the shipped app.

See Research/Guest/virtual_camera_transport.md for the camera transport validation and the hook installation prerequisites.