Security review of 912f7c1: the mkfs wrapper trusts no sibling claim; the internal-place helper fails closed
gates / gates (push) Successful in 25s
gates / gates (push) Successful in 25s
- felhom-mkfs-guarded: the 0.158.0 exemption for a sibling part mounted at /mnt/<name> + under /mnt/felhom-drives is removed — the agent can make that corroborating mount itself. Every mount of every node outside /mnt/felhom-drives refuses (kernel mount table); an unlistable disk refuses. CandidatePartition.Formattable is false for every part of a disk with a mounted node, so it is never offered for formatting (attach still is). - felhom-internal-place: a failed lvs listing, a listing without the pool, or a blkid exit other than 0/2 refuses (they read as "nothing promised" / "no signature" before). Every new test was seen failing against the 0.158.0 versions. Claude-Session: https://claude.ai/code/session_012qRErfCoiTkvDK9N5XHbzb
This commit is contained in:
@@ -13,7 +13,8 @@ import (
|
||||
// A disk that passed the WHOLE-disk unclaimed filter (classifyClaim: not the system disk, no LVM/ZFS/RAID/LUKS/swap
|
||||
// member on any node, no foreign mount on any node) also lists its partitions, each with its own state:
|
||||
//
|
||||
// empty no filesystem, no children → „format this part" (self-serve: the agent's probe says blank)
|
||||
// empty no filesystem, no children → „format this part" (self-serve: the agent's probe says blank) —
|
||||
// only while NO part of the disk is mounted (Formattable)
|
||||
// filesystem ext4/xfs (mountable) or another fs → „use this part" when mountable; „format this part" only through
|
||||
// the customer-confirmed data-bearing path (the agent's own probe)
|
||||
// in_use already Felhom's own drive → shown, never offered (it is a registered drive already)
|
||||
@@ -32,6 +33,10 @@ type CandidatePartition struct {
|
||||
Mountable bool `json:"mountable"`
|
||||
DurableID string `json:"durable_id,omitempty"` // uuid:<fs-uuid> — the attach key ("" when empty)
|
||||
MountedAt string `json:"mounted_at,omitempty"` // in_use: Felhom's own mount
|
||||
// Formattable is false when ANY node of the disk is mounted (another part in use): the root mkfs wrapper refuses
|
||||
// every mount outside /mnt/felhom-drives on the disk and deliberately does not trust a sibling that claims to be
|
||||
// Felhom's own (a compromised agent could fake that). Such a part can still be USED (attach erases nothing).
|
||||
Formattable bool `json:"formattable"`
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -55,6 +60,19 @@ func candidatePartitions(lsblkJSON []byte, wholeName string, sizeOf func(string)
|
||||
if d.Name != wholeName {
|
||||
continue
|
||||
}
|
||||
diskMounted := d.MountPoint != ""
|
||||
var walk func(n lsblkDev)
|
||||
walk = func(n lsblkDev) {
|
||||
if n.MountPoint != "" {
|
||||
diskMounted = true
|
||||
}
|
||||
for _, c := range n.Children {
|
||||
walk(c)
|
||||
}
|
||||
}
|
||||
for _, c := range d.Children {
|
||||
walk(c)
|
||||
}
|
||||
for _, p := range d.Children {
|
||||
if len(p.Children) > 0 || memberFSTypes[p.FSType] {
|
||||
continue // LVM/mapper on it, or a member: not a place (the disk filter refuses these anyway)
|
||||
@@ -74,6 +92,7 @@ func candidatePartitions(lsblkJSON []byte, wholeName string, sizeOf func(string)
|
||||
c.DurableID = "uuid:" + u
|
||||
}
|
||||
}
|
||||
c.Formattable = c.State != PartInUse && !diskMounted
|
||||
out = append(out, c)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,3 +71,21 @@ func TestPartitions_UncorroboratedMountIsNotOffered(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The root wrapper refuses any format on a disk with a mounted node (and trusts no „it is Felhom's own" claim), so a
|
||||
// part next to a mounted one is never offered for formatting — only for use. Positive control: an unmounted disk.
|
||||
func TestPartitions_FormattableOnlyWhenNothingOnTheDiskIsMounted(t *testing.T) {
|
||||
m := listParts(map[string]bool{"/mnt/films": true})
|
||||
for dev, p := range m {
|
||||
if p.Formattable {
|
||||
t.Fatalf("%s: a part of a disk with a mounted part must not be formattable: %+v", dev, p)
|
||||
}
|
||||
}
|
||||
free := `{"blockdevices":[{"name":"sdc","fstype":null,"mountpoint":null,"children":[
|
||||
{"name":"sdc1","fstype":null,"mountpoint":null},{"name":"sdc2","fstype":"ext4","mountpoint":null}]}]}`
|
||||
got := candidatePartitions([]byte(free), "sdc", func(string) int64 { return 1 << 30 }, func(string) int { return 1 },
|
||||
func(string) (string, bool) { return "u", true }, nil)
|
||||
if len(got) != 2 || !got[0].Formattable || !got[1].Formattable {
|
||||
t.Fatalf("parts of an unmounted disk are formattable, got %+v", got)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user