diff --git a/libcontainer/intelrdt/intelrdt.go b/libcontainer/intelrdt/intelrdt.go index 3a1521cc0..ac05f2252 100644 --- a/libcontainer/intelrdt/intelrdt.go +++ b/libcontainer/intelrdt/intelrdt.go @@ -10,6 +10,7 @@ import ( "strings" "sync" + securejoin "github.com/cyphar/filepath-securejoin" "github.com/moby/sys/mountinfo" "golang.org/x/sys/unix" @@ -159,10 +160,25 @@ func NewManager(config *configs.Config, id string, path string) *Manager { if config.IntelRdt == nil { return nil } - if _, err := Root(); err != nil { - // Intel RDT is not available. + + rootPath, err := Root() + if err != nil { return nil } + // NOTE: Should we check if the path provided as arg matches the path + // constructed below? If not, we're screwed as we've effectively lost resctrl + // control of the container (e.g. because the resctrl fs was unmounted or + // remounted elsewhere). All operations are deemed to fail. + if path == "" { + clos := id + if config.IntelRdt.ClosID != "" { + clos = config.IntelRdt.ClosID + } + if path, err = securejoin.SecureJoin(rootPath, clos); err != nil { + return nil + } + } + return newManager(config, id, path) } @@ -434,21 +450,6 @@ func IsMBAEnabled() bool { return mbaEnabled } -// Get the path of the clos group in "resource control" filesystem that the container belongs to -func (m *Manager) getIntelRdtPath() (string, error) { - rootPath, err := Root() - if err != nil { - return "", err - } - - clos := m.id - if m.config.IntelRdt != nil && m.config.IntelRdt.ClosID != "" { - clos = m.config.IntelRdt.ClosID - } - - return filepath.Join(rootPath, clos), nil -} - // Apply applies Intel RDT configuration to the process with the specified pid. func (m *Manager) Apply(pid int) (err error) { // If intelRdt is not specified in config, we do nothing @@ -456,10 +457,7 @@ func (m *Manager) Apply(pid int) (err error) { return nil } - path, err := m.getIntelRdtPath() - if err != nil { - return err - } + path := m.GetPath() m.mu.Lock() defer m.mu.Unlock() @@ -503,9 +501,6 @@ func (m *Manager) Destroy() error { // GetPath returns Intel RDT path to save in a state file and to be able to // restore the object later. func (m *Manager) GetPath() string { - if m.path == "" { - m.path, _ = m.getIntelRdtPath() - } return m.path } diff --git a/libcontainer/intelrdt/intelrdt_test.go b/libcontainer/intelrdt/intelrdt_test.go index c127cd8f7..114499f82 100644 --- a/libcontainer/intelrdt/intelrdt_test.go +++ b/libcontainer/intelrdt/intelrdt_test.go @@ -101,13 +101,14 @@ func TestApply(t *testing.T) { helper := NewIntelRdtTestUtil(t) const closID = "test-clos" + closPath := filepath.Join(helper.IntelRdtPath, closID) helper.config.IntelRdt.ClosID = closID - intelrdt := newManager(helper.config, "", helper.IntelRdtPath) + intelrdt := newManager(helper.config, "container-1", closPath) if err := intelrdt.Apply(1234); err == nil { t.Fatal("unexpected success when applying pid") } - if _, err := os.Stat(filepath.Join(helper.IntelRdtPath, closID)); err == nil { + if _, err := os.Stat(closPath); err == nil { t.Fatal("closid dir should not exist") }