Skip to content

Commit 2e6ecee

Browse files
rob-pclaude
andcommitted
Mount and unlock Data volume before detection in Recovery Mode
Ports the core fix from upstream PR assafdori#144 onto bypass-mdm-enhanced.sh: APFS volumes aren't auto-mounted in Recovery, and on modern FileVault-encrypted Macs the old inline unlock never ran because detect_volumes errored out first when /Volumes/Data didn't exist. Adds a mount_data_volume() step that resolves the disk identifier, detects FileVault/Locked status, unlocks via passphrase with a 3-attempt retry, and falls back across four mount strategies. Also redirects warn/success/info to stderr so status messages no longer leak into command-substitution captures. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 0d298a6 commit 2e6ecee

1 file changed

Lines changed: 132 additions & 9 deletions

File tree

bypass-mdm-enhanced.sh

Lines changed: 132 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,22 @@ error_exit() {
1919

2020
# Warning function
2121
warn() {
22-
echo -e "${YEL}WARNING: $1${NC}"
22+
echo -e "${YEL}WARNING: $1${NC}" >&2
2323
}
2424

2525
# Success function
2626
success() {
27-
echo -e "${GRN}$1${NC}"
27+
echo -e "${GRN}$1${NC}" >&2
2828
}
2929

3030
# Info function
3131
info() {
32-
echo -e "${BLU}$1${NC}"
32+
echo -e "${BLU}$1${NC}" >&2
33+
}
34+
35+
# Debug function
36+
debug() {
37+
echo -e "${PUR}[DEBUG] $1${NC}" >&2
3338
}
3439

3540
# Validation function for username
@@ -94,6 +99,124 @@ find_available_uid() {
9499
return 1
95100
}
96101

102+
# Mount (and if needed, FileVault-unlock) the Data volume in Recovery Mode.
103+
# APFS volumes are not auto-mounted in Recovery, and on modern Macs the Data
104+
# volume is typically FileVault-encrypted. Must run before detect_volumes.
105+
mount_data_volume() {
106+
info "=== MOUNT DATA VOLUME STEP ==="
107+
108+
if [ -d "/Volumes/Data" ]; then
109+
info "Data volume already mounted at /Volumes/Data"
110+
return 0
111+
fi
112+
113+
debug "Data volume not found at /Volumes/Data, need to mount it"
114+
115+
local data_volume_id=""
116+
info "Searching for 'Data' volume in diskutil..."
117+
118+
data_volume_id=$(diskutil list | grep "APFS Volume" | grep "Data" | grep "disk3" | awk '{print $NF}' | head -1)
119+
debug "After searching on disk3: data_volume_id='$data_volume_id'"
120+
121+
if [ -z "$data_volume_id" ]; then
122+
debug "Not found on disk3, searching all disks..."
123+
data_volume_id=$(diskutil list | grep "APFS Volume" | grep "Data" | awk '{print $NF}' | head -1)
124+
debug "After searching all disks: data_volume_id='$data_volume_id'"
125+
fi
126+
127+
if [ -z "$data_volume_id" ]; then
128+
error_exit "Could not find 'Data' volume identifier in diskutil output"
129+
fi
130+
131+
info "Found data volume identifier: $data_volume_id"
132+
133+
local volume_status
134+
volume_status=$(diskutil apfs list 2>&1 | grep -A 15 "Volume $data_volume_id" | head -20)
135+
debug "Volume status:\n$volume_status"
136+
137+
if echo "$volume_status" | grep -E "(FileVault.*Yes|Locked.*Yes)" > /dev/null; then
138+
warn "FileVault-encrypted Data volume detected — unlock required"
139+
140+
local unlock_success=0
141+
local unlock_attempts=0
142+
while [ $unlock_success -eq 0 ] && [ $unlock_attempts -lt 3 ]; do
143+
unlock_attempts=$((unlock_attempts + 1))
144+
echo "" >&2
145+
if [ $unlock_attempts -eq 1 ]; then
146+
echo -e "${YEL}Enter your FileVault password (the one used at startup)${NC}" >&2
147+
read -s -p "Password: " filevault_pass
148+
else
149+
echo -e "${RED}Password incorrect. Attempt $unlock_attempts of 3${NC}" >&2
150+
read -s -p "Try again: " filevault_pass
151+
fi
152+
echo "" >&2
153+
154+
local unlock_output
155+
unlock_output=$(diskutil apfs unlockVolume "$data_volume_id" -passphrase "$filevault_pass" 2>&1)
156+
if [ $? -eq 0 ]; then
157+
success "Volume unlocked"
158+
unlock_success=1
159+
else
160+
warn "Unlock failed: $unlock_output"
161+
fi
162+
done
163+
164+
if [ $unlock_success -eq 0 ]; then
165+
error_exit "Failed to unlock volume after $unlock_attempts attempts"
166+
fi
167+
fi
168+
169+
info "Mounting data volume..."
170+
local mount_output
171+
172+
# Method 1: standard mount
173+
mount_output=$(diskutil mount "$data_volume_id" 2>&1)
174+
debug "Method 1 (mount) output: $mount_output"
175+
if echo "$mount_output" | grep -q "mounted"; then
176+
sleep 1
177+
if [ -d "/Volumes/Data" ]; then
178+
success "Data volume mounted"
179+
return 0
180+
fi
181+
fi
182+
183+
# Method 2: mountDisk
184+
mount_output=$(diskutil mountDisk "$data_volume_id" 2>&1)
185+
debug "Method 2 (mountDisk) output: $mount_output"
186+
if echo "$mount_output" | grep -q "mounted"; then
187+
sleep 1
188+
if [ -d "/Volumes/Data" ]; then
189+
success "Data volume mounted (method 2)"
190+
return 0
191+
fi
192+
fi
193+
194+
# Method 3: explicit mount point
195+
mkdir -p /Volumes/Data 2>/dev/null
196+
mount_output=$(diskutil mount -mountPoint /Volumes/Data "$data_volume_id" 2>&1)
197+
debug "Method 3 (explicit mountPoint) output: $mount_output"
198+
if echo "$mount_output" | grep -q "mounted"; then
199+
sleep 1
200+
if [ -d "/Volumes/Data" ]; then
201+
success "Data volume mounted (method 3)"
202+
return 0
203+
fi
204+
fi
205+
206+
# Method 4: raw mount(8)
207+
local device_path="/dev/$data_volume_id"
208+
if [ -e "$device_path" ]; then
209+
mount_output=$(mount -t apfs "$device_path" /Volumes/Data 2>&1)
210+
if [ $? -eq 0 ] && [ -d "/Volumes/Data" ]; then
211+
success "Data volume mounted (method 4)"
212+
return 0
213+
fi
214+
debug "Method 4 failed: $mount_output"
215+
fi
216+
217+
error_exit "All mount methods failed. Could not mount data volume."
218+
}
219+
97220
# Function to detect system volumes with multiple fallback strategies (Restored Original)
98221
detect_volumes() {
99222
local system_vol=""
@@ -148,6 +271,12 @@ detect_volumes() {
148271
echo "$system_vol|$data_vol"
149272
}
150273

274+
# Mount & unlock the Data volume first (Recovery Mode doesn't auto-mount APFS)
275+
mount_data_volume
276+
if [ ! -d "/Volumes/Data" ]; then
277+
error_exit "Mount process reported success but /Volumes/Data does not exist"
278+
fi
279+
151280
# Detect volumes at startup
152281
volume_info=$(detect_volumes)
153282
system_volume=$(echo "$volume_info" | cut -d'|' -f1)
@@ -175,12 +304,6 @@ select opt in "${options[@]}"; do
175304
echo -e "${YEL}═══════════════════════════════════════${NC}"
176305
echo ""
177306

178-
# FileVault Check (Integrated from decryption research)
179-
if ! diskutil mount "$data_volume" 2>/dev/null; then
180-
warn "Data volume is locked (FileVault). Please enter your login password to unlock."
181-
diskutil apfs unlockVolume "$data_volume" || error_exit "Failed to unlock Data volume."
182-
fi
183-
184307
# Normalize data volume name if needed
185308
if [ "$data_volume" != "Data" ]; then
186309
info "Renaming data volume to 'Data' for consistency..."

0 commit comments

Comments
 (0)