carlos / platform Public

activator: a seed proof on a kernel with no cgroup.kill keeps the leader-only proof

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev 4771d147e6225d24b60d42368324dfd401f2d928 parent 7903294
2 files changed, +25 −2
  • internal/activator/backend_exec.go +10 −2
  • internal/activator/containment_test.go +15 −0
diff --git a/internal/activator/backend_exec.go b/internal/activator/backend_exec.go
index 017ea974f..b95208e75 100644
--- a/internal/activator/backend_exec.go
+++ b/internal/activator/backend_exec.go
@@ -1124,8 +1124,9 @@ func (b *ExecBackend) seedChild(ctx context.Context, rt registry.Route, exe stri
// lease. An absent cgroup is empty. A box with no delegated cgroup
// (cgroup.ErrNoDelegation) ran the seed unaccounted, with nothing that
// could reach a descendant, so the leader's exit is the only proof there
-// is (ledger 127): it logs and answers nil. Any other failure is returned,
-// and the caller keeps the database (ErrSeedUnproven).
+// is (ledger 127): it logs and answers nil. So is a kernel with no
+// cgroup.kill (cgroup.ErrNoKill). Any other failure is returned, and the
+// caller keeps the database (ErrSeedUnproven).
func (b *ExecBackend) seedDescendantsGone(ctx context.Context, rt registry.Route, child string) error {
var err error
switch {
@@ -1140,6 +1141,13 @@ func (b *ExecBackend) seedDescendantsGone(ctx context.Context, rt registry.Route
log.Printf("activator: %s: the seed ran with no delegated cgroup; its leader's exit is the only proof there is", rt.Host)
return nil
}
+ if errors.Is(err, cgroup.ErrNoKill) {
+ // A kernel before 5.14 can kill nothing in a cgroup (EmptyHost's
+ // rule): read as unproven, an obligation could never be discharged
+ // on such a box and the row would stay down for good.
+ log.Printf("activator: %s: this kernel has no cgroup.kill; the seed's leader's exit is the only proof there is", rt.Host)
+ return nil
+ }
return err
}
diff --git a/internal/activator/containment_test.go b/internal/activator/containment_test.go
index 12e03f2ad..a6680b4e4 100644
--- a/internal/activator/containment_test.go
+++ b/internal/activator/containment_test.go
@@ -639,6 +639,21 @@ func TestAPreexistingDBBesideAnUnprovenSeedIsRefusedThenKept(t *testing.T) {
}
}
+// Finding 5, on the seed's own proof: a kernel with no cgroup.kill can kill
+// nothing, so the leader's exit is the only proof there is, as with no
+// delegation. Read as unproven instead, an obligation could never be
+// discharged on such a box and the row would stay down for good.
+func TestASeedProofWithNoCgroupKillIsTheLeaderOnlyProof(t *testing.T) {
+ const host = "old-kernel-seed.example.com"
+ b, _ := delegatedBackend(t, host)
+ b.cgroupKill = func(context.Context, registry.Route, string) error {
+ return fmt.Errorf("%w: open cgroup.kill: no such file or directory", cgroup.ErrNoKill)
+ }
+ if err := b.seedDescendantsGone(context.Background(), registry.Route{Host: host}, ""); err != nil {
+ t.Fatalf("seedDescendantsGone = %v, want the leader-only proof (nil)", err)
+ }
+}
+
// Flag on, a failed seed's role child is proven empty before the database
// it built is removed.
func TestAFlagOnFailedSeedProvesItsRoleChildBeforeRemovingTheDB(t *testing.T) {