From da9b846f71c340529f534e1671b37b23fe66550d Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Tue, 31 Aug 2021 16:22:25 -0700 Subject: [PATCH] libct/cg: add Resources=nil unit test Cgroup controllers should never panic, and yet sometimes they do. Add a unit test to check that controllers never panic when called with nil arguments and/or resources, and fix a few found cases. Signed-off-by: Kir Kolyshkin --- libcontainer/cgroups/fs2/fs2.go | 6 +++ libcontainer/cgroups/manager/manager_test.go | 45 ++++++++++++++++++++ libcontainer/cgroups/systemd/v1.go | 3 ++ libcontainer/cgroups/systemd/v2.go | 3 ++ 4 files changed, 57 insertions(+) create mode 100644 libcontainer/cgroups/manager/manager_test.go diff --git a/libcontainer/cgroups/fs2/fs2.go b/libcontainer/cgroups/fs2/fs2.go index 067d9791aa0..492778e3105 100644 --- a/libcontainer/cgroups/fs2/fs2.go +++ b/libcontainer/cgroups/fs2/fs2.go @@ -129,6 +129,9 @@ func (m *manager) GetStats() (*cgroups.Stats, error) { } func (m *manager) Freeze(state configs.FreezerState) error { + if m.config.Resources == nil { + return errors.New("cannot toggle freezer: cgroups not configured for container") + } if err := setFreezer(m.dirPath, state); err != nil { return err } @@ -145,6 +148,9 @@ func (m *manager) Path(_ string) string { } func (m *manager) Set(r *configs.Resources) error { + if r == nil { + return nil + } if err := m.getControllers(); err != nil { return err } diff --git a/libcontainer/cgroups/manager/manager_test.go b/libcontainer/cgroups/manager/manager_test.go new file mode 100644 index 00000000000..5e053656440 --- /dev/null +++ b/libcontainer/cgroups/manager/manager_test.go @@ -0,0 +1,45 @@ +package manager + +import ( + "testing" + + "github.com/opencontainers/runc/libcontainer/configs" +) + +// TestNilResources checks that a cgroup manager do not panic when +// config.Resources is nil. While it does not make sense to use a +// manager with no resources, it should not result in a panic. +// +// This tests either v1 or v2 managers (both fs and systemd) +// depending on what cgroup version is available on the host. + +func TestNilResources(t *testing.T) { + for _, sd := range []bool{false, true} { + cg := &configs.Cgroup{} // .Resources is nil + cg.Systemd = sd + mgr, err := New(cg) + if err != nil { + // Some managers require non-nil Resources during + // instantiation -- provide and retry. In such case + // we're mostly testing Set(nil) below. + cg.Resources = &configs.Resources{} + mgr, err = New(cg) + if err != nil { + t.Error(err) + continue + } + } + _ = mgr.Apply(-1) + _ = mgr.Set(nil) + _ = mgr.Freeze(configs.Thawed) + _ = mgr.Exists() + _, _ = mgr.GetAllPids() + _, _ = mgr.GetCgroups() + _, _ = mgr.GetFreezerState() + _ = mgr.Path("") + _ = mgr.GetPaths() + _, _ = mgr.GetStats() + _, _ = mgr.OOMKillCount() + _ = mgr.Destroy() + } +} diff --git a/libcontainer/cgroups/systemd/v1.go b/libcontainer/cgroups/systemd/v1.go index 28a62e41adc..74030391a97 100644 --- a/libcontainer/cgroups/systemd/v1.go +++ b/libcontainer/cgroups/systemd/v1.go @@ -389,6 +389,9 @@ func (m *legacyManager) freezeBeforeSet(unitName string, r *configs.Resources) ( } func (m *legacyManager) Set(r *configs.Resources) error { + if r == nil { + return nil + } if r.Unified != nil { return cgroups.ErrV1NoUnified } diff --git a/libcontainer/cgroups/systemd/v2.go b/libcontainer/cgroups/systemd/v2.go index 4fcd23205c5..7a7fe63662b 100644 --- a/libcontainer/cgroups/systemd/v2.go +++ b/libcontainer/cgroups/systemd/v2.go @@ -384,6 +384,9 @@ func (m *unifiedManager) GetStats() (*cgroups.Stats, error) { } func (m *unifiedManager) Set(r *configs.Resources) error { + if r == nil { + return nil + } properties, err := genV2ResourcesProperties(r, m.dbus) if err != nil { return err