Merge pull request #13047 from AFOliveira/fix/factory-reset-packaged-path-20260923
Pin factory-reset elevation to the packaged command
This commit is contained in:
3 files changed
+87
-1
No files matched your search
@@ -29,17 +29,25 @@
|
||||
set -euo pipefail
|
||||
|
||||
PROVISIONING_DIR=/var/lib/omarchy/provisioning
|
||||
PACKAGED_PATH=/usr/bin/omarchy-system-factory-reset
|
||||
OMARCHY_PATH="${OMARCHY_PATH:-/usr/share/omarchy}"
|
||||
TOP_MNT=/run/omarchy-system-factory-reset/top
|
||||
NEXT_NAME=@omarchy-reset-next
|
||||
LOG_FILE=/var/log/omarchy-system-factory-reset.log
|
||||
|
||||
# Never replace a newer checkout reset with a different installed implementation.
|
||||
if ! /usr/bin/cmp -s -- "${BASH_SOURCE[0]}" "$PACKAGED_PATH"; then
|
||||
echo "Factory reset differs from the installed command. Install the matching Omarchy package before resetting." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Self-elevate so the menu entry (and a bare shell invocation) need no sudo
|
||||
# prefix. The caller's gum theme vars are forwarded as `env` arguments rather
|
||||
# than via `sudo -E`, so styling survives even under an env_reset sudoers.
|
||||
# Always elevate the packaged copy, including when invoked from a dev checkout.
|
||||
if (( EUID != 0 )); then
|
||||
mapfile -t gum_env < <(env | grep '^GUM_' || true)
|
||||
exec sudo env "${gum_env[@]}" "$0" "$@"
|
||||
exec sudo env "${gum_env[@]}" "$PACKAGED_PATH" "$@"
|
||||
fi
|
||||
|
||||
export PATH="$OMARCHY_PATH/bin:$PATH"
|
||||
|
||||
@@ -198,6 +198,8 @@ yet and silently runs the packaged copy of one it has. The drop-in is validated
|
||||
with `visudo -c` before install and removed by `omarchy-dev-unlink`; unlike
|
||||
`/etc/omarchy.conf`, it takes effect without a reboot.
|
||||
|
||||
Factory reset is an exception: it always self-elevates through `/usr/bin/omarchy-system-factory-reset` and refuses a checkout copy that differs from the installed command, including when invoked with `sudo`. Install the matching package before resetting so a newer checkout cannot silently hand off to older account-scrubbing code.
|
||||
|
||||
## Runtime finalization (`omarchy-provision-user`)
|
||||
|
||||
Runs once per user. It does **not** copy `~/.config/**`, `~/.bashrc`,
|
||||
|
||||
Executable
+76
@@ -0,0 +1,76 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
source "$(dirname "$0")/base-test.sh"
|
||||
|
||||
if (( EUID == 0 )); then
|
||||
skip "factory-reset self-elevation requires an unprivileged caller"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
tmp=$(mktemp -d)
|
||||
trap 'rm -rf "$tmp"' EXIT
|
||||
mkdir -p "$tmp/bin" "$tmp/checkout with spaces"
|
||||
|
||||
# Exercise the real startup, but never include the destructive reset body.
|
||||
awk '
|
||||
/^export PATH=/ { found = 1; print "exit 99"; exit }
|
||||
{ print }
|
||||
END { if (!found) exit 1 }
|
||||
' "$ROOT/bin/omarchy-system-factory-reset" >"$tmp/checkout with spaces/reset"
|
||||
grep -Fxq 'PACKAGED_PATH=/usr/bin/omarchy-system-factory-reset' "$ROOT/bin/omarchy-system-factory-reset" || fail "factory reset pins the packaged path"
|
||||
sed -i "s|^PACKAGED_PATH=.*|PACKAGED_PATH=\"$tmp/packaged-reset\"|" "$tmp/checkout with spaces/reset"
|
||||
cp "$tmp/checkout with spaces/reset" "$tmp/packaged-reset"
|
||||
chmod +x "$tmp/checkout with spaces/reset" "$tmp/packaged-reset"
|
||||
ln -s "$tmp/checkout with spaces/reset" "$tmp/reset-link"
|
||||
|
||||
cat >"$tmp/bin/sudo" <<'SH'
|
||||
#!/bin/bash
|
||||
printf '%s\0' "$@" >"$CALL_LOG"
|
||||
exit "${SUDO_STATUS:-0}"
|
||||
SH
|
||||
chmod +x "$tmp/bin/sudo"
|
||||
|
||||
args=('argument with spaces' '' '--flag' '$(touch should-not-run)' $'two\nlines')
|
||||
expected=(env 'GUM_INPUT_PROMPT=Reset this computer? ' "$tmp/packaged-reset" "${args[@]}")
|
||||
for invocation in "$tmp/checkout with spaces/reset" './checkout with spaces/reset' "$tmp/reset-link" "$tmp/packaged-reset" reset; do
|
||||
for status in 0 1 127; do
|
||||
actual_status=0
|
||||
(cd "$tmp" && env -i HOME="$tmp" PATH="$tmp/bin:$tmp/checkout with spaces:/usr/bin:/bin" \
|
||||
OMARCHY_PATH="$tmp/checkout with spaces" PACKAGED_PATH="$tmp/wrong-target" \
|
||||
GUM_INPUT_PROMPT='Reset this computer? ' CALL_LOG="$tmp/call" SUDO_STATUS="$status" \
|
||||
"$invocation" "${args[@]}") || actual_status=$?
|
||||
(( actual_status == status )) || fail "elevation status is preserved for $invocation"
|
||||
mapfile -d '' -t actual <"$tmp/call"
|
||||
(( ${#actual[@]} == ${#expected[@]} )) || fail "elevation argument count is preserved"
|
||||
for i in "${!expected[@]}"; do
|
||||
[[ ${actual[i]} == "${expected[i]}" ]] || fail "elevation argument $i is preserved for $invocation"
|
||||
done
|
||||
[[ ! -e $tmp/should-not-run ]] || fail "caller arguments were executed"
|
||||
done
|
||||
pass "factory reset pins $invocation to the packaged command and preserves arguments, styling and status"
|
||||
done
|
||||
|
||||
if unshare -Ur true >/dev/null 2>&1; then
|
||||
status=0
|
||||
unshare -Ur "$tmp/packaged-reset" || status=$?
|
||||
(( status == 99 )) || fail "matching root invocation did not reach the guarded body"
|
||||
pass "matching packaged root invocation reaches the reset body"
|
||||
else
|
||||
skip "user namespaces unavailable; root invocation coverage"
|
||||
fi
|
||||
|
||||
# A checkout must not hand off to older installed code, even with explicit sudo.
|
||||
printf '\n# older packaged copy\n' >>"$tmp/packaged-reset"
|
||||
rm -f "$tmp/call"
|
||||
if CALL_LOG="$tmp/call" PATH="$tmp/bin:/usr/bin:/bin" "$tmp/reset-link" >"$tmp/mismatch" 2>&1; then
|
||||
fail "mismatched reset implementation was accepted"
|
||||
fi
|
||||
[[ ! -e $tmp/call ]] || fail "mismatched reset requested elevation"
|
||||
grep -Fq 'Install the matching Omarchy package' "$tmp/mismatch" || fail "mismatch explains recovery"
|
||||
if unshare -Ur true >/dev/null 2>&1; then
|
||||
status=0
|
||||
unshare -Ur "$tmp/reset-link" >"$tmp/root-mismatch" 2>&1 || status=$?
|
||||
(( status == 1 )) || fail "root invocation did not refuse mismatch before the reset body"
|
||||
pass "root checkout invocation refuses a mismatched packaged reset"
|
||||
fi
|
||||
pass "mismatched checkout refuses before elevation"
|
||||
Reference in new issue
Block a user