Two levels of pure taxonomy carrying no information, and a 2-directory
cap leaves no room for them. Categories now sit directly under
linux_configuration/: features, fixes, utils, misc, fresh-install,
installers, diagnostics, gaming, boot_recovery, periodic_background, lib,
meta, tests. A script's own lib/ and tests/ are exempt from the cap, so
those stay put.
Depth violations 248 -> 139; roughly 40 of the remainder are inside
digital_wellbeing and hosts, deferred until the guard-lib repoint.
The moves are the easy half. What breaks is every path that counted
levels, and three classes of it had to be found by resolving paths rather
than reading diffs:
- 52 relative `source` lines for lib/common.sh and lib/android.sh. The
correct prefix differs per file: 40 were ../../ and 12 were ../../../,
so a blanket replace would have fixed one set and broken the other.
- REPO_ROOT in 7 fixes/lib/tests harnesses and setup_syncyomi_guard.sh,
each walking up four levels from a directory now two levels shallower.
This caused a real regression -- the fixes suite went red with
"log_warn: command not found" -- caught by running it and comparing
against the pre-move baseline worktree.
- conftest.py's sys.path entries, which took the pytest gate down with
14 collection errors, and the `# shellcheck source=` directives, which
took shellcheck down with SC1091.
16 symlinks in $HOME broke, including the entire i3blocks bar. All
repointed, and cpu_monitor/memory/disk/time/volume were run to confirm
they emit real output rather than merely resolving.
Verified: 1798 tests pass at 100% coverage, 8 of 9 lib/tests suites pass
(the ninth needs the coverage jail, identically at baseline), pre-commit
is clean, and the two untracked secret configs are still ignored after
their gitignore paths changed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PJrqKERAo5QUeEHWS5Asgp
4.6 KiB
Integrity verification, cleanup and stale locks
Integrity Verification
On every invocation, the wrapper verifies policy files haven't been tampered with:
verify_policy_integrity() {
# Reads /var/lib/pacman-wrapper/policy.sha256
# Compares SHA256 of each policy file
# If mismatch: BLOCKS all operations
}
If tampering detected:
SECURITY WARNING: Policy file integrity check failed!
CRITICAL: Policy files have been tampered with!
Wrapper operation DENIED. Please reinstall using: sudo install_pacman_wrapper.sh
Hosts Integration
The wrapper integrates with the hosts guard system:
pre_unlock_hosts() {
# Called before any transaction (-S, -U, -R)
/usr/local/share/hosts-guard/pacman-pre-unlock-hosts.sh
}
post_relock_hosts() {
# Called after transaction completes
/usr/local/share/hosts-guard/pacman-post-relock-hosts.sh
}
This allows package installations to modify /etc/hosts temporarily (e.g., for network setup) while maintaining protection.
Common Tasks
Adding a Blocked Package
- Edit
pacman_blocked_keywords.txt:
echo "newkeyword" >> pacman_blocked_keywords.txt
- Reinstall wrapper to update checksums:
sudo ./install_pacman_wrapper.sh
Whitelisting a Package
If a legitimate package is being blocked (e.g., python-firefox-sync blocked by "firefox" keyword):
- Edit
pacman_whitelist.txt:
echo "python-firefox-sync" >> pacman_whitelist.txt
- Reinstall wrapper:
sudo ./install_pacman_wrapper.sh
Adding a Challenge Requirement
- Edit
pacman_greylist.txt:
echo "suspicious-package" >> pacman_greylist.txt
- Reinstall wrapper.
Bypassing the Wrapper (Emergency)
If wrapper is broken and you need real pacman:
sudo /usr/bin/pacman.orig -S package
Warning: This bypasses all security checks.
Post-Transaction Cleanup
After every transaction, the wrapper:
- Scans installed packages for blocked keywords
- Removes any that match (shouldn't happen normally)
- Scans for greylisted packages and removes them
- Checks if VirtualBox is installed and enforces hosts
remove_installed_blocked_packages() {
mapfile -t installed_names < <("$PACMAN_BIN" -Qq)
for name in "${installed_names[@]}"; do
if is_blocked_package_name "$name"; then
pacman -Rns --noconfirm "$name"
fi
done
}
Stale Lock Handling
The stale-lock logic lives in pacman_lock_lib.sh (shared, sourced by both
pacman_wrapper.sh and makepkg_wrapper.sh — single source of truth). The
wrapper sources it only AFTER verify_policy_integrity, and the lib is listed in
the integrity manifest, so a tampered lib is rejected before it runs.
If /var/lib/pacman/db.lck exists but no pacman is running:
- Interactive: Prompts user to remove (15s timeout)
- Non-interactive (
--noconfirm): Auto-removes; also auto-removes if lock is10 minutes old
- If a real pacman/pamac process is running: Blocks with error. Detection uses
fuser/lsofon the lock file AND a system-widepgrep -x pacmanguard (pacman_process_running) so an UNPRIVILEGED caller (makepkg is never root) can still see a ROOTpacman -Syuthat its ownfusercannot.
Makepkg wrapper
/usr/bin/makepkg is symlinked to makepkg_wrapper (real binary at
/usr/bin/makepkg.orig). Vendored makepkg's run_pacman() has its own
lock-wait that checks ONLY file existence with no timeout, so an orphaned
db.lck hangs makepkg -i forever ("Pacman is currently in use, please
wait...") before pacman is ever called — the pacman wrapper's cleanup never
gets a turn. makepkg_wrapper closes this: for install-bound invocations
(-i/--install) it clears an orphaned lock up front, then execs real makepkg.
It bypasses (execs real makepkg unchanged) inside a fakeroot build sandbox
(FAKEROOTKEY set) or for non-install invocations, and fails open — if the
shared lib is missing it execs real makepkg rather than break all builds.
Upgrade survival
A pacman-git upgrade reinstalls /usr/bin/pacman and /usr/bin/makepkg as
stock binaries, clobbering the wrapper symlinks. Two mechanisms restore them:
- PostTransaction hook
/etc/pacman.d/hooks/96-restore-pkg-wrappers.hook(Target = pacman/pacman-git) runsrewrap_pkg_managers.sh(file-ops only, never calls pacman) to re-establish both symlinks and refresh the.origbackups. NOTE: alpmOperationaccepts only Install/Upgrade/Remove — an invalid value aborts EVERY transaction; validate with a real-Sinstall. - Drift verifier
check_makepkg_wrapper()incheck_and_enable_services.shplus the hourly periodic driver re-running both installers.