How cfw_install_host.sh Host-Mounts the CFW Driver Without Running the VM
The cfw_install_host.sh script attaches the VM's Disk.img as a raw disk to the macOS host, mounts the APFS volumes directly, installs the custom firmware files, and flips the boot snapshot—all while the virtual iPhone remains powered off.
The vphone-cli project by Lakr233 provides a lightweight virtual iPhone environment for iOS security research. Understanding how cfw_install_host.sh host-mounts the CFW driver without leaving the VM running enables researchers to perform deterministic, scriptable firmware modifications without booting the guest operating system or managing complex guest-side privileged operations.
How Host-Mode Installation Works
Unlike traditional guest-mode installation that requires the VM to be running, the host-mode workflow implemented in scripts/cfw_install_host.sh operates directly on the virtual disk image. This approach attaches the raw disk image to the macOS host, manipulates the APFS container structure, and updates the boot snapshot offline.
The script follows a strict sequence: validate the environment, attach the disk image as a raw block device, identify the system volume within the APFS container, mount the required volumes to temporary host paths, execute the variant-specific installer, flip the boot snapshot to activate the new firmware, and clean up all resources.
Step-by-Step Execution Flow
Root Privilege Enforcement
The script first ensures it operates with elevated privileges. If not running as root, it re-executes itself using sudo while preserving any SUDO_ASKPASS environment variable for non-interactive deployments.
# From scripts/cfw_install_host.sh lines 37-40
if [ "$(id -u)" != "0" ]; then
exec sudo -A "$0" "$@"
fi
This requirement exists because mounting APFS containers, modifying volume ownership, and writing to the raw disk image require kernel-level access that standard user accounts cannot obtain.
Disk Image Validation
Before attempting any mount operations, the script verifies that the virtual machine is truly powered off. It locates the VM directory and checks for the existence of Disk.img, then confirms no other process is accessing the file using lsof.
# From scripts/cfw_install_host.sh lines 43-46 and 58-60
VM_DIR="${1:-./vm}"
DISK_IMG="$VM_DIR/Disk.img"
if lsof "$DISK_IMG" >/dev/null 2>&1; then
echo "[!] Error: Disk.img is in use. Is the VM running?"
exit 1
fi
This check prevents corruption that would occur if the host attempted to mount a disk image currently in use by a running virtual machine.
Raw Disk Attachment
With the VM confirmed offline, the script attaches the Disk.img file as a raw disk without creating a standard mount point. It uses hdiutil with the CRawDiskImage class specification to expose the underlying block device.
# From scripts/cfw_install_host.sh lines 63-66
BASEDISK=$(hdiutil attach -nomount -imagekey diskimage-class=CRawDiskImage "$DISK_IMG" | \
grep "/dev/disk" | head -1 | awk '{print $1}')
CONT="${BASEDISK}s1"
The -nomount flag ensures the filesystem remains unmounted while the block device becomes available for APFS container operations. The script extracts the first slice (${BASEDISK}s1) as the APFS container reference.
APFS Container Discovery
The script must identify the specific system volume within the APFS container that holds the iOS operating system. It parses diskutil apfs list output to locate the volume marked with the "System (Case-sensitive)" role.
# From scripts/cfw_install_host.sh lines 65-66
SYS=$(diskutil apfs list "$CONT" | grep -A 5 "System (Case-sensitive)" | \
grep "Volume " | head -1 | awk '{print $2}')
This yields two critical variables: CONT (the container device path) and SYS (the system volume identifier), which the variant-specific installers use to target the correct mount points.
Volume Mounting and File Installation
A cleanup function registered with trap ensures temporary mount points are unmounted and the disk is detached on script exit, regardless of success or failure.
# From scripts/cfw_install_host.sh lines 70-76
cleanup() {
umount /private/tmp/cfwhost/mnt* 2>/dev/null || true
hdiutil detach "$BASEDISK" >/dev/null 2>&1 || true
}
trap cleanup EXIT
The script then executes the variant-specific installer (such as cfw_install.sh or cfw_install_dev.sh) inside a subshell that receives the container path via the CFW_HOST_CONTAINER environment variable.
# From scripts/cfw_install_host.sh lines 78-85
(
export CFW_HOST_CONTAINER="$CONT"
bash "$INSTALLER"
)
These installer scripts mount the APFS volumes under /private/tmp/cfwhost/mnt* directories, copy the custom firmware files onto the mounted filesystems, and perform any necessary configuration changes—all on the host side.
Boot Snapshot Manipulation
After file installation completes, the script activates the new firmware by renaming the boot snapshot. It invokes tools/apfs_snap_rename.py to rename the snapshot from com.apple.os.update to the live system volume name.
# From scripts/cfw_install_host.sh lines 89-91
python3 tools/apfs_snap_rename.py "$CONT" "$SYS"
This operation modifies the APFS metadata to point the default boot volume to the newly installed firmware. Because this happens on the host-mounted image, the VM never requires a reboot to apply the changes.
Cleanup and Ownership Restoration
Finally, the script restores file ownership to the original invoking user. This prevents permission-denied errors when subsequent commands like make boot or setup_machine attempt to access the modified VM_DIR.
# From scripts/cfw_install_host.sh lines 102-106
if [ -n "$SUDO_USER" ]; then
chown -R "$SUDO_USER" "$VM_DIR"
fi
The cleanup trap ensures the raw disk image is properly detached and temporary mount points are removed, leaving the VM in a clean, offline state ready for the next boot.
Usage Examples
Install the default experimental variant into the standard ./vm directory:
sudo ./scripts/cfw_install_host.sh
Install a specific jailbreak variant to a custom VM location:
sudo ./scripts/cfw_install_host.sh --variant jb /path/to/custom/vm
Successful execution produces output similar to:
[*] host-mode CFW install: variant=exp vm=/path/to/vphone-cli/vm
[*] attached: container=disk2s2 system=disk2s5
[*] running cfw_install_exp.sh (files placed on host mounts)...
[*] flipping boot snapshot offline (com.apple.os.update -> live volume)...
[+] host-mode CFW install complete. Boot with: make boot
Summary
- Direct disk attachment:
cfw_install_host.shuseshdiutil attach -nomount -imagekey diskimage-class=CRawDiskImageto expose the VM'sDisk.imgas a block device without mounting the filesystem. - Offline APFS manipulation: The script identifies the system volume via
diskutil apfs listand mounts it to temporary host directories under/private/tmp/cfwhost/. - Snapshot-based activation: The Python helper
apfs_snap_rename.pyflips the boot snapshot offline, activating the CFW without requiring a VM reboot. - Safety mechanisms: Process checks via
lsofensure the VM is powered off, while atrapcleanup function guarantees resource release even on script failure. - Permission management: The script elevates to root for block device access, then reverts ownership to
$SUDO_USERto maintain accessibility for subsequent operations.
Frequently Asked Questions
What is the difference between host-mode and guest-mode CFW installation?
Host-mode installation, implemented in cfw_install_host.sh, attaches the VM disk image directly to the macOS host and modifies the filesystem while the VM remains powered off. Guest-mode installation requires the VM to be running and executes installation commands inside the guest operating system. Host-mode is faster, more deterministic, and avoids the complexity of managing privileged operations within the guest environment.
Why does the script require root privileges?
The script requires root access because mounting APFS containers using hdiutil and diskutil requires kernel-level permissions. Additionally, writing to the raw disk image blocks and modifying volume ownership with chown on APFS volumes demand elevated privileges that standard macOS user accounts cannot obtain.
How does the script ensure the VM is not running during installation?
Before attaching the disk image, the script checks for open file handles on Disk.img using the lsof command according to scripts/cfw_install_host.sh lines 58-60. If any process is accessing the image, the script aborts with an error message. This prevents filesystem corruption that would occur if the host and guest simultaneously accessed the same block device.
What happens if the installation process is interrupted?
The script registers a cleanup function with trap EXIT that automatically unmounts any temporary mount points under /private/tmp/cfwhost/ and detaches the raw disk image using hdiutil detach. This ensures that even if the script fails or receives a termination signal, the host does not retain dangling mounts or locked disk images that would prevent subsequent VM operations.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →