Files
vphone-cli/research/boot_launchd_data_volume_lookup_analysis.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

161 lines
5.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 errors 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