v0.54.0: format-safety foundation — unclaimed-disk guard + guarded-mkfs wrapper
Impl-1. Format now runs a mandatory unclaimed-disk guard (internal/storage/claim.go: SystemDisks + lsblk member-FSTYPE + foreign-mount + RO + pvs/zpool; fail-safe → CLAIMED) before any mkfs — refuses the OS disk / LVM PV / ZFS-mdraid member / foreign-mounted device even when non-data-bearing (guard sits in Format, not the handler). Below the agent, mkfs goes ONLY through configs/felhom-mkfs-guarded.sh (sudoers no longer allowlists raw mkfs.*), which re-checks the catastrophic cases as root. Read-only pvs/zpool added to FELHOM_DISK. Tests + red-proof; capability manifest updated. go build/vet/test clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -24,7 +24,9 @@ Cmnd_Alias FELHOM_DISK = \
|
||||
/usr/sbin/smartctl -a -j /dev/nvme[0-9]*n[0-9]*, \
|
||||
/usr/sbin/smartctl -a -j /dev/vd[a-z]*, \
|
||||
/usr/sbin/smartctl -a -j /dev/hd[a-z]*, \
|
||||
/usr/sbin/lvs --reportformat json --units b -o lv_name\,data_percent\,metadata_percent -- *
|
||||
/usr/sbin/lvs --reportformat json --units b -o lv_name\,data_percent\,metadata_percent -- *, \
|
||||
/usr/sbin/pvs --reportformat json --noheadings -o pv_name, \
|
||||
/usr/sbin/zpool status -P
|
||||
|
||||
# Provisioning back-half (slice 8A, doc 03 §6): populate a guest's bootstrap config mount
|
||||
# host-side (internal/provision). These are host-root ops the API token cannot do — a bind mount
|
||||
@@ -37,16 +39,15 @@ Cmnd_Alias FELHOM_PROVISION = \
|
||||
/usr/sbin/pct set [0-9]* -mp[0-9]* /var/lib/felhom-agent/guests/*, \
|
||||
/usr/sbin/pct set [0-9]* -onboot 1
|
||||
|
||||
# Disk inspection + format (slice 8C). blkid/lsblk read the device's data-bearing evidence (the
|
||||
# agent decides data-bearing-ness from THIS, never the caller's claim); mkfs.* formats a device the
|
||||
# agent already classified blank (a data-bearing format is refused pending an operator signature).
|
||||
# The agent fine-validates the device path (ValidateBlockDevice: raw disk / partition under /dev
|
||||
# only) + fstype before any exec — the wildcard is the coarse allowlist, the agent is the fine gate.
|
||||
# Disk inspection + format (slice 8C + Impl-1). blkid/lsblk read the device's data-bearing evidence
|
||||
# (the agent decides data-bearing-ness from THIS, never the caller's claim). Format goes ONLY through
|
||||
# felhom-mkfs-guarded (Impl-1 Part B): raw mkfs.* is NO LONGER allowlisted, so even a bad agent cannot
|
||||
# mkfs the OS disk — the wrapper re-checks the catastrophic cases (system disk / LVM PV / foreign mount)
|
||||
# as root and refuses, and the agent's unclaimed-disk filter (claim.go) is the primary guard above it.
|
||||
Cmnd_Alias FELHOM_FORMAT = \
|
||||
/usr/sbin/blkid -p -o export /dev/*, \
|
||||
/usr/bin/lsblk -J -o NAME\,FSTYPE\,PTTYPE\,MOUNTPOINT /dev/*, \
|
||||
/usr/sbin/mkfs.ext4 -F /dev/*, \
|
||||
/usr/sbin/mkfs.xfs -f /dev/*
|
||||
/usr/local/sbin/felhom-mkfs-guarded /dev/* *
|
||||
|
||||
# LAN split-horizon resolver (internal/lanresolver): the agent manages a host-side dnsmasq that
|
||||
# answers *.<customer-domain> with each guest's live LAN IP. install only ever writes felhom-*.conf
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
#!/bin/bash
|
||||
#===============================================================================
|
||||
# felhom-mkfs-guarded — the ONLY mkfs path the felhom-agent sudoers permits (Impl-1 Part B,
|
||||
# SPIKE-drive-enrollment-2026-07-01 §SQ3). Defense-in-depth BELOW the agent: even a buggy or
|
||||
# compromised agent cannot mkfs a catastrophic target through this — it re-checks, as root, the
|
||||
# cheap catastrophic cases (OS/system disk, LVM physical volume, a foreign mount) and refuses.
|
||||
#
|
||||
# The agent's full unclaimed-disk filter (internal/storage/claim.go) is the PRIMARY guard; this
|
||||
# wrapper is a deliberately minimal, auditable second gate. It is NOT the place for the full filter.
|
||||
#
|
||||
# Usage: felhom-mkfs-guarded <device> <fstype:ext4|xfs>
|
||||
#===============================================================================
|
||||
set -euo pipefail
|
||||
|
||||
die() { echo "felhom-mkfs-guarded: REFUSED: $*" >&2; exit 1; }
|
||||
|
||||
dev="${1:-}"; fstype="${2:-}"
|
||||
[[ -n "$dev" && -n "$fstype" ]] || die "usage: felhom-mkfs-guarded <device> <fstype>"
|
||||
|
||||
# The device must be a REAL block-device node under /dev — no symlink (e.g. /dev/disk/by-*), no traversal.
|
||||
[[ "$dev" == /dev/* ]] || die "device must be under /dev ($dev)"
|
||||
[[ "$dev" != *..* ]] || die "path traversal ($dev)"
|
||||
[[ -b "$dev" ]] || die "not a block device ($dev)"
|
||||
[[ ! -L "$dev" ]] || die "device must be a real node, not a symlink ($dev)"
|
||||
|
||||
# Whole-disk of the target (a partition's parent, else the disk itself).
|
||||
pk="$(lsblk -ndo PKNAME "$dev" 2>/dev/null || true)"
|
||||
whole="$dev"; [[ -n "$pk" ]] && whole="/dev/$pk"
|
||||
|
||||
# 1) OS/system disk — does the target's whole-disk back /, /boot or /boot/efi?
|
||||
while read -r src mnt _rest; do
|
||||
case "$mnt" in
|
||||
/|/boot|/boot/efi)
|
||||
spk="$(lsblk -ndo PKNAME "$src" 2>/dev/null || true)"
|
||||
swhole="$src"; [[ -n "$spk" ]] && swhole="/dev/$spk"
|
||||
[[ "$swhole" == "$whole" || "$src" == "$dev" || "$src" == "$whole" ]] && die "system/OS disk ($dev backs $mnt)"
|
||||
;;
|
||||
esac
|
||||
done < /proc/mounts
|
||||
|
||||
# 2) LVM physical volume anywhere on the target disk or its partitions.
|
||||
if command -v pvs >/dev/null 2>&1; then
|
||||
while read -r pv; do
|
||||
pv="${pv//[[:space:]]/}"; [[ -z "$pv" ]] && continue
|
||||
pvpk="$(lsblk -ndo PKNAME "$pv" 2>/dev/null || true)"
|
||||
pvwhole="$pv"; [[ -n "$pvpk" ]] && pvwhole="/dev/$pvpk"
|
||||
[[ "$pvwhole" == "$whole" ]] && die "device holds an LVM physical volume ($pv)"
|
||||
done < <(pvs --noheadings -o pv_name 2>/dev/null || true)
|
||||
fi
|
||||
|
||||
# 3) mounted OUTSIDE Felhom's own drive area = a live foreign filesystem → catastrophic. Mounts under
|
||||
# /mnt/felhom-drives are our own drives (the agent detaches before a re-init) → allowed.
|
||||
while read -r mp; do
|
||||
[[ -z "$mp" ]] && continue
|
||||
case "$mp" in
|
||||
/mnt/felhom-drives|/mnt/felhom-drives/*) : ;;
|
||||
*) die "device (or a partition) is mounted at $mp ($dev)" ;;
|
||||
esac
|
||||
done < <(lsblk -nro MOUNTPOINT "$whole" 2>/dev/null || true)
|
||||
|
||||
# Passed the catastrophic checks → format. exec so the mkfs exit status is the wrapper's.
|
||||
case "$fstype" in
|
||||
ext4) exec /usr/sbin/mkfs.ext4 -F "$dev" ;;
|
||||
xfs) exec /usr/sbin/mkfs.xfs -f "$dev" ;;
|
||||
*) die "unsupported fstype ($fstype)" ;;
|
||||
esac
|
||||
Reference in New Issue
Block a user