mirror of
https://github.com/kuhyx/scripts.git
synced 2026-07-04 13:23:07 +02:00
92 lines
2.3 KiB
Bash
92 lines
2.3 KiB
Bash
|
|
#!/usr/bin/env bash
|
||
|
|
# Shared functions for hosts-guard pacman hooks
|
||
|
|
# This file is sourced by pacman-pre-unlock-hosts.sh and pacman-post-relock-hosts.sh
|
||
|
|
|
||
|
|
TARGET=/etc/hosts
|
||
|
|
LOGTAG=hosts-guard-hook
|
||
|
|
|
||
|
|
# Check if target has a read-only mount
|
||
|
|
is_ro_mount() {
|
||
|
|
findmnt -no OPTIONS -T "$TARGET" 2>/dev/null | grep -qw ro
|
||
|
|
}
|
||
|
|
|
||
|
|
# Count mount layers for the target
|
||
|
|
mount_layers_count() {
|
||
|
|
awk '$5=="/etc/hosts"{c++} END{print c+0}' /proc/self/mountinfo 2>/dev/null || echo 0
|
||
|
|
}
|
||
|
|
|
||
|
|
# Collapse all bind mount layers
|
||
|
|
collapse_mounts() {
|
||
|
|
local i=0
|
||
|
|
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
|
||
|
|
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
|
||
|
|
}
|
||
|
|
|
||
|
|
# Stop systemd units related to hosts guard
|
||
|
|
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
|
||
|
|
}
|
||
|
|
|
||
|
|
# Remove immutable/append-only attributes
|
||
|
|
remove_host_attrs() {
|
||
|
|
if command -v lsattr >/dev/null 2>&1; then
|
||
|
|
local attrs
|
||
|
|
attrs=$(lsattr -d "$TARGET" 2>/dev/null || true)
|
||
|
|
if echo "$attrs" | grep -q " i "; then
|
||
|
|
chattr -i "$TARGET" >/dev/null 2>&1 || true
|
||
|
|
fi
|
||
|
|
if echo "$attrs" | grep -q " a "; then
|
||
|
|
chattr -a "$TARGET" >/dev/null 2>&1 || true
|
||
|
|
fi
|
||
|
|
fi
|
||
|
|
}
|
||
|
|
|
||
|
|
# Apply immutable attribute
|
||
|
|
apply_immutable() {
|
||
|
|
if command -v chattr >/dev/null 2>&1; then
|
||
|
|
chattr +i "$TARGET" >/dev/null 2>&1 || true
|
||
|
|
fi
|
||
|
|
}
|
||
|
|
|
||
|
|
# Apply a single read-only bind mount layer
|
||
|
|
apply_ro_bind_mount() {
|
||
|
|
mount --bind "$TARGET" "$TARGET" >/dev/null 2>&1 || true
|
||
|
|
mount -o remount,ro,bind "$TARGET" >/dev/null 2>&1 || true
|
||
|
|
}
|
||
|
|
|
||
|
|
# Start the path watcher service
|
||
|
|
start_path_watcher() {
|
||
|
|
if command -v systemctl >/dev/null 2>&1; then
|
||
|
|
systemctl start hosts-guard.path >/dev/null 2>&1 || true
|
||
|
|
fi
|
||
|
|
}
|
||
|
|
|
||
|
|
# Log to system logger and run log file
|
||
|
|
log_hook() {
|
||
|
|
local phase="$1"
|
||
|
|
local state="$2"
|
||
|
|
logger -t "$LOGTAG" "$phase: $state"
|
||
|
|
echo "$(date -Is) $phase-$state" >>/run/hosts-guard-hook.log 2>/dev/null || true
|
||
|
|
}
|