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

5.9 KiB
Raw Blame History

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