From c99cb8373e3027add5afffae3fae089ed0af07cd Mon Sep 17 00:00:00 2001 From: Krzysztof kuhy Rudnicki Date: Sat, 4 Jul 2026 11:47:59 +0200 Subject: [PATCH] feat: initial guard-lib - shared tamper-resistance primitives Extracts the chattr+bind-mount+systemd-watcher file-locking pattern (and a new pacman PreTransaction package-block primitive) out of screen-locker and steam-backlog-enforcer into a standalone, config-driven library so both projects (and steam-backlog-enforcer's new block-gaming feature) can share one implementation instead of maintaining parallel copies. - guardctl: CLI entry point (file-guard, package-block subcommands) - lib/file_guard.sh: chattr +i / bind-mount / systemd-path-watcher / pacman hook enforcement for a single target file, keyed by /etc/guard-lib/targets config; includes `sync` (adopt current content as canonical - for a caller's own legitimate edit) distinct from `pacman-relock` (revert drift) - lib/package_block.sh: time-locked pacman PreTransaction hook that refuses to (re)install a given package while a lock file's `until` timestamp is in the future; supports --bind-mount to compose with file-guard on the same lock file - pacman-hooks/: the installed hook scripts + .hook definitions - systemd/: guard-file@.path/.service watcher units, guard-bind-mount@.service Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01AFNiYQQgSLAkiBXswyimPq --- guard-lib/guardctl | 59 +++ guard-lib/install.sh | 44 +++ guard-lib/lib/common.sh | 132 +++++++ guard-lib/lib/file_guard.sh | 350 ++++++++++++++++++ guard-lib/lib/package_block.sh | 148 ++++++++ .../pacman-hooks/10-guard-lib-unlock-all.hook | 12 + .../pacman-hooks/90-guard-lib-relock-all.hook | 12 + .../pacman-hooks/guard-lib-relock-all.sh | 20 + .../pacman-hooks/guard-lib-unlock-all.sh | 23 ++ guard-lib/systemd/guard-bind-mount@.service | 12 + guard-lib/systemd/guard-file@.path | 10 + guard-lib/systemd/guard-file@.service | 6 + guard-lib/verify-stage1.sh | 183 +++++++++ 13 files changed, 1011 insertions(+) create mode 100755 guard-lib/guardctl create mode 100755 guard-lib/install.sh create mode 100644 guard-lib/lib/common.sh create mode 100644 guard-lib/lib/file_guard.sh create mode 100644 guard-lib/lib/package_block.sh create mode 100644 guard-lib/pacman-hooks/10-guard-lib-unlock-all.hook create mode 100644 guard-lib/pacman-hooks/90-guard-lib-relock-all.hook create mode 100755 guard-lib/pacman-hooks/guard-lib-relock-all.sh create mode 100755 guard-lib/pacman-hooks/guard-lib-unlock-all.sh create mode 100644 guard-lib/systemd/guard-bind-mount@.service create mode 100644 guard-lib/systemd/guard-file@.path create mode 100644 guard-lib/systemd/guard-file@.service create mode 100755 guard-lib/verify-stage1.sh diff --git a/guard-lib/guardctl b/guard-lib/guardctl new file mode 100755 index 0000000..d19c5a4 --- /dev/null +++ b/guard-lib/guardctl @@ -0,0 +1,59 @@ +#!/bin/bash +# guardctl - unified CLI for guard-lib's file-guard and package-block primitives. +set -euo pipefail + +GUARD_LIB_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# When installed to /usr/local/bin, lib/ lives alongside it at +# /usr/local/lib/guard-lib; fall back to the repo layout for local runs. +if [[ -d "$GUARD_LIB_ROOT/lib" ]]; then + LIB_DIR="$GUARD_LIB_ROOT/lib" +elif [[ -d "/usr/local/lib/guard-lib" ]]; then + LIB_DIR="/usr/local/lib/guard-lib" +else + echo "guardctl: error: cannot locate lib/ directory" >&2 + exit 1 +fi + +# shellcheck source=lib/common.sh +source "$LIB_DIR/common.sh" +# shellcheck source=lib/file_guard.sh +source "$LIB_DIR/file_guard.sh" +# shellcheck source=lib/package_block.sh +source "$LIB_DIR/package_block.sh" + +usage() { + cat <<'EOF' +Usage: guardctl [args...] + +Primitives: + file-guard install --target [--canonical ] [--bind-mount] [--plugin