forked from Manuel/meeting-assistant
189 lines
8.1 KiB
Bash
189 lines
8.1 KiB
Bash
#!/bin/bash
|
|
# Existing macOS Recovery/launchd runtime hook; never installs or erases anything.
|
|
set -u
|
|
PATH="/usr/bin:/bin:/usr/sbin:/sbin"
|
|
export PATH
|
|
PROOF_TOKEN="@@PROOF_TOKEN@@"
|
|
STATE_DIR="/Volumes/installstate"
|
|
PROOF_LOG="$STATE_DIR/proof.log"
|
|
RESULT="$STATE_DIR/result.json"
|
|
EXPECTED_BYTES=68719476736
|
|
MAX_LOG_BYTES=4194304
|
|
os_version=""
|
|
architecture=""
|
|
uid=-1
|
|
system_exit=-1
|
|
arbitration_exit=-1
|
|
recovery_exit=-1
|
|
disk_list_exit=-1
|
|
selected_disk=""
|
|
disk_bytes=0
|
|
|
|
count=0
|
|
while [ ! -d "$STATE_DIR" ] && (( count < 120 )); do
|
|
/sbin/mount_9p installstate >/dev/null 2>&1 || :
|
|
count=$((count + 1))
|
|
sleep 1
|
|
done
|
|
[ -d "$STATE_DIR" ] || exit 1
|
|
: > "$PROOF_LOG" || exit 1
|
|
rm -f "$RESULT" "$RESULT.tmp"
|
|
printf '[proof-token] %s\n' "$PROOF_TOKEN" >> "$PROOF_LOG"
|
|
|
|
finish() {
|
|
local success="$1" reason="$2"
|
|
printf '[proof-result] %s: %s\n' "$success" "$reason" >> "$PROOF_LOG"
|
|
printf '{"token":"%s","success":%s,"reason":"%s","osVersion":"%s","architecture":"%s","uid":%s,"systemExit":%s,"diskArbitrationExit":%s,"recoveryExit":%s,"diskListExit":%s,"disk":"%s","diskBytes":%s,"readOnly":false}\n' \
|
|
"$PROOF_TOKEN" "$success" "$reason" "$os_version" "$architecture" "$uid" \
|
|
"$system_exit" "$arbitration_exit" "$recovery_exit" "$disk_list_exit" \
|
|
"$selected_disk" "$disk_bytes" > "$RESULT.tmp"
|
|
/bin/mv -f "$RESULT.tmp" "$RESULT" || exit 1
|
|
# Keep the service alive for the bounded host diagnostic to capture evidence.
|
|
while :; do sleep 60; done
|
|
}
|
|
|
|
run_command() {
|
|
local name="$1"
|
|
shift
|
|
local process timer sleeper exit_code started observer=""
|
|
LAST_OUTPUT="/tmp/native-diagnostic-$name.out"
|
|
printf '\n[proof-command] %s:' "$name" >> "$PROOF_LOG"
|
|
printf ' %s' "$@" >> "$PROOF_LOG"
|
|
printf '\n' >> "$PROOF_LOG"
|
|
started=$SECONDS
|
|
"$@" > "$LAST_OUTPUT" 2>&1 &
|
|
process=$!
|
|
printf '[proof-start] %s child=%s shell=%s parent=%s seconds=%s\n' "$name" "$process" "$$" "$PPID" "$started" >> "$PROOF_LOG"
|
|
(
|
|
trap 'kill "$sleeper" 2>/dev/null || :; exit 0' TERM INT
|
|
sleep 45 &
|
|
sleeper=$!
|
|
wait "$sleeper"
|
|
printf '[proof-timeout] %s child=%s elapsed=%ss signal=TERM\n' "$name" "$process" "$((SECONDS - started))" >> "$PROOF_LOG"
|
|
kill -TERM "$process" 2>/dev/null || :
|
|
sleep 2 & sleeper=$!; wait "$sleeper"
|
|
kill -KILL "$process" 2>/dev/null || :
|
|
) &
|
|
timer=$!
|
|
if [[ "$name" = platform || "$name" = platform-warm ]]; then
|
|
# Observers never extend the independent 45-second command deadline.
|
|
(
|
|
local sample_pid="" sample_timer="" pause_pid="" pause sample_exit
|
|
trap 'kill -KILL "$sample_pid" 2>/dev/null || :; kill -TERM "$sample_timer" "$pause_pid" 2>/dev/null || :; exit 0' TERM INT
|
|
for pause in 10 15; do
|
|
sleep "$pause" & pause_pid=$!; wait "$pause_pid"
|
|
printf '[proof-process] %s child=%s elapsed=%ss fields=pid,ppid,stat,cpu-time,elapsed,cpu-percent,wchan,comm\n' "$name" "$process" "$((SECONDS - started))" >> "$PROOF_LOG"
|
|
/bin/ps -p "$process" -o pid=,ppid=,stat=,time=,etime=,pcpu=,wchan=,comm= >> "$PROOF_LOG" 2>&1 &
|
|
sample_pid=$!
|
|
(
|
|
local sample_sleeper=""
|
|
trap 'kill "$sample_sleeper" 2>/dev/null || :; exit 0' TERM INT
|
|
sleep 5 & sample_sleeper=$!; wait "$sample_sleeper"
|
|
kill -KILL "$sample_pid" 2>/dev/null || :
|
|
) & sample_timer=$!
|
|
wait "$sample_pid"; sample_exit=$?
|
|
kill -TERM "$sample_timer" 2>/dev/null || :; wait "$sample_timer" 2>/dev/null || :
|
|
printf '[proof-process-exit] %s %s\n' "$name" "$sample_exit" >> "$PROOF_LOG"
|
|
sample_pid=""; sample_timer=""; pause_pid=""
|
|
done
|
|
) & observer=$!
|
|
fi
|
|
wait "$process"
|
|
exit_code=$?
|
|
kill -TERM "$timer" 2>/dev/null || :
|
|
wait "$timer" 2>/dev/null || :
|
|
if [ -n "$observer" ]; then
|
|
kill -TERM "$observer" 2>/dev/null || :
|
|
wait "$observer" 2>/dev/null || :
|
|
fi
|
|
/usr/bin/tail -c 524288 "$LAST_OUTPUT" >> "$PROOF_LOG"
|
|
printf '\n[proof-duration] %s child=%s elapsed=%ss\n' "$name" "$process" "$((SECONDS - started))" >> "$PROOF_LOG"
|
|
printf '\n[proof-exit] %s\n' "$exit_code" >> "$PROOF_LOG"
|
|
LAST_EXIT="$exit_code"
|
|
local size
|
|
size=$(/usr/bin/stat -f '%z' "$PROOF_LOG" 2>/dev/null || printf '0')
|
|
(( size <= MAX_LOG_BYTES )) || finish false diagnostic_log_budget_exceeded
|
|
return 0
|
|
}
|
|
|
|
# Collect cheap native identity/context before the first framework-dependent probe.
|
|
run_command kernel /usr/bin/uname -a
|
|
(( LAST_EXIT == 0 )) || finish false uname_failed
|
|
run_command architecture /usr/bin/uname -m
|
|
(( LAST_EXIT == 0 )) || finish false architecture_probe_failed
|
|
architecture=$(cat "$LAST_OUTPUT")
|
|
[ "$architecture" = x86_64 ] || finish false unexpected_guest_architecture
|
|
run_command account /usr/bin/id
|
|
run_command uid /usr/bin/id -u
|
|
(( LAST_EXIT == 0 )) || finish false uid_probe_failed
|
|
uid=$(cat "$LAST_OUTPUT")
|
|
[ "$uid" = 0 ] || finish false recovery_account_not_root
|
|
run_command bootargs /usr/sbin/sysctl kern.bootargs
|
|
run_command cpu /usr/sbin/sysctl machdep.cpu.brand_string machdep.cpu.features machdep.cpu.leaf7_features
|
|
run_command parent /bin/ps -p "$$" -p "$PPID" -o pid=,ppid=,comm=
|
|
run_command processes /bin/ps -axo pid,ppid,comm
|
|
run_command platform /usr/bin/sw_vers
|
|
platform_exit="$LAST_EXIT"
|
|
run_command system /bin/launchctl print system
|
|
system_exit="$LAST_EXIT"
|
|
run_command arbitration /bin/launchctl print system/com.apple.diskarbitrationd
|
|
arbitration_exit="$LAST_EXIT"
|
|
run_command recovery /bin/launchctl print system/com.apple.recoveryosd
|
|
recovery_exit="$LAST_EXIT"
|
|
if (( platform_exit != 0 )); then
|
|
printf '[proof-retry] sw_vers once after native service context; same 45-second deadline\n' >> "$PROOF_LOG"
|
|
run_command platform-warm /usr/bin/sw_vers
|
|
platform_exit="$LAST_EXIT"
|
|
fi
|
|
(( platform_exit == 0 )) || finish false sw_vers_failed
|
|
run_command version /usr/bin/sw_vers -productVersion
|
|
(( LAST_EXIT == 0 )) || finish false product_version_failed
|
|
os_version=$(cat "$LAST_OUTPUT")
|
|
[[ "$os_version" =~ ^[0-9]+\.[0-9]+(\.[0-9]+)?$ ]] || finish false product_version_invalid
|
|
(( ${os_version%%.*} >= 14 )) || finish false unsupported_macos_version
|
|
|
|
# Bound readiness independently of the host's 40-minute overall deadline.
|
|
readiness_start=$SECONDS
|
|
attempt=0
|
|
while (( SECONDS - readiness_start < 600 )); do
|
|
attempt=$((attempt + 1))
|
|
printf '\n[readiness-attempt] %s\n' "$attempt" >> "$PROOF_LOG"
|
|
run_command disks /usr/sbin/diskutil list physical
|
|
disk_list_exit="$LAST_EXIT"
|
|
if (( disk_list_exit == 0 )); then
|
|
disk_list=$(cat "$LAST_OUTPUT")
|
|
candidates=0
|
|
while IFS= read -r disk; do
|
|
[ -n "$disk" ] || continue
|
|
run_command "info-$disk" /usr/sbin/diskutil info "/dev/$disk"
|
|
(( LAST_EXIT == 0 )) || continue
|
|
info=$(cat "$LAST_OUTPUT")
|
|
if printf '%s\n' "$info" | grep -Eq '^[[:space:]]*(Read-Only (Media|Device)|(Media|Device) Read-Only):[[:space:]]*Yes'; then
|
|
continue
|
|
fi
|
|
printf '%s\n' "$info" | grep -Eq '^[[:space:]]*(Read-Only (Media|Device)|(Media|Device) Read-Only):[[:space:]]*No' || continue
|
|
size=$(printf '%s\n' "$info" | sed -nE 's/^[[:space:]]*Disk Size:.*\(([0-9]+) Bytes\).*/\1/p' | head -n 1)
|
|
[[ "$size" =~ ^[0-9]+$ ]] || continue
|
|
(( size == EXPECTED_BYTES )) || continue
|
|
candidates=$((candidates + 1))
|
|
selected_disk="/dev/$disk"
|
|
disk_bytes="$size"
|
|
printf '[writable-target] %s %s bytes\n' "$selected_disk" "$disk_bytes" >> "$PROOF_LOG"
|
|
done < <(printf '%s\n' "$disk_list" | sed -nE 's#^/dev/(disk[0-9]+).*#\1#p')
|
|
(( candidates <= 1 )) || finish false ambiguous_writable_64g_disks
|
|
if (( candidates == 1 )); then
|
|
# Re-probe live launchd domains after disk readiness, preserving native exits.
|
|
run_command system_ready /bin/launchctl print system
|
|
system_exit="$LAST_EXIT"
|
|
run_command arbitration_ready /bin/launchctl print system/com.apple.diskarbitrationd
|
|
arbitration_exit="$LAST_EXIT"
|
|
run_command recovery_ready /bin/launchctl print system/com.apple.recoveryosd
|
|
recovery_exit="$LAST_EXIT"
|
|
(( system_exit == 0 && arbitration_exit == 0 && recovery_exit == 0 )) || finish false service_domain_not_ready
|
|
finish true native_recovery_and_writable_64g_disk_ready
|
|
fi
|
|
fi
|
|
sleep 5
|
|
done
|
|
finish false disk_management_or_writable_target_not_ready
|