diff --git a/hosts/guard/install_pacman_hooks.sh b/hosts/guard/install_pacman_hooks.sh index c4b63c5..63e92e7 100755 --- a/hosts/guard/install_pacman_hooks.sh +++ b/hosts/guard/install_pacman_hooks.sh @@ -9,21 +9,8 @@ HOOKS_DIR="/etc/pacman.d/hooks" install -d -m 755 "$HOOKS_DIR" -# Pre-transaction hook -cat >"$HOOKS_DIR/10-unlock-etc-hosts.hook" <<'HOOK' -[Trigger] -Operation = Upgrade -Operation = Install -Operation = Remove -Type = Package -Target = * - -[Action] -Description = Temporarily unlocking /etc/hosts for transaction -When = PreTransaction -Exec = /bin/bash /usr/local/share/hosts-guard/pacman-pre-unlock-hosts.sh -NeedsTargets -HOOK +# Ensure any legacy pre-transaction hook is removed so pre-unlock only occurs via the wrapper +rm -f "$HOOKS_DIR/10-unlock-etc-hosts.hook" 2>/dev/null || true # Post-transaction hook cat >"$HOOKS_DIR/90-relock-etc-hosts.hook" <<'HOOK' @@ -43,7 +30,9 @@ HOOK # Place helper scripts into a shared location install -d -m 755 /usr/local/share/hosts-guard -install -m 755 "$SCRIPT_DIR/pacman-hooks/pacman-pre-unlock-hosts.sh" /usr/local/share/hosts-guard/ install -m 755 "$SCRIPT_DIR/pacman-hooks/pacman-post-relock-hosts.sh" /usr/local/share/hosts-guard/ +# Remove legacy pre-unlock helper if present to reduce accidental execution surface +rm -f /usr/local/share/hosts-guard/pacman-pre-unlock-hosts.sh 2>/dev/null || true + echo "Pacman hooks installed into $HOOKS_DIR." diff --git a/hosts/guard/pacman-hooks/pacman-post-relock-hosts.sh b/hosts/guard/pacman-hooks/pacman-post-relock-hosts.sh index 450f4e7..9589bb3 100644 --- a/hosts/guard/pacman-hooks/pacman-post-relock-hosts.sh +++ b/hosts/guard/pacman-hooks/pacman-post-relock-hosts.sh @@ -8,7 +8,7 @@ LOGTAG=hosts-guard-hook mount_layers_count() { awk '$5=="/etc/hosts"{c++} END{print c+0}' /proc/self/mountinfo 2>/dev/null || echo 0; } collapse_mounts() { local i=0 - if command -v mountpoint >/devnull 2>&1; then + if command -v mountpoint >/dev/null 2>&1; then while mountpoint -q "$TARGET"; do umount -l "$TARGET" >/dev/null 2>&1 || break i=$((i+1)) diff --git a/hosts/guard/pacman-hooks/pacman-pre-unlock-hosts.sh b/hosts/guard/pacman-hooks/pacman-pre-unlock-hosts.sh deleted file mode 100644 index e44866a..0000000 --- a/hosts/guard/pacman-hooks/pacman-pre-unlock-hosts.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env bash -# Non-interactive pre-transaction hook to temporarily unlock /etc/hosts - -TARGET=/etc/hosts -LOGTAG=hosts-guard-hook - -stop_units_if_present() { - local units=(hosts-bind-mount.service hosts-guard.path) - for u in "${units[@]}"; do - if command -v systemctl >/dev/null 2>&1; then - if systemctl list-unit-files 2>/dev/null | grep -q "^$u"; then - systemctl stop "$u" >/dev/null 2>&1 || true - fi - fi - done -} - -is_ro_mount() { findmnt -no OPTIONS -T "$TARGET" 2>/dev/null | grep -qw ro; } -is_bind_mount() { findmnt -no OPTIONS -T "$TARGET" 2>/dev/null | grep -qw bind; } - -mount_layers_count() { awk '$5=="/etc/hosts"{c++} END{print c+0}' /proc/self/mountinfo 2>/dev/null || echo 0; } -cleanup_mount_stacks() { - local i=0 - # Unmount bind layers until /etc/hosts is no longer a mountpoint - if command -v mountpoint >/dev/null 2>&1; then - while mountpoint -q "$TARGET"; do - umount -l "$TARGET" >/dev/null 2>&1 || break - i=$((i+1)) - (( i > 20 )) && break - done - else - # Fallback to best-effort using mountinfo count - local cnt - cnt=$(mount_layers_count) - while (( cnt > 1 )); do - umount -l "$TARGET" >/dev/null 2>&1 || break - i=$((i+1)) - (( i > 20 )) && break - cnt=$(mount_layers_count) - done - fi -} - -# Drop protective attributes if present -if command -v lsattr >/dev/null 2>&1; then - attrs=$(lsattr -d "$TARGET" 2>/dev/null || true) - echo "$attrs" | grep -q " i " && chattr -i "$TARGET" >/dev/null 2>&1 || true - echo "$attrs" | grep -q " a " && chattr -a "$TARGET" >/dev/null 2>&1 || true -fi - -stop_units_if_present - -logger -t "$LOGTAG" "pre: unlocking /etc/hosts (starting)" -echo "$(date -Is) pre-unlock" >> /run/hosts-guard-hook.log 2>/dev/null || true - -# Always collapse any existing layers; we'll operate on the plain file -cleanup_mount_stacks - -# If someone managed a ro single-layer mount, ensure rw by remounting or collapsing again -if is_ro_mount; then - mount -o remount,rw "$TARGET" >/dev/null 2>&1 || cleanup_mount_stacks -fi - -logger -t "$LOGTAG" "pre: unlocking /etc/hosts (done)" - -exit 0