carlos / platform Public

zdd plan 2 final fix: ParentLimit refuses when there is no cgroup manager

With containment on and no cgroup manager, a flat or foreign
ParentLimit answered nil through the manager's nil-safe
SetParentLimit, so a swap could admit an overlap with no parent raised
and no generation child to kill. The backend now refuses with
cgroup.ErrNoDelegation; the manager's own nil-safe contract is kept for
its other callers.

Final review finding L2 (triage T10 nil-manager item).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev 72674b27c749dc99b988fdd5688b05d3569db151 parent ba6e6d6
2 files changed, +18 −0
  • internal/activator/containment.go +6 −0
  • internal/activator/containment_test.go +12 −0
diff --git a/internal/activator/containment.go b/internal/activator/containment.go
index 42e4e3809..ec0a824ec 100644
--- a/internal/activator/containment.go
+++ b/internal/activator/containment.go
@@ -160,6 +160,12 @@ func (b *ExecBackend) ParentLimit(ctx context.Context, rt registry.Route, l cgro
case LayoutFenced, LayoutConflict:
return fmt.Errorf("%s: refusing to set a parent limit: %s", rt.Host, p.reason)
}
+ // The manager's SetParentLimit answers nil with no manager; here that
+ // would admit an overlap with no parent raised and no generation child
+ // to kill, so it refuses.
+ if b.Cgroups == nil {
+ return cgroup.ErrNoDelegation
+ }
return b.Cgroups.SetParentLimit(rt.Host, l)
}
diff --git a/internal/activator/containment_test.go b/internal/activator/containment_test.go
index 8885b523a..a66c53e47 100644
--- a/internal/activator/containment_test.go
+++ b/internal/activator/containment_test.go
@@ -159,6 +159,18 @@ func TestParentLimitFlatWritesTheParent(t *testing.T) {
}
}
+// No cgroup manager (no delegation): there is no parent to raise, so a
+// flat ParentLimit refuses rather than let a swap admit an overlap with
+// nothing raised.
+func TestParentLimitFlatRefusesWithoutACgroupManager(t *testing.T) {
+ b := testExecBackend(t)
+ b.GenContainment = true
+ b.Cgroups = nil
+ if err := b.ParentLimit(context.Background(), registry.Route{Host: "h.example.com"}, cgroup.OverlapLimit(cgroup.TierDefault, cgroup.TierDefault)); !errors.Is(err, cgroup.ErrNoDelegation) {
+ t.Fatalf("ParentLimit with no cgroup manager: %v, want cgroup.ErrNoDelegation", err)
+ }
+}
+
// A fixture is not cgroup v2: KillGen must refuse rather than claim an
// empty child it never proved.
func TestKillGenFlatRefusesWithoutCgroupV2(t *testing.T) {