Install the separately owned firmware aliases through the package helper so stock firmware updates and stable refreshes retain them. Use a distinct migration to reach machines with the prior migration completed and preserve the reboot prompt until reboot. Restore the generic updater and leave display quirks to the kernel. Co-Authored-By: Codex GPT-6.1-Sol XHigh <noreply@openai.com>
149 lines
5.4 KiB
Bash
149 lines
5.4 KiB
Bash
#!/bin/bash
|
|
|
|
# Test the real orchestration with fixed privileged paths redirected to harmless
|
|
# stand-ins. No host sudo, package transaction, namespace root, or exploit runs.
|
|
boundary_tmp=$(mktemp -d)
|
|
trap 'rm -rf "$boundary_tmp"' EXIT
|
|
export SUDO_TEST_ROOT="$boundary_tmp/omarchy"
|
|
export SUDO_TEST_LOG="$boundary_tmp/events"
|
|
export SUDO_TEST_CACHE="$boundary_tmp/cache"
|
|
export OMARCHY_PATH="$SUDO_TEST_ROOT"
|
|
export SUDO_TEST_HOME="$boundary_tmp/home"
|
|
mkdir -p "$SUDO_TEST_HOME"
|
|
mkdir -p "$SUDO_TEST_ROOT/bin" "$SUDO_TEST_ROOT/mock" "$SUDO_TEST_ROOT/default/omarchy/sudo-no-update"
|
|
: >"$SUDO_TEST_LOG"
|
|
|
|
copy_boundary_file() {
|
|
python3 - "$ROOT" "$SUDO_TEST_ROOT" "$1" <<'PY'
|
|
import sys
|
|
from pathlib import Path
|
|
source, target, name = map(Path,sys.argv[1:])
|
|
p=target/name
|
|
p.parent.mkdir(parents=True,exist_ok=True)
|
|
s=(source/name).read_text().replace('$HOME', '$SUDO_TEST_HOME')
|
|
for command in ['sudo','pkexec','pacman','omarchy-pkg-missing','systemd-inhibit','setpriv','snapper']:
|
|
s=s.replace('/usr/bin/'+command, str(target/'mock'/command))
|
|
s=s.replace('PATH=/usr/bin:/usr/sbin:/bin:/sbin', 'PATH="'+str(target/'bin')+':/usr/bin:/usr/sbin:/bin:/sbin"')
|
|
p.write_text(s)
|
|
p.chmod((source/name).stat().st_mode & 0o777)
|
|
PY
|
|
}
|
|
|
|
copy_boundary_file bin/omarchy-security-functions
|
|
copy_boundary_file bin/omarchy-update-pacman
|
|
copy_boundary_file default/omarchy/sudo-no-update/sudo
|
|
|
|
cat >"$SUDO_TEST_ROOT/mock/sudo" <<'STUB'
|
|
#!/bin/bash
|
|
set -euo pipefail
|
|
printf 'sudo' >>"$SUDO_TEST_LOG"
|
|
printf ' %q' "$@" >>"$SUDO_TEST_LOG"
|
|
printf '\n' >>"$SUDO_TEST_LOG"
|
|
if [[ ${1:-} == "-h" ]]; then
|
|
if [[ ${SUDO_TEST_UNSUPPORTED:-0} == "1" ]]; then
|
|
echo 'usage: sudo [-ABbEHknPS] command'
|
|
else
|
|
echo 'usage: sudo [-ABbEHkNnPS] command'
|
|
fi
|
|
exit 0
|
|
fi
|
|
if [[ ${1:-} == "-k" || ${1:-} == "-K" ]]; then
|
|
[[ ${SUDO_TEST_REVOKE_FAIL:-0} != "1" ]] || exit 1
|
|
/usr/bin/rm -f "$SUDO_TEST_CACHE"
|
|
exit 0
|
|
fi
|
|
if [[ ${1:-} == "-n" && ! -e $SUDO_TEST_CACHE ]]; then
|
|
# Non-interactive sudo cannot authenticate without a cached credential.
|
|
exit 1
|
|
fi
|
|
if [[ ${1:-} == "-N" ]]; then
|
|
shift
|
|
else
|
|
touch "$SUDO_TEST_CACHE"
|
|
fi
|
|
[[ ${SUDO_TEST_SUDO_FAIL:-0} != "1" ]] || exit 1
|
|
background=0
|
|
while (( $# )); do
|
|
case "$1" in
|
|
-N|-n) shift ;;
|
|
-b) background=1; shift ;;
|
|
-v) exit 0 ;;
|
|
-u|--user) shift 2 ;;
|
|
--) shift; break ;;
|
|
*) break ;;
|
|
esac
|
|
done
|
|
(( $# )) || exit 0
|
|
if (( background )); then
|
|
"$@" &
|
|
else
|
|
"$@"
|
|
fi
|
|
STUB
|
|
chmod +x "$SUDO_TEST_ROOT/mock/sudo"
|
|
# The updater's own phases call a bare sudo from its fixed PATH. Resolve it to
|
|
# the stand-in so no test can ever reach the host's sudo.
|
|
ln -s ../mock/sudo "$SUDO_TEST_ROOT/bin/sudo"
|
|
|
|
cat >"$SUDO_TEST_ROOT/bin/test-step" <<'STUB'
|
|
#!/bin/bash
|
|
set -euo pipefail
|
|
step=${0##*/}
|
|
printf 'step:%s %s\n' "$step" "$*" >>"$SUDO_TEST_LOG"
|
|
if [[ $step == "systemd-run" ]]; then
|
|
# omarchy-update-pacman registers the transaction as a PID 1 scope on booted
|
|
# hosts. Run the wrapped command in place so the pacman step still executes.
|
|
while (( $# )) && [[ $1 == -* ]]; do shift; done
|
|
exec "$@"
|
|
fi
|
|
# omarchy update shares one authorization with its post-update hook and mise.
|
|
# Standalone hooks, such as the pre-refresh one, and AUR builds run cold.
|
|
if [[ $step == "omarchy-hook" && ${1:-} == "post-update" ]] || [[ $step == "omarchy-update-mise" ]]; then
|
|
[[ -e $SUDO_TEST_CACHE ]] || exit 94
|
|
elif [[ $step == "omarchy-hook" || $step == "yay" ]]; then
|
|
[[ ! -e $SUDO_TEST_CACHE ]] || exit 91
|
|
fi
|
|
if [[ -n ${SUDO_TEST_REMOVE_WRAPPER_STEP:-} && "$step $*" == $SUDO_TEST_REMOVE_WRAPPER_STEP ]]; then
|
|
# Model a package transaction replacing the running tree with a release
|
|
# that predates the wrapper.
|
|
/usr/bin/rm -f "$OMARCHY_PATH/default/omarchy/sudo-no-update/sudo"
|
|
fi
|
|
if [[ ${SUDO_TEST_FAIL_STEP:-} == "$step" ]]; then
|
|
# Model a misbehaving child leaving state behind, then failing. Cleanup must
|
|
# still revoke it. This never invokes real sudo or exercises a privilege flaw.
|
|
touch "$SUDO_TEST_CACHE"
|
|
exit 17
|
|
fi
|
|
if [[ ${SUDO_TEST_SIGNAL_STEP:-} == "$step" ]]; then
|
|
touch "$SUDO_TEST_CACHE"
|
|
kill -TERM "$PPID"
|
|
exit 0
|
|
fi
|
|
case "$step" in
|
|
omarchy-update-system-pkgs|omarchy-update-keyring|omarchy-snapshot)
|
|
sudo /usr/bin/true
|
|
;;
|
|
pacman) exit 0 ;;
|
|
yay)
|
|
[[ $* == *"--sudo $OMARCHY_PATH/default/omarchy/sudo-no-update/sudo"* ]] || exit 92
|
|
[[ $* == *"--sudoloop=false"* ]] || exit 93
|
|
[[ $(command -v sudo) == "$OMARCHY_PATH/default/omarchy/sudo-no-update/sudo" ]] || exit 95
|
|
;;
|
|
esac
|
|
STUB
|
|
chmod +x "$SUDO_TEST_ROOT/bin/test-step"
|
|
for step in omarchy-update-lock omarchy-update-requires-free-space omarchy-update-confirm omarchy-update-pkg-prune omarchy-snapshot omarchy-update-stay-awake omarchy-update-dev omarchy-update-keyring omarchy-update-system-pkgs omarchy-migrate omarchy-hook omarchy-update-aur-pkgs omarchy-update-mise omarchy-update-orphan-pkgs omarchy-update-analyze-logs omarchy-update-status omarchy-update-restart omarchy-pkg-aur-accessible omarchy-notification-dismiss pacman systemd-run cp yay; do
|
|
ln -s test-step "$SUDO_TEST_ROOT/bin/$step"
|
|
done
|
|
ln -s ../bin/test-step "$SUDO_TEST_ROOT/mock/pacman"
|
|
|
|
reset_boundary() {
|
|
: >"$SUDO_TEST_LOG"
|
|
/usr/bin/rm -f "$SUDO_TEST_CACHE"
|
|
unset SUDO_TEST_FAIL_STEP SUDO_TEST_SIGNAL_STEP SUDO_TEST_SUDO_FAIL SUDO_TEST_REVOKE_FAIL SUDO_TEST_UNSUPPORTED SUDO_TEST_REMOVE_WRAPPER_STEP
|
|
}
|
|
assert_boundary_cold() {
|
|
[[ ! -e $SUDO_TEST_CACHE ]] || fail "$1 left cached authorization"
|
|
[[ $(tail -1 "$SUDO_TEST_LOG") == "sudo -k" ]] || fail "$1 did not revoke at exit" "$(<"$SUDO_TEST_LOG")"
|
|
}
|