Repository: opencontainers/runc
Pull request #3354 (2022-01-27 19:11:22)

Factory cleanup
_This used to be part of #3316._

This set cleanups LinuxFactory, removing some interfaces, option functions etc. Lots of changes, but mostly removal.

This removes about 6K of code and 5K of data from the binary, reducing its overall size by 0.1% (not counting debuginfo, i.e. for a stripped binary) without any change in functionality.

More importantly, this improves readability a notch by simplifying some code and data structures, and removing about 200 lines of code and tests.

kolyshkin: Release job failed because of a network glitch:

> E: Failed to fetch https://provo-mirror.opensuse.org/repositories/devel:/tools:/criu/Debian_11/amd64/criu_3.16.1-3_amd64.deb  > Could not connect to provo-mirror.opensuse.org:443 (91.193.113.70). - connect (111: Connection refused)

Restarted.
kolyshkin: @opencontainers/runc-maintainers PTAL (I have more changes pending that depend on these commits)

Patch:
diff --git a/libcontainer/README.md b/libcontainer/README.md
index 658eb431..79388eaf 100644
--- a/libcontainer/README.md
+++ b/libcontainer/README.md
@@ -45,7 +45,7 @@ Then to create a container you first have to initialize an instance of a factory
 that will handle the creation and initialization for a container.
 
 ```go
-factory, err := libcontainer.New("/var/lib/container", libcontainer.InitArgs(os.Args[0], "init"))
+factory, err := libcontainer.New("/var/lib/container")
 if err != nil {
 	logrus.Fatal(err)
 	return
diff --git a/libcontainer/configs/validate/rootless.go b/libcontainer/configs/validate/rootless.go
index 9a6e5eb3..7afdb431 100644
--- a/libcontainer/configs/validate/rootless.go
+++ b/libcontainer/configs/validate/rootless.go
@@ -8,9 +8,9 @@ import (
 	"github.com/opencontainers/runc/libcontainer/configs"
 )
 
-// rootlessEUID makes sure that the config can be applied when runc
+// rootlessEUIDCheck makes sure that the config can be applied when runc
 // is being executed as a non-root user (euid != 0) in the current user namespace.
-func (v *ConfigValidator) rootlessEUID(config *configs.Config) error {
+func rootlessEUIDCheck(config *configs.Config) error {
 	if !config.RootlessEUID {
 		return nil
 	}
diff --git a/libcontainer/configs/validate/validator.go b/libcontainer/configs/validate/validator.go
index 6493124a..6972ec9c 100644
--- a/libcontainer/configs/validate/validator.go
+++ b/libcontainer/configs/validate/validator.go
@@ -16,30 +16,19 @@ import (
 	"golang.org/x/sys/unix"
 )
 
-type Validator interface {
-	Validate(*configs.Config) error
-}
-
-func New() Validator {
-	return &ConfigValidator{}
-}
-
-type ConfigValidator struct{}
-
 type check func(config *configs.Config) error
 
-func (v *ConfigValidator) Validate(config *configs.Config) error {
+func Validate(config *configs.Config) error {
 	checks := []check{
-		v.cgroups,
-		v.rootfs,
-		v.network,
-		v.hostname,
-		v.security,
-		v.usernamespace,
-		v.cgroupnamespace,
-		v.sysctl,
-		v.intelrdt,
-		v.rootlessEUID,
+		cgroupsCheck,
+		rootfs,
+		network,
+		hostname,
+		security,
+		namespaces,
+		sysctl,
+		intelrdtCheck,
+		rootlessEUIDCheck,
 	}
 	for _, c := range checks {
 		if err := c(config); err != nil {
@@ -48,7 +37,7 @@ func (v *ConfigValidator) Validate(config *configs.Config) error {
 	}
 	// Relaxed validation rules for backward compatibility
 	warns := []check{
-		v.mounts, // TODO (runc v1.x.x): make this an error instead of a warning
+		mounts, // TODO (runc v1.x.x): make this an error instead of a warning
 	}
 	for _, c := range warns {
 		if err := c(config); err != nil {
@@ -60,7 +49,7 @@ func (v *ConfigValidator) Validate(config *configs.Config) error {
 
 // rootfs validates if the rootfs is an absolute path and is not a symlink
 // to the container's root filesystem.
-func (v *ConfigValidator) rootfs(config *configs.Config) error {
+func rootfs(config *configs.Config) error {
 	if _, err := os.Stat(config.Rootfs); err != nil {
 		return fmt.Errorf("invalid rootfs: %w", err)
 	}
@@ -77,7 +66,7 @@ func (v *ConfigValidator) rootfs(config *configs.Config) error {
 	return nil
 }
 
-func (v *ConfigValidator) network(config *configs.Config) error {
+func network(config *configs.Config) error {
 	if !config.Namespaces.Contains(configs.NEWNET) {
 		if len(config.Networks) > 0 || len(config.Routes) > 0 {
 			return errors.New("unable to apply network settings without a private NET namespace")
@@ -86,14 +75,14 @@ func (v *ConfigValidator) network(config *configs.Config) error {
 	return nil
 }
 
-func (v *ConfigValidator) hostname(config *configs.Config) error {
+func hostname(config *configs.Config) error {
 	if config.Hostname != "" && !config.Namespaces.Contains(configs.NEWUTS) {
 		return errors.New("unable to set hostname without a private UTS namespace")
 	}
 	return nil
 }
 
-func (v *ConfigValidator) security(config *configs.Config) error {
+func security(config *configs.Config) error {
 	// restrict sys without mount namespace
 	if (len(config.MaskPaths) > 0 || len(config.ReadonlyPaths) > 0) &&
 		!config.Namespaces.Contains(configs.NEWNS) {
@@ -106,7 +95,7 @@ func (v *ConfigValidator) security(config *configs.Config) error {
 	return nil
 }
 
-func (v *ConfigValidator) usernamespace(config *configs.Config) error {
+func namespaces(config *configs.Config) error {
 	if config.Namespaces.Contains(configs.NEWUSER) {
 		if _, err := os.Stat("/proc/self/ns/user"); os.IsNotExist(err) {
 			return errors.New("USER namespaces aren't enabled in the kernel")
@@ -116,15 +105,13 @@ func (v *ConfigValidator) usernamespace(config *configs.Config) error {
 			return errors.New("User namespace mappings specified, but USER namespace isn't enabled in the config")
 		}
 	}
-	return nil
-}
 
-func (v *ConfigValidator) cgroupnamespace(config *configs.Config) error {
 	if config.Namespaces.Contains(configs.NEWCGROUP) {
 		if _, err := os.Stat("/proc/self/ns/cgroup"); os.IsNotExist(err) {
 			return errors.New("cgroup namespaces aren't enabled in the kernel")
 		}
 	}
+
 	return nil
 }
 
@@ -161,7 +148,7 @@ func convertSysctlVariableToDotsSeparator(val string) string {
 // sysctl validates that the specified sysctl keys are valid or not.
 // /proc/sys isn't completely namespaced and depending on which namespaces
 // are specified, a subset of sysctls are permitted.
-func (v *ConfigValidator) sysctl(config *configs.Config) error {
+func sysctl(config *configs.Config) error {
 	validSysctlMap := map[string]bool{
 		"kernel.msgmax":          true,
 		"kernel.msgmnb":          true,
@@ -227,7 +214,7 @@ func (v *ConfigValidator) sysctl(config *configs.Config) error {
 	return nil
 }
 
-func (v *ConfigValidator) intelrdt(config *configs.Config) error {
+func intelrdtCheck(config *configs.Config) error {
 	if config.IntelRdt != nil {
 		if !intelrdt.IsCATEnabled() && !intelrdt.IsMBAEnabled() {
 			return errors.New("intelRdt is specified in config, but Intel RDT is not supported or enabled")
@@ -248,7 +235,7 @@ func (v *ConfigValidator) intelrdt(config *configs.Config) error {
 	return nil
 }
 
-func (v *ConfigValidator) cgroups(config *configs.Config) error {
+func cgroupsCheck(config *configs.Config) error {
 	c := config.Cgroups
 	if c == nil {
 		return nil
@@ -277,7 +264,7 @@ func (v *ConfigValidator) cgroups(config *configs.Config) error {
 	return nil
 }
 
-func (v *ConfigValidator) mounts(config *configs.Config) error {
+func mounts(config *configs.Config) error {
 	for _, m := range config.Mounts {
 		if !filepath.IsAbs(m.Destination) {
 			return fmt.Errorf("invalid mount %+v: mount destination not absolute", m)
diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go
index 91bea2a3..8af9ac2c 100644
--- a/libcontainer/container_linux.go
+++ b/libcontainer/container_linux.go
@@ -23,6 +23,7 @@ import (
 	"github.com/opencontainers/runtime-spec/specs-go"
 	"github.com/sirupsen/logrus"
 	"github.com/vishvananda/netlink/nl"
+	"golang.org/x/sys/execabs"
 	"golang.org/x/sys/unix"
 	"google.golang.org/protobuf/proto"
 
@@ -40,13 +41,9 @@ type linuxContainer struct {
 	root                 string
 	config               *configs.Config
 	cgroupManager        cgroups.Manager
-	intelRdtManager      intelrdt.Manager
-	initPath             string
-	initArgs             []string
+	intelRdtManager      *intelrdt.Manager
 	initProcess          parentProcess
 	initProcessStartTime uint64
-	newuidmapPath        string
-	newgidmapPath        string
 	m                    sync.Mutex
 	criuVersion          int
 	state                containerState
@@ -481,8 +478,8 @@ func (c *linuxContainer) newParentProcess(p *Process) (parentProcess, error) {
 }
 
 func (c *linuxContainer) commandTemplate(p *Process, childInitPipe *os.File, childLogPipe *os.File) *exec.Cmd {
-	cmd := exec.Command(c.initPath, c.initArgs[1:]...)
-	cmd.Args[0] = c.initArgs[0]
+	cmd := exec.Command("/proc/self/exe", "init")
+	cmd.Args[0] = os.Args[0]
 	cmd.Stdin = p.Stdin
 	cmd.Stdout = p.Stdout
 	cmd.Stderr = p.Stderr
@@ -2150,11 +2147,16 @@ func (c *linuxContainer) bootstrapData(cloneFlags uintptr, nsMaps map[configs.Na
 	if !joinExistingUser {
 		// write uid mappings
 		if len(c.config.UidMappings) > 0 {
-			if c.config.RootlessEUID && c.newuidmapPath != "" {
-				r.AddData(&Bytemsg{
-					Type:  UidmapPathAttr,
-					Value: []byte(c.newuidmapPath),
-				})
+			if c.config.RootlessEUID {
+				// We resolve the paths for new{u,g}idmap from
+				// the context of runc to avoid doing a path
+				// lookup in the nsexec context.
+				if path, err := execabs.LookPath("newuidmap"); err == nil {
+					r.AddData(&Bytemsg{
+						Type:  UidmapPathAttr,
+						Value: []byte(path),
+					})
+				}
 			}
 			b, err := encodeIDMapping(c.config.UidMappings)
 			if err != nil {
@@ -2176,11 +2178,13 @@ func (c *linuxContainer) bootstrapData(cloneFlags uintptr, nsMaps map[configs.Na
 				Type:  GidmapAttr,
 				Value: b,
 			})
-			if c.config.RootlessEUID && c.newgidmapPath != "" {
-				r.AddData(&Bytemsg{
-					Type:  GidmapPathAttr,
-					Value: []byte(c.newgidmapPath),
-				})
+			if c.config.RootlessEUID {
+				if path, err := execabs.LookPath("newgidmap"); err == nil {
+					r.AddData(&Bytemsg{
+						Type:  GidmapPathAttr,
+						Value: []byte(path),
+					})
+				}
 			}
 			if requiresRootOrMappingTool(c.config) {
 				r.AddData(&Boolmsg{
diff --git a/libcontainer/factory_linux.go b/libcontainer/factory_linux.go
index d72a0532..a0ea4fe3 100644
--- a/libcontainer/factory_linux.go
+++ b/libcontainer/factory_linux.go
@@ -5,7 +5,6 @@ import (
 	"errors"
 	"fmt"
 	"os"
-	"path/filepath"
 	"regexp"
 	"runtime/debug"
 	"strconv"
@@ -29,39 +28,6 @@ const (
 
 var idRegex = regexp.MustCompile(`^[\w+-\.]+$`)
 
-// InitArgs returns an options func to configure a LinuxFactory with the
-// provided init binary path and arguments.
-func InitArgs(args ...string) func(*LinuxFactory) error {
-	return func(l *LinuxFactory) (err error) {
-		if len(args) > 0 {
-			// Resolve relative paths to ensure that its available
-			// after directory changes.
-			if args[0], err = filepath.Abs(args[0]); err != nil {
-				// The only error returned from filepath.Abs is
-				// the one from os.Getwd, i.e. a system error.
-				return err
-			}
-		}
-
-		l.InitArgs = args
-		return nil
-	}
-}
-
-// IntelRdtfs is an options func to configure a LinuxFactory to return
-// containers that use the Intel RDT "resource control" filesystem to
-// create and manage Intel RDT resources (e.g., L3 cache, memory bandwidth).
-func IntelRdtFs(l *LinuxFactory) error {
-	if !intelrdt.IsCATEnabled() && !intelrdt.IsMBAEnabled() {
-		l.NewIntelRdtManager = nil
-	} else {
-		l.NewIntelRdtManager = func(config *configs.Config, id string, path string) intelrdt.Manager {
-			return intelrdt.NewManager(config, id, path)
-		}
-	}
-	return nil
-}
-
 // TmpfsRoot is an option func to mount LinuxFactory.Root to tmpfs.
 func TmpfsRoot(l *LinuxFactory) error {
 	mounted, err := mountinfo.Mounted(l.Root)
@@ -85,10 +51,7 @@ func New(root string, options ...func(*LinuxFactory) error) (Factory, error) {
 		}
 	}
 	l := &LinuxFactory{
-		Root:      root,
-		InitPath:  "/proc/self/exe",
-		InitArgs:  []string{os.Args[0], "init"},
-		Validator: validate.New(),
+		Root: root,
 	}
 
 	for _, opt := range options {
@@ -106,25 +69,6 @@ func New(root string, options ...func(*LinuxFactory) error) (Factory, error) {
 type LinuxFactory struct {
 	// Root directory for the factory to store state.
 	Root string
-
-	// InitPath is the path for calling the init responsibilities for spawning
-	// a container.
-	InitPath string
-
-	// InitArgs are arguments for calling the init responsibilities for spawning
-	// a container.
-	InitArgs []string
-
-	// New{u,g}idmapPath is the path to the binaries used for mapping with
-	// rootless containers.
-	NewuidmapPath string
-	NewgidmapPath string
-
-	// Validator provides validation to container configurations.
-	Validator validate.Validator
-
-	// NewIntelRdtManager returns an initialized Intel RDT manager for a single container.
-	NewIntelRdtManager func(config *configs.Config, id string, path string) intelrdt.Manager
 }
 
 func (l *LinuxFactory) Create(id string, config *configs.Config) (Container, error) {
@@ -134,7 +78,7 @@ func (l *LinuxFactory) Create(id string, config *configs.Config) (Container, err
 	if err := l.validateID(id); err != nil {
 		return nil, err
 	}
-	if err := l.Validator.Validate(config); err != nil {
+	if err := validate.Validate(config); err != nil {
 		return nil, err
 	}
 	containerRoot, err := securejoin.SecureJoin(l.Root, id)
@@ -185,17 +129,11 @@ func (l *LinuxFactory) Create(id string, config *configs.Config) (Container, err
 		return nil, err
 	}
 	c := &linuxContainer{
-		id:            id,
-		root:          containerRoot,
-		config:        config,
-		initPath:      l.InitPath,
-		initArgs:      l.InitArgs,
-		newuidmapPath: l.NewuidmapPath,
-		newgidmapPath: l.NewgidmapPath,
-		cgroupManager: cm,
-	}
-	if l.NewIntelRdtManager != nil {
-		c.intelRdtManager = l.NewIntelRdtManager(config, id, "")
+		id:              id,
+		root:            containerRoot,
+		config:          config,
+		cgroupManager:   cm,
+		intelRdtManager: intelrdt.NewManager(config, id, ""),
 	}
 	c.state = &stoppedState{c: c}
 	return c, nil
@@ -231,17 +169,11 @@ func (l *LinuxFactory) Load(id string) (Container, error) {
 		initProcessStartTime: state.InitProcessStartTime,
 		id:                   id,
 		config:               &state.Config,
-		initPath:             l.InitPath,
-		initArgs:             l.InitArgs,
-		newuidmapPath:        l.NewuidmapPath,
-		newgidmapPath:        l.NewgidmapPath,
 		cgroupManager:        cm,
+		intelRdtManager:      intelrdt.NewManager(&state.Config, id, state.IntelRdtPath),
 		root:                 containerRoot,
 		created:              state.Created,
 	}
-	if l.NewIntelRdtManager != nil {
-		c.intelRdtManager = l.NewIntelRdtManager(&state.Config, id, state.IntelRdtPath)
-	}
 	c.state = &loadedState{c: c}
 	if err := c.refreshState(); err != nil {
 		return nil, err
@@ -365,24 +297,6 @@ func (l *LinuxFactory) validateID(id string) error {
 	return nil
 }
 
-// NewuidmapPath returns an option func to configure a LinuxFactory with the
-// provided ..
-func NewuidmapPath(newuidmapPath string) func(*LinuxFactory) error {
-	return func(l *LinuxFactory) error {
-		l.NewuidmapPath = newuidmapPath
-		return nil
-	}
-}
-
-// NewgidmapPath returns an option func to configure a LinuxFactory with the
-// provided ..
-func NewgidmapPath(newgidmapPath string) func(*LinuxFactory) error {
-	return func(l *LinuxFactory) error {
-		l.NewgidmapPath = newgidmapPath
-		return nil
-	}
-}
-
 func parseMountFds() ([]int, error) {
 	fdsJSON := os.Getenv("_LIBCONTAINER_MOUNT_FDS")
 	if fdsJSON == "" {
diff --git a/libcontainer/intelrdt/intelrdt.go b/libcontainer/intelrdt/intelrdt.go
index 1fe1ec3e..3953f930 100644
--- a/libcontainer/intelrdt/intelrdt.go
+++ b/libcontainer/intelrdt/intelrdt.go
@@ -146,34 +146,27 @@ import (
  * }
  */
 
-type Manager interface {
-	// Applies Intel RDT configuration to the process with the specified pid
-	Apply(pid int) error
-
-	// Returns statistics for Intel RDT
-	GetStats() (*Stats, error)
-
-	// Destroys the Intel RDT container-specific 'container_id' group
-	Destroy() error
-
-	// Returns Intel RDT path to save in a state file and to be able to
-	// restore the object later
-	GetPath() string
-
-	// Set Intel RDT "resource control" filesystem as configured.
-	Set(container *configs.Config) error
-}
-
-// This implements interface Manager
-type intelRdtManager struct {
+type Manager struct {
 	mu     sync.Mutex
 	config *configs.Config
 	id     string
 	path   string
 }
 
-func NewManager(config *configs.Config, id string, path string) Manager {
-	return &intelRdtManager{
+// NewManager returns a new instance of Manager, or nil, if the Intel RDT
+// functionality is not available from hardware or not enabled in the kernel.
+func NewManager(config *configs.Config, id string, path string) *Manager {
+	if _, err := Root(); err != nil {
+		// Intel RDT is not available.
+		return nil
+	}
+	return newManager(config, id, path)
+}
+
+// newManager is the same as NewManager, except it does not check if the feature
+// is actually available. Used by unit tests that mock intelrdt paths.
+func newManager(config *configs.Config, id string, path string) *Manager {
+	return &Manager{
 		config: config,
 		id:     id,
 		path:   path,
@@ -507,7 +500,7 @@ func IsMBAScEnabled() bool {
 }
 
 // Get the path of the clos group in "resource control" filesystem that the container belongs to
-func (m *intelRdtManager) getIntelRdtPath() (string, error) {
+func (m *Manager) getIntelRdtPath() (string, error) {
 	rootPath, err := Root()
 	if err != nil {
 		return "", err
@@ -522,7 +515,7 @@ func (m *intelRdtManager) getIntelRdtPath() (string, error) {
 }
 
 // Applies Intel RDT configuration to the process with the specified pid
-func (m *intelRdtManager) Apply(pid int) (err error) {
+func (m *Manager) Apply(pid int) (err error) {
 	// If intelRdt is not specified in config, we do nothing
 	if m.config.IntelRdt == nil {
 		return nil
@@ -557,7 +550,7 @@ func (m *intelRdtManager) Apply(pid int) (err error) {
 }
 
 // Destroys the Intel RDT container-specific 'container_id' group
-func (m *intelRdtManager) Destroy() error {
+func (m *Manager) Destroy() error {
 	// Don't remove resctrl group if closid has been explicitly specified. The
 	// group is likely externally managed, i.e. by some other entity than us.
 	// There are probably other containers/tasks sharing the same group.
@@ -574,7 +567,7 @@ func (m *intelRdtManager) Destroy() error {
 
 // Returns Intel RDT path to save in a state file and to be able to
 // restore the object later
-func (m *intelRdtManager) GetPath() string {
+func (m *Manager) GetPath() string {
 	if m.path == "" {
 		m.path, _ = m.getIntelRdtPath()
 	}
@@ -582,7 +575,7 @@ func (m *intelRdtManager) GetPath() string {
 }
 
 // Returns statistics for Intel RDT
-func (m *intelRdtManager) GetStats() (*Stats, error) {
+func (m *Manager) GetStats() (*Stats, error) {
 	// If intelRdt is not specified in config
 	if m.config.IntelRdt == nil {
 		return nil, nil
@@ -668,7 +661,7 @@ func (m *intelRdtManager) GetStats() (*Stats, error) {
 }
 
 // Set Intel RDT "resource control" filesystem as configured.
-func (m *intelRdtManager) Set(container *configs.Config) error {
+func (m *Manager) Set(container *configs.Config) error {
 	// About L3 cache schema:
 	// It has allocation bitmasks/values for L3 cache on each socket,
 	// which contains L3 cache id and capacity bitmask (CBM).
diff --git a/libcontainer/process_linux.go b/libcontainer/process_linux.go
index 97f28a1a..ae91d5b9 100644
--- a/libcontainer/process_linux.go
+++ b/libcontainer/process_linux.go
@@ -303,7 +303,7 @@ type initProcess struct {
 	logFilePair     filePair
 	config          *initConfig
 	manager         cgroups.Manager
-	intelRdtManager intelrdt.Manager
+	intelRdtManager *intelrdt.Manager
 	container       *linuxContainer
 	fds             []string
 	process         *Process
diff --git a/utils_linux.go b/utils_linux.go
index 9f7619d6..c2214a23 100644
--- a/utils_linux.go
+++ b/utils_linux.go
@@ -5,7 +5,6 @@ import (
 	"fmt"
 	"net"
 	"os"
-	"os/exec"
 	"path/filepath"
 	"strconv"
 
@@ -32,23 +31,7 @@ func loadFactory(context *cli.Context) (libcontainer.Factory, error) {
 		return nil, err
 	}
 
-	intelRdtManager := libcontainer.IntelRdtFs
-
-	// We resolve the paths for {newuidmap,newgidmap} from the context of runc,
-	// to avoid doing a path lookup in the nsexec context. TODO: The binary
-	// names are not currently configurable.
-	newuidmap, err := exec.LookPath("newuidmap")
-	if err != nil {
-		newuidmap = ""
-	}
-	newgidmap, err := exec.LookPath("newgidmap")
-	if err != nil {
-		newgidmap = ""
-	}
-
-	return libcontainer.New(abs, intelRdtManager,
-		libcontainer.NewuidmapPath(newuidmap),
-		libcontainer.NewgidmapPath(newgidmap))
+	return libcontainer.New(abs)
 }
 
 // getContainer returns the specified container instance by loading it from state
diff --git a/vendor/golang.org/x/sys/execabs/execabs.go b/vendor/golang.org/x/sys/execabs/execabs.go
new file mode 100644
index 00000000..78192498
--- /dev/null
+++ b/vendor/golang.org/x/sys/execabs/execabs.go
@@ -0,0 +1,102 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package execabs is a drop-in replacement for os/exec
+// that requires PATH lookups to find absolute paths.
+// That is, execabs.Command("cmd") runs the same PATH lookup
+// as exec.Command("cmd"), but if the result is a path
+// which is relative, the Run and Start methods will report
+// an error instead of running the executable.
+//
+// See https://blog.golang.org/path-security for more information
+// about when it may be necessary or appropriate to use this package.
+package execabs
+
+import (
+	"context"
+	"fmt"
+	"os/exec"
+	"path/filepath"
+	"reflect"
+	"unsafe"
+)
+
+// ErrNotFound is the error resulting if a path search failed to find an executable file.
+// It is an alias for exec.ErrNotFound.
+var ErrNotFound = exec.ErrNotFound
+
+// Cmd represents an external command being prepared or run.
+// It is an alias for exec.Cmd.
+type Cmd = exec.Cmd
+
+// Error is returned by LookPath when it fails to classify a file as an executable.
+// It is an alias for exec.Error.
+type Error = exec.Error
+
+// An ExitError reports an unsuccessful exit by a command.
+// It is an alias for exec.ExitError.
+type ExitError = exec.ExitError
+
+func relError(file, path string) error {
+	return fmt.Errorf("%s resolves to executable in current directory (.%c%s)", file, filepath.Separator, path)
+}
+
+// LookPath searches for an executable named file in the directories
+// named by the PATH environment variable. If file contains a slash,
+// it is tried directly and the PATH is not consulted. The result will be
+// an absolute path.
+//
+// LookPath differs from exec.LookPath in its handling of PATH lookups,
+// which are used for file names without slashes. If exec.LookPath's
+// PATH lookup would have returned an executable from the current directory,
+// LookPath instead returns an error.
+func LookPath(file string) (string, error) {
+	path, err := exec.LookPath(file)
+	if err != nil {
+		return "", err
+	}
+	if filepath.Base(file) == file && !filepath.IsAbs(path) {
+		return "", relError(file, path)
+	}
+	return path, nil
+}
+
+func fixCmd(name string, cmd *exec.Cmd) {
+	if filepath.Base(name) == name && !filepath.IsAbs(cmd.Path) {
+		// exec.Command was called with a bare binary name and
+		// exec.LookPath returned a path which is not absolute.
+		// Set cmd.lookPathErr and clear cmd.Path so that it
+		// cannot be run.
+		lookPathErr := (*error)(unsafe.Pointer(reflect.ValueOf(cmd).Elem().FieldByName("lookPathErr").Addr().Pointer()))
+		if *lookPathErr == nil {
+			*lookPathErr = relError(name, cmd.Path)
+		}
+		cmd.Path = ""
+	}
+}
+
+// CommandContext is like Command but includes a context.
+//
+// The provided context is used to kill the process (by calling os.Process.Kill)
+// if the context becomes done before the command completes on its own.
+func CommandContext(ctx context.Context, name string, arg ...string) *exec.Cmd {
+	cmd := exec.CommandContext(ctx, name, arg...)
+	fixCmd(name, cmd)
+	return cmd
+
+}
+
+// Command returns the Cmd struct to execute the named program with the given arguments.
+// See exec.Command for most details.
+//
+// Command differs from exec.Command in its handling of PATH lookups,
+// which are used when the program name contains no slashes.
+// If exec.Command would have returned an exec.Cmd configured to run an
+// executable from the current directory, Command instead
+// returns an exec.Cmd that will return an error from Start or Run.
+func Command(name string, arg ...string) *exec.Cmd {
+	cmd := exec.Command(name, arg...)
+	fixCmd(name, cmd)
+	return cmd
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index e6cfb193..17a6794f 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -72,6 +72,7 @@ github.com/vishvananda/netns
 golang.org/x/net/bpf
 # golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c
 ## explicit
+golang.org/x/sys/execabs
 golang.org/x/sys/internal/unsafeheader
 golang.org/x/sys/unix
 golang.org/x/sys/windows


Test patch:
diff --git a/libcontainer/configs/validate/rootless_test.go b/libcontainer/configs/validate/rootless_test.go
index 59d15575..0657abf4 100644
--- a/libcontainer/configs/validate/rootless_test.go
+++ b/libcontainer/configs/validate/rootless_test.go
@@ -34,10 +34,8 @@ func rootlessEUIDConfig() *configs.Config {
 }
 
 func TestValidateRootlessEUID(t *testing.T) {
-	validator := New()
-
 	config := rootlessEUIDConfig()
-	if err := validator.Validate(config); err != nil {
+	if err := Validate(config); err != nil {
 		t.Errorf("Expected error to not occur: %+v", err)
 	}
 }
@@ -45,31 +43,25 @@ func TestValidateRootlessEUID(t *testing.T) {
 /* rootlessEUIDMappings */
 
 func TestValidateRootlessEUIDUserns(t *testing.T) {
-	validator := New()
-
 	config := rootlessEUIDConfig()
 	config.Namespaces = nil
-	if err := validator.Validate(config); err == nil {
+	if err := Validate(config); err == nil {
 		t.Errorf("Expected error to occur if user namespaces not set")
 	}
 }
 
 func TestValidateRootlessEUIDMappingUid(t *testing.T) {
-	validator := New()
-
 	config := rootlessEUIDConfig()
 	config.UidMappings = nil
-	if err := validator.Validate(config); err == nil {
+	if err := Validate(config); err == nil {
 		t.Errorf("Expected error to occur if no uid mappings provided")
 	}
 }
 
 func TestValidateNonZeroEUIDMappingGid(t *testing.T) {
-	validator := New()
-
 	config := rootlessEUIDConfig()
 	config.GidMappings = nil
-	if err := validator.Validate(config); err == nil {
+	if err := Validate(config); err == nil {
 		t.Errorf("Expected error to occur if no gid mappings provided")
 	}
 }
@@ -78,8 +70,6 @@ func TestValidateNonZeroEUIDMappingGid(t *testing.T) {
 
 func TestValidateRootlessEUIDMountUid(t *testing.T) {
 	config := rootlessEUIDConfig()
-	validator := New()
-
 	config.Mounts = []*configs.Mount{
 		{
 			Source:      "devpts",
@@ -88,37 +78,35 @@ func TestValidateRootlessEUIDMountUid(t *testing.T) {
 		},
 	}
 
-	if err := validator.Validate(config); err != nil {
+	if err := Validate(config); err != nil {
 		t.Errorf("Expected error to not occur when uid= not set in mount options: %+v", err)
 	}
 
 	config.Mounts[0].Data = "uid=5"
-	if err := validator.Validate(config); err == nil {
+	if err := Validate(config); err == nil {
 		t.Errorf("Expected error to occur when setting uid=5 in mount options")
 	}
 
 	config.Mounts[0].Data = "uid=0"
-	if err := validator.Validate(config); err != nil {
+	if err := Validate(config); err != nil {
 		t.Errorf("Expected error to not occur when setting uid=0 in mount options: %+v", err)
 	}
 
 	config.Mounts[0].Data = "uid=2"
 	config.UidMappings[0].Size = 10
-	if err := validator.Validate(config); err != nil {
+	if err := Validate(config); err != nil {
 		t.Errorf("Expected error to not occur when setting uid=2 in mount options and UidMapping[0].size is 10")
 	}
 
 	config.Mounts[0].Data = "uid=20"
 	config.UidMappings[0].Size = 10
-	if err := validator.Validate(config); err == nil {
+	if err := Validate(config); err == nil {
 		t.Errorf("Expected error to occur when setting uid=20 in mount options and UidMapping[0].size is 10")
 	}
 }
 
 func TestValidateRootlessEUIDMountGid(t *testing.T) {
 	config := rootlessEUIDConfig()
-	validator := New()
-
 	config.Mounts = []*configs.Mount{
 		{
 			Source:      "devpts",
@@ -127,29 +115,29 @@ func TestValidateRootlessEUIDMountGid(t *testing.T) {
 		},
 	}
 
-	if err := validator.Validate(config); err != nil {
+	if err := Validate(config); err != nil {
 		t.Errorf("Expected error to not occur when gid= not set in mount options: %+v", err)
 	}
 
 	config.Mounts[0].Data = "gid=5"
-	if err := validator.Validate(config); err == nil {
+	if err := Validate(config); err == nil {
 		t.Errorf("Expected error to occur when setting gid=5 in mount options")
 	}
 
 	config.Mounts[0].Data = "gid=0"
-	if err := validator.Validate(config); err != nil {
+	if err := Validate(config); err != nil {
 		t.Errorf("Expected error to not occur when setting gid=0 in mount options: %+v", err)
 	}
 
 	config.Mounts[0].Data = "gid=5"
 	config.GidMappings[0].Size = 10
-	if err := validator.Validate(config); err != nil {
+	if err := Validate(config); err != nil {
 		t.Errorf("Expected error to not occur when setting gid=5 in mount options and GidMapping[0].size is 10")
 	}
 
 	config.Mounts[0].Data = "gid=11"
 	config.GidMappings[0].Size = 10
-	if err := validator.Validate(config); err == nil {
+	if err := Validate(config); err == nil {
 		t.Errorf("Expected error to occur when setting gid=11 in mount options and GidMapping[0].size is 10")
 	}
 }
diff --git a/libcontainer/configs/validate/validator_test.go b/libcontainer/configs/validate/validator_test.go
index 5181333f..59a40338 100644
--- a/libcontainer/configs/validate/validator_test.go
+++ b/libcontainer/configs/validate/validator_test.go
@@ -14,8 +14,7 @@ func TestValidate(t *testing.T) {
 		Rootfs: "/var",
 	}
 
-	validator := New()
-	err := validator.Validate(config)
+	err := Validate(config)
 	if err != nil {
 		t.Errorf("Expected error to not occur: %+v", err)
 	}
@@ -32,8 +31,7 @@ func TestValidateWithInvalidRootfs(t *testing.T) {
 		Rootfs: dir,
 	}
 
-	validator := New()
-	err := validator.Validate(config)
+	err := Validate(config)
 	if err == nil {
 		t.Error("Expected error to occur but it was nil")
 	}
@@ -47,8 +45,7 @@ func TestValidateNetworkWithoutNETNamespace(t *testing.T) {
 		Networks:   []*configs.Network{network},
 	}
 
-	validator := New()
-	err := validator.Validate(config)
+	err := Validate(config)
 	if err == nil {
 		t.Error("Expected error to occur but it was nil")
 	}
@@ -62,8 +59,7 @@ func TestValidateNetworkRoutesWithoutNETNamespace(t *testing.T) {
 		Routes:     []*configs.Route{route},
 	}
 
-	validator := New()
-	err := validator.Validate(config)
+	err := Validate(config)
 	if err == nil {
 		t.Error("Expected error to occur but it was nil")
 	}
@@ -80,8 +76,7 @@ func TestValidateHostname(t *testing.T) {
 		),
 	}
 
-	validator := New()
-	err := validator.Validate(config)
+	err := Validate(config)
 	if err != nil {
 		t.Errorf("Expected error to not occur: %+v", err)
 	}
@@ -93,8 +88,7 @@ func TestValidateHostnameWithoutUTSNamespace(t *testing.T) {
 		Hostname: "runc",
 	}
 
-	validator := New()
-	err := validator.Validate(config)
+	err := Validate(config)
 	if err == nil {
 		t.Error("Expected error to occur but it was nil")
 	}
@@ -111,8 +105,7 @@ func TestValidateSecurityWithMaskPaths(t *testing.T) {
 		),
 	}
 
-	validator := New()
-	err := validator.Validate(config)
+	err := Validate(config)
 	if err != nil {
 		t.Errorf("Expected error to not occur: %+v", err)
 	}
@@ -129,8 +122,7 @@ func TestValidateSecurityWithROPaths(t *testing.T) {
 		),
 	}
 
-	validator := New()
-	err := validator.Validate(config)
+	err := Validate(config)
 	if err != nil {
 		t.Errorf("Expected error to not occur: %+v", err)
 	}
@@ -143,8 +135,7 @@ func TestValidateSecurityWithoutNEWNS(t *testing.T) {
 		ReadonlyPaths: []string{"/proc/sys"},
 	}
 
-	validator := New()
-	err := validator.Validate(config)
+	err := Validate(config)
 	if err == nil {
 		t.Error("Expected error to occur but it was nil")
 	}
@@ -163,8 +154,7 @@ func TestValidateUsernamespace(t *testing.T) {
 		),
 	}
 
-	validator := New()
-	err := validator.Validate(config)
+	err := Validate(config)
 	if err != nil {
 		t.Errorf("expected error to not occur %+v", err)
 	}
@@ -177,8 +167,7 @@ func TestValidateUsernamespaceWithoutUserNS(t *testing.T) {
 		UidMappings: []configs.IDMap{uidMap},
 	}
 
-	validator := New()
-	err := validator.Validate(config)
+	err := Validate(config)
 	if err == nil {
 		t.Error("Expected error to occur but it was nil")
 	}
@@ -226,8 +215,7 @@ func TestValidateSysctl(t *testing.T) {
 			Sysctl: map[string]string{k: v},
 		}
 
-		validator := New()
-		err := validator.Validate(config)
+		err := Validate(config)
 		if err == nil {
 			t.Error("Expected error to occur but it was nil")
 		}
@@ -259,8 +247,7 @@ func TestValidateValidSysctl(t *testing.T) {
 			},
 		}
 
-		validator := New()
-		err := validator.Validate(config)
+		err := Validate(config)
 		if err != nil {
 			t.Errorf("Expected error to not occur with {%s=%s} but got: %q", k, v, err)
 		}
@@ -281,8 +268,7 @@ func TestValidateSysctlWithSameNs(t *testing.T) {
 		),
 	}
 
-	validator := New()
-	err := validator.Validate(config)
+	err := Validate(config)
 	if err == nil {
 		t.Error("Expected error to occur but it was nil")
 	}
@@ -323,8 +309,7 @@ func TestValidateSysctlWithBindHostNetNS(t *testing.T) {
 		),
 	}
 
-	validator := New()
-	if err := validator.Validate(config); err == nil {
+	if err := Validate(config); err == nil {
 		t.Error("Expected error to occur but it was nil")
 	}
 }
@@ -336,8 +321,7 @@ func TestValidateSysctlWithoutNETNamespace(t *testing.T) {
 		Namespaces: []configs.Namespace{},
 	}
 
-	validator := New()
-	err := validator.Validate(config)
+	err := Validate(config)
 	if err == nil {
 		t.Error("Expected error to occur but it was nil")
 	}
@@ -358,8 +342,6 @@ func TestValidateMounts(t *testing.T) {
 		{isErr: false, dest: "/abs/but/../unclean"},
 	}
 
-	validator := New()
-
 	for _, tc := range testCases {
 		config := &configs.Config{
 			Rootfs: "/var",
@@ -368,7 +350,7 @@ func TestValidateMounts(t *testing.T) {
 			},
 		}
 
-		err := validator.Validate(config)
+		err := Validate(config)
 		if tc.isErr && err == nil {
 			t.Errorf("mount dest: %s, expected error, got nil", tc.dest)
 		}
diff --git a/libcontainer/container_linux_test.go b/libcontainer/container_linux_test.go
index 3eb6e5af..27eee624 100644
--- a/libcontainer/container_linux_test.go
+++ b/libcontainer/container_linux_test.go
@@ -7,22 +7,15 @@ import (
 
 	"github.com/opencontainers/runc/libcontainer/cgroups"
 	"github.com/opencontainers/runc/libcontainer/configs"
-	"github.com/opencontainers/runc/libcontainer/intelrdt"
 	"github.com/opencontainers/runc/libcontainer/system"
 )
 
 type mockCgroupManager struct {
 	pids    []int
 	allPids []int
-	stats   *cgroups.Stats
 	paths   map[string]string
 }
 
-type mockIntelRdtManager struct {
-	stats *intelrdt.Stats
-	path  string
-}
-
 func (m *mockCgroupManager) GetPids() ([]int, error) {
 	return m.pids, nil
 }
@@ -32,7 +25,7 @@ func (m *mockCgroupManager) GetAllPids() ([]int, error) {
 }
 
 func (m *mockCgroupManager) GetStats() (*cgroups.Stats, error) {
-	return m.stats, nil
+	return nil, nil
 }
 
 func (m *mockCgroupManager) Apply(pid int) error {
@@ -76,30 +69,6 @@ func (m *mockCgroupManager) GetFreezerState() (configs.FreezerState, error) {
 	return configs.Thawed, nil
 }
 
-func (m *mockIntelRdtManager) Apply(pid int) error {
-	return nil
-}
-
-func (m *mockIntelRdtManager) GetStats() (*intelrdt.Stats, error) {
-	return m.stats, nil
-}
-
-func (m *mockIntelRdtManager) Destroy() error {
-	return nil
-}
-
-func (m *mockIntelRdtManager) GetPath() string {
-	return m.path
-}
-
-func (m *mockIntelRdtManager) Set(container *configs.Config) error {
-	return nil
-}
-
-func (m *mockIntelRdtManager) GetCgroups() (*configs.Cgroup, error) {
-	return nil, nil
-}
-
 type mockProcess struct {
 	_pid    int
 	started uint64
@@ -173,61 +142,11 @@ func TestGetContainerPids(t *testing.T) {
 	}
 }
 
-func TestGetContainerStats(t *testing.T) {
-	container := &linuxContainer{
-		id:     "myid",
-		config: &configs.Config{},
-		cgroupManager: &mockCgroupManager{
-			pids: []int{1, 2, 3},
-			stats: &cgroups.Stats{
-				MemoryStats: cgroups.MemoryStats{
-					Usage: cgroups.MemoryData{
-						Usage: 1024,
-					},
-				},
-			},
-		},
-		intelRdtManager: &mockIntelRdtManager{
-			stats: &intelrdt.Stats{
-				L3CacheSchema: "L3:0=f;1=f0",
-				MemBwSchema:   "MB:0=20;1=70",
-			},
-		},
-	}
-	stats, err := container.Stats()
-	if err != nil {
-		t.Fatal(err)
-	}
-	if stats.CgroupStats == nil {
-		t.Fatal("cgroup stats are nil")
-	}
-	if stats.CgroupStats.MemoryStats.Usage.Usage != 1024 {
-		t.Fatalf("expected memory usage 1024 but received %d", stats.CgroupStats.MemoryStats.Usage.Usage)
-	}
-	if intelrdt.IsCATEnabled() {
-		if stats.IntelRdtStats == nil {
-			t.Fatal("intel rdt stats are nil")
-		}
-		if stats.IntelRdtStats.L3CacheSchema != "L3:0=f;1=f0" {
-			t.Fatalf("expected L3CacheSchema L3:0=f;1=f0 but received %s", stats.IntelRdtStats.L3CacheSchema)
-		}
-	}
-	if intelrdt.IsMBAEnabled() {
-		if stats.IntelRdtStats == nil {
-			t.Fatal("intel rdt stats are nil")
-		}
-		if stats.IntelRdtStats.MemBwSchema != "MB:0=20;1=70" {
-			t.Fatalf("expected MemBwSchema MB:0=20;1=70 but received %s", stats.IntelRdtStats.MemBwSchema)
-		}
-	}
-}
-
 func TestGetContainerState(t *testing.T) {
 	var (
-		pid                  = os.Getpid()
-		expectedMemoryPath   = "/sys/fs/cgroup/memory/myid"
-		expectedNetworkPath  = fmt.Sprintf("/proc/%d/ns/net", pid)
-		expectedIntelRdtPath = "/sys/fs/resctrl/myid"
+		pid                 = os.Getpid()
+		expectedMemoryPath  = "/sys/fs/cgroup/memory/myid"
+		expectedNetworkPath = fmt.Sprintf("/proc/%d/ns/net", pid)
 	)
 	container := &linuxContainer{
 		id: "myid",
@@ -248,24 +167,10 @@ func TestGetContainerState(t *testing.T) {
 		},
 		cgroupManager: &mockCgroupManager{
 			pids: []int{1, 2, 3},
-			stats: &cgroups.Stats{
-				MemoryStats: cgroups.MemoryStats{
-					Usage: cgroups.MemoryData{
-						Usage: 1024,
-					},
-				},
-			},
 			paths: map[string]string{
 				"memory": expectedMemoryPath,
 			},
 		},
-		intelRdtManager: &mockIntelRdtManager{
-			stats: &intelrdt.Stats{
-				L3CacheSchema: "L3:0=f0;1=f",
-				MemBwSchema:   "MB:0=70;1=20",
-			},
-			path: expectedIntelRdtPath,
-		},
 	}
 	container.state = &createdState{c: container}
 	state, err := container.State()
@@ -285,15 +190,6 @@ func TestGetContainerState(t *testing.T) {
 	if memPath := paths["memory"]; memPath != expectedMemoryPath {
 		t.Fatalf("expected memory path %q but received %q", expectedMemoryPath, memPath)
 	}
-	if intelrdt.IsCATEnabled() || intelrdt.IsMBAEnabled() {
-		intelRdtPath := state.IntelRdtPath
-		if intelRdtPath == "" {
-			t.Fatal("intel rdt path should not be empty")
-		}
-		if intelRdtPath != expectedIntelRdtPath {
-			t.Fatalf("expected intel rdt path %q but received %q", expectedIntelRdtPath, intelRdtPath)
-		}
-	}
 	for _, ns := range container.config.Namespaces {
 		path := state.NamespacePaths[ns.Type]
 		if path == "" {
diff --git a/libcontainer/factory_linux_test.go b/libcontainer/factory_linux_test.go
index d29c32e9..47f30699 100644
--- a/libcontainer/factory_linux_test.go
+++ b/libcontainer/factory_linux_test.go
@@ -37,28 +37,6 @@ func TestFactoryNew(t *testing.T) {
 	}
 }
 
-func TestFactoryNewIntelRdt(t *testing.T) {
-	root := t.TempDir()
-	factory, err := New(root, IntelRdtFs)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if factory == nil {
-		t.Fatal("factory should not be nil")
-	}
-	lfactory, ok := factory.(*LinuxFactory)
-	if !ok {
-		t.Fatal("expected linux factory returned on linux based systems")
-	}
-	if lfactory.Root != root {
-		t.Fatalf("expected factory root to be %q but received %q", root, lfactory.Root)
-	}
-
-	if factory.Type() != "libcontainer" {
-		t.Fatalf("unexpected factory type: %q, expected %q", factory.Type(), "libcontainer")
-	}
-}
-
 func TestFactoryNewTmpfs(t *testing.T) {
 	root := t.TempDir()
 	factory, err := New(root, TmpfsRoot)
@@ -157,7 +135,7 @@ func TestFactoryLoadContainer(t *testing.T) {
 	if err := marshal(filepath.Join(root, id, stateFilename), expectedState); err != nil {
 		t.Fatal(err)
 	}
-	factory, err := New(root, IntelRdtFs)
+	factory, err := New(root)
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/libcontainer/intelrdt/intelrdt_test.go b/libcontainer/intelrdt/intelrdt_test.go
index 2184a146..c127cd8f 100644
--- a/libcontainer/intelrdt/intelrdt_test.go
+++ b/libcontainer/intelrdt/intelrdt_test.go
@@ -20,7 +20,7 @@ func TestIntelRdtSetL3CacheSchema(t *testing.T) {
 	})
 
 	helper.config.IntelRdt.L3CacheSchema = l3CacheSchemeAfter
-	intelrdt := NewManager(helper.config, "", helper.IntelRdtPath)
+	intelrdt := newManager(helper.config, "", helper.IntelRdtPath)
 	if err := intelrdt.Set(helper.config); err != nil {
 		t.Fatal(err)
 	}
@@ -50,7 +50,7 @@ func TestIntelRdtSetMemBwSchema(t *testing.T) {
 	})
 
 	helper.config.IntelRdt.MemBwSchema = memBwSchemeAfter
-	intelrdt := NewManager(helper.config, "", helper.IntelRdtPath)
+	intelrdt := newManager(helper.config, "", helper.IntelRdtPath)
 	if err := intelrdt.Set(helper.config); err != nil {
 		t.Fatal(err)
 	}
@@ -80,7 +80,7 @@ func TestIntelRdtSetMemBwScSchema(t *testing.T) {
 	})
 
 	helper.config.IntelRdt.MemBwSchema = memBwScSchemeAfter
-	intelrdt := NewManager(helper.config, "", helper.IntelRdtPath)
+	intelrdt := newManager(helper.config, "", helper.IntelRdtPath)
 	if err := intelrdt.Set(helper.config); err != nil {
 		t.Fatal(err)
 	}
@@ -103,7 +103,7 @@ func TestApply(t *testing.T) {
 	const closID = "test-clos"
 
 	helper.config.IntelRdt.ClosID = closID
-	intelrdt := NewManager(helper.config, "", helper.IntelRdtPath)
+	intelrdt := newManager(helper.config, "", helper.IntelRdtPath)
 	if err := intelrdt.Apply(1234); err == nil {
 		t.Fatal("unexpected success when applying pid")
 	}
@@ -112,7 +112,7 @@ func TestApply(t *testing.T) {
 	}
 
 	// Dir should be created if some schema has been specified
-	intelrdt.(*intelRdtManager).config.IntelRdt.L3CacheSchema = "L3:0=f"
+	intelrdt.config.IntelRdt.L3CacheSchema = "L3:0=f"
 	if err := intelrdt.Apply(1235); err != nil {
 		t.Fatalf("Apply() failed: %v", err)
 	}
diff --git a/libcontainer/specconv/spec_linux_test.go b/libcontainer/specconv/spec_linux_test.go
index 56d80869..1068c55a 100644
--- a/libcontainer/specconv/spec_linux_test.go
+++ b/libcontainer/specconv/spec_linux_test.go
@@ -540,8 +540,7 @@ func TestSpecconvExampleValidate(t *testing.T) {
 			spec.Process.NoNewPrivileges, config.NoNewPrivileges)
 	}
 
-	validator := validate.New()
-	if err := validator.Validate(config); err != nil {
+	if err := validate.Validate(config); err != nil {
 		t.Errorf("Expected specconv to produce valid container config: %v", err)
 	}
 }
@@ -562,8 +561,7 @@ func TestSpecconvNoLinuxSection(t *testing.T) {
 		t.Errorf("Couldn't create libcontainer config: %v", err)
 	}
 
-	validator := validate.New()
-	if err := validator.Validate(config); err != nil {
+	if err := validate.Validate(config); err != nil {
 		t.Errorf("Expected specconv to produce valid container config: %v", err)
 	}
 }
@@ -617,8 +615,7 @@ func TestNonZeroEUIDCompatibleSpecconvValidate(t *testing.T) {
 		t.Errorf("Couldn't create libcontainer config: %v", err)
 	}
 
-	validator := validate.New()
-	if err := validator.Validate(config); err != nil {
+	if err := validate.Validate(config); err != nil {
 		t.Errorf("Expected specconv to produce valid rootless container config: %v", err)
 	}
 }