mirror of
https://github.com/Lakr233/vphone-cli.git
synced 2026-09-05 17:14:28 +00:00
Prefix research patch comparison doc and normalize root markdown names Rename research root markdown files to scoped topic names
161 lines
5.9 KiB
Markdown
161 lines
5.9 KiB
Markdown
# launchd Boot Sequence Analysis (mount-phase-1 / data volume lookup)
|
||
|
||
Date: 2026-03-06
|
||
Target binary in IDA: launchd (Darwin Bootstrapper 7.0.0, libxpc_executables-3089.42.1~6)
|
||
|
||
## Scope
|
||
|
||
This analysis focuses on the log segment:
|
||
|
||
- `mount-phase-1`
|
||
- `failed to lookup data volume - Attribute not found`
|
||
- `mount: data volume missing, but not required in env: 1`
|
||
|
||
and answers where launchd is involved vs where `mount`/APFS is actually failing.
|
||
|
||
## Ground Truth from launchd (IDA)
|
||
|
||
### 1) Boot task source is embedded plist in launchd
|
||
|
||
- Embedded config plist string contains:
|
||
- `Boot` dictionary
|
||
- `mount-phase-1` -> `Program=/sbin/mount`, `ProgramArguments=["mount","-P","1"]`
|
||
- `data-protection` -> `Program=/usr/libexec/init_data_protection`, `CSIdentityOverride=com.apple.seputil`
|
||
|
||
### 2) Boot task dictionary wiring
|
||
|
||
- `sub_10004D978`:
|
||
- reads launchd `__TEXT,__config`
|
||
- extracts `Boot` dictionary
|
||
- stores into `qword_10007F138`
|
||
|
||
- `sub_100047B94`:
|
||
- lookup task from `qword_10007F138`
|
||
- runs gate check (`sub_100047C8C`)
|
||
- executes task by calling `sub_100047DD0`
|
||
|
||
### 3) Boot sequence order (relevant slice)
|
||
|
||
- `start` -> `sub_1000489A4` -> async `sub_100048590`
|
||
- `sub_100048590` task order includes:
|
||
- `mount-phase-1`
|
||
- `data-protection`
|
||
- `finish-obliteration`
|
||
- `detect-installed-roots`
|
||
- `mount-phase-2`
|
||
|
||
### 4) Task execution and failure handling
|
||
|
||
- `sub_100047DD0`:
|
||
- logs `Doing boot task`
|
||
- `posix_spawnp()` actual executable
|
||
- for non-async tasks waits via `sub_100049180`
|
||
|
||
- `sub_100049180`:
|
||
- checks exit status
|
||
- if `RequireSuccess=true` and exit is failure -> calls `sub_100048D0C`
|
||
|
||
- `sub_100048D0C`:
|
||
- logs `Boot task failed: %s`
|
||
- logs `Panicking in 3 seconds.`
|
||
- then panics
|
||
|
||
## Key Conclusion: where the quoted error originates
|
||
|
||
`failed to lookup data volume - Attribute not found` is **not** generated by launchd internals.
|
||
|
||
In this path, launchd is only the orchestrator:
|
||
|
||
1. launchd runs `/sbin/mount -P 1` for `mount-phase-1`
|
||
2. `mount` prints `failed to lookup data volume...`
|
||
3. launchd only sees child exit result, then decides whether to panic based on `RequireSuccess`
|
||
|
||
So this error’s primary fault domain is in `mount` + APFS/IOKit interactions, not in launchd task scheduler code.
|
||
|
||
## `mount -P 1` call chain (IDA-verified)
|
||
|
||
Target binary: `research/artifacts/launchd_23B85/mount.from_vm_disk.current`
|
||
|
||
- `start` @ `0x100003DC8`
|
||
- phase path calls `sub_100003480(&env)` then `sub_100003674()`
|
||
- `sub_100003480` @ `0x100003480`
|
||
- reads `IODeviceTree:/filesystems/fstab` property `os_env_type`
|
||
- calls `APFSContainerGetBootDevice(&CFString)`
|
||
- builds `/dev/<boot-container>` string in global buffer
|
||
- `sub_100003674` @ `0x100003674`
|
||
- calls `APFSVolumeRoleFind(<bootdev>, 0x40, &CFArray)`
|
||
- on non-zero return:
|
||
- `fprintf("%sfailed to lookup data volume - %s\n", ..., strerror(ret & 0x3fff))`
|
||
- if single match, converts CFString -> data volume path
|
||
|
||
Important:
|
||
|
||
- `0x40` is the queried role selector in this build.
|
||
- `Attribute not found` corresponds to `ENOATTR` (`93`) after `ret & 0x3fff`.
|
||
- phase-1 can continue with warning, but this often cascades into `data-protection` failure in your failing trace set.
|
||
|
||
## Updated Causality (with new control evidence)
|
||
|
||
User-provided control result:
|
||
|
||
- `cfw_install` (without JB extras) reproduces the same failure.
|
||
- TXM path is known-good in this setup.
|
||
|
||
Implication:
|
||
|
||
- JB-only userspace deltas are no longer primary suspects for this error.
|
||
- Current highest-confidence differentiator is kernel state/patch delta.
|
||
|
||
## Plausible causes (re-ranked)
|
||
|
||
### A. kernel-side causes (highest probability now)
|
||
|
||
1. APFS role/device lookup path is denied/altered by kernel policy path for `mount` (`IOUC AppleAPFSUserClient ... MACF` class of failure).
|
||
2. Kernel APFS patch interaction causes role metadata read path to return "attribute not found".
|
||
3. Kernel patch ordering or overlap in `fw_patch_jb` modifies behavior that minimal/non-JB flow does not.
|
||
|
||
### B. mount userspace path causes (still relevant, but secondary to A)
|
||
|
||
1. `mount -P 1` phase logic expects Data role metadata that is unavailable under current kernel behavior.
|
||
2. Userspace APFS query path receives transformed errno/status from kernel and prints attribute-missing message.
|
||
|
||
### C. launchd-level causes (currently de-prioritized)
|
||
|
||
1. launchd task definition mismatch.
|
||
2. spawn-level failures before mount logic.
|
||
3. task gating differences.
|
||
|
||
These are less consistent with the new control result and with observed mount-origin log text.
|
||
|
||
## Practical meaning
|
||
|
||
- For this failure, launchd reverse already gives enough certainty that launchd is orchestrator only.
|
||
- Next decisive work should move to APFS userspace API return-site tracing and corresponding kernel handlers.
|
||
- Detailed `mount -P 1` failure/hang matrix is documented in:
|
||
- `research/boot_mount_phase1_failure_matrix.md`
|
||
|
||
## Most likely kernel-side silent-fail line (current ranking)
|
||
|
||
1. `APFSVolumeRoleFind` path reaches APFS userclient method and gets transformed deny/error (most consistent with `IOUC AppleAPFSUserClient failed MACF ... mount` history).
|
||
2. Base APFS entitlement bypass patch (`patch_apfs_get_dev_by_role_entitlement`, patch #16) matched the wrong deny branch or altered control flow for role lookup.
|
||
3. Base sandbox-op stubs (mount/vnode related) hit an unintended target due ops-table drift.
|
||
|
||
Lower probability for this exact string:
|
||
|
||
- launchd plist/task ordering itself
|
||
- fstab format/ramdisk missing (would produce different dominant signatures)
|
||
|
||
## Artifact notes
|
||
|
||
Current extracted launchd sample (for reproducible local reference):
|
||
|
||
- `research/artifacts/launchd_23B85/launchd.from_vm_disk.current`
|
||
- sha256: `411d730c95d99a088e94b673eff3fa73d6d3cc778b24b476cd0b7866cd037443`
|
||
- `research/artifacts/launchd_23B85/launchd.plist.from_vm_disk.current`
|
||
- sha256: `dc972e30220b3e9e8323d23ce4a4737d849893dd79e305693de902ff65ddacab`
|
||
|
||
Observed in this sample:
|
||
|
||
- no `/cores/launchdhook.dylib` load command
|
||
- launchd embedded boot task plist present and readable
|