Repository: opencontainers/runc
Pull request #2931 (2021-05-03 17:31:41)

script/release.sh: add -a to force rebuild
This is an alternative to #2930. 

https://golang.org/cmd/go/#hdr-Build_and_test_caching says:

> If you have made changes to the C libraries on your system, you will
> need to clean the cache explicitly or else use the -a build flag
> (see 'go help build') to force rebuilding of packages that depend
> on the updated C libraries.

This means that:

1. We need to either `go clean -cache` or `go build -a` when building
   the release binary. Adding `-a` seems less intrusive / more focused.

2. The check for existing `libseccomp.a` (added by commit d748280aa)
   is no longer needed.


Patch:
diff --git a/Makefile b/Makefile
index 1d43f353..56ce5294 100644
--- a/Makefile
+++ b/Makefile
@@ -14,10 +14,6 @@ COMMIT_NO := $(shell git rev-parse HEAD 2> /dev/null || true)
 COMMIT ?= $(if $(shell git status --porcelain --untracked-files=no),"$(COMMIT_NO)-dirty","$(COMMIT_NO)")
 VERSION := $(shell cat ./VERSION)
 
-# TODO: rm -mod=vendor once go 1.13 is unsupported
-ifneq ($(GO111MODULE),off)
-	MOD_VENDOR := "-mod=vendor"
-endif
 ifeq ($(shell $(GO) env GOOS),linux)
 	ifeq (,$(filter $(shell $(GO) env GOARCH),mips mipsle mips64 mips64le ppc64))
 		ifeq (,$(findstring -race,$(EXTRA_FLAGS)))
@@ -25,9 +21,9 @@ ifeq ($(shell $(GO) env GOOS),linux)
 		endif
 	endif
 endif
-GO_BUILD := $(GO) build -trimpath $(MOD_VENDOR) $(GO_BUILDMODE) $(EXTRA_FLAGS) -tags "$(BUILDTAGS)" \
+GO_BUILD := $(GO) build -trimpath $(GO_BUILDMODE) $(EXTRA_FLAGS) -tags "$(BUILDTAGS)" \
 	-ldflags "-X main.gitCommit=$(COMMIT) -X main.version=$(VERSION) $(EXTRA_LDFLAGS)"
-GO_BUILD_STATIC := CGO_ENABLED=1 $(GO) build -trimpath $(MOD_VENDOR) $(EXTRA_FLAGS) -tags "$(BUILDTAGS) netgo osusergo" \
+GO_BUILD_STATIC := CGO_ENABLED=1 $(GO) build -trimpath $(EXTRA_FLAGS) -tags "$(BUILDTAGS) netgo osusergo" \
 	-ldflags "-w -extldflags -static -X main.gitCommit=$(COMMIT) -X main.version=$(VERSION) $(EXTRA_LDFLAGS)"
 
 .DEFAULT: runc
@@ -74,7 +70,7 @@ unittest: runcimage
 		$(RUNC_IMAGE) make localunittest TESTFLAGS=$(TESTFLAGS)
 
 localunittest: all
-	$(GO) test $(MOD_VENDOR) -timeout 3m -tags "$(BUILDTAGS)" $(TESTFLAGS) -v ./...
+	$(GO) test -timeout 3m -tags "$(BUILDTAGS)" $(TESTFLAGS) -v ./...
 
 integration: runcimage
 	$(CONTAINER_ENGINE) run $(CONTAINER_ENGINE_RUN_FLAGS) \
diff --git a/README.md b/README.md
index 23106d30..f978c73e 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ A third party security audit was performed by Cure53, you can see the full repor
 ## Building
 
 `runc` currently supports the Linux platform with various architecture support.
-It must be built with Go version 1.13 or higher.
+It must be built with Go version 1.14 or higher.
 
 In order to enable seccomp support you will need to install `libseccomp` on your platform.
 > e.g. `libseccomp-devel` for CentOS, or `libseccomp-dev` for Ubuntu
diff --git a/go.mod b/go.mod
index 105cec57..07d6260a 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
 module github.com/opencontainers/runc
 
-go 1.13
+go 1.14
 
 require (
 	github.com/checkpoint-restore/go-criu/v5 v5.0.0
diff --git a/libcontainer/cgroups/cgroups.go b/libcontainer/cgroups/cgroups.go
index 68a346ca..c418fbae 100644
--- a/libcontainer/cgroups/cgroups.go
+++ b/libcontainer/cgroups/cgroups.go
@@ -7,44 +7,37 @@ import (
 )
 
 type Manager interface {
-	// Apply creates a cgroup, if not yet created, and adds a process
-	// with the specified pid into that cgroup.  A special value of -1
-	// can be used to merely create a cgroup.
+	// Applies cgroup configuration to the process with the specified pid
 	Apply(pid int) error
 
-	// GetPids returns the PIDs of all processes inside the cgroup.
+	// Returns the PIDs inside the cgroup set
 	GetPids() ([]int, error)
 
-	// GetAllPids returns the PIDs of all processes inside the cgroup
-	// any all its sub-cgroups.
+	// Returns the PIDs inside the cgroup set & all sub-cgroups
 	GetAllPids() ([]int, error)
 
-	// GetStats returns cgroups statistics.
+	// Returns statistics for the cgroup set
 	GetStats() (*Stats, error)
 
-	// Freeze sets the freezer cgroup to the specified state.
+	// Toggles the freezer cgroup according with specified state
 	Freeze(state configs.FreezerState) error
 
-	// Destroy removes cgroup.
+	// Destroys the cgroup set
 	Destroy() error
 
 	// Path returns a cgroup path to the specified controller/subsystem.
 	// For cgroupv2, the argument is unused and can be empty.
 	Path(string) string
 
-	// Set sets cgroup resources parameters/limits. If the argument is nil,
-	// the resources specified during Manager creation (or the previous call
-	// to Set) are used.
-	Set(r *configs.Resources) error
+	// Sets the cgroup as configured.
+	Set(container *configs.Config) error
 
-	// GetPaths returns cgroup path(s) to save in a state file in order to
-	// restore later.
+	// GetPaths returns cgroup path(s) to save in a state file in order to restore later.
 	//
-	// For cgroup v1, a key is cgroup subsystem name, and the value is the
-	// path to the cgroup for this subsystem.
+	// For cgroup v1, a key is cgroup subsystem name, and the value is the path
+	// to the cgroup for this subsystem.
 	//
-	// For cgroup v2 unified hierarchy, a key is "", and the value is the
-	// unified path.
+	// For cgroup v2 unified hierarchy, a key is "", and the value is the unified path.
 	GetPaths() map[string]string
 
 	// GetCgroups returns the cgroup data as configured.
@@ -53,7 +46,7 @@ type Manager interface {
 	// GetFreezerState retrieves the current FreezerState of the cgroup.
 	GetFreezerState() (configs.FreezerState, error)
 
-	// Exists returns whether the cgroup path exists or not.
+	// Whether the cgroup path exists or not
 	Exists() bool
 
 	// OOMKillCount reports OOM kill count for the cgroup.
diff --git a/libcontainer/cgroups/fs/blkio.go b/libcontainer/cgroups/fs/blkio.go
index 05fec260..dca2a622 100644
--- a/libcontainer/cgroups/fs/blkio.go
+++ b/libcontainer/cgroups/fs/blkio.go
@@ -25,19 +25,19 @@ func (s *BlkioGroup) Apply(path string, d *cgroupData) error {
 	return join(path, d.pid)
 }
 
-func (s *BlkioGroup) Set(path string, r *configs.Resources) error {
-	if r.BlkioWeight != 0 {
-		if err := fscommon.WriteFile(path, "blkio.weight", strconv.FormatUint(uint64(r.BlkioWeight), 10)); err != nil {
+func (s *BlkioGroup) Set(path string, cgroup *configs.Cgroup) error {
+	if cgroup.Resources.BlkioWeight != 0 {
+		if err := fscommon.WriteFile(path, "blkio.weight", strconv.FormatUint(uint64(cgroup.Resources.BlkioWeight), 10)); err != nil {
 			return err
 		}
 	}
 
-	if r.BlkioLeafWeight != 0 {
-		if err := fscommon.WriteFile(path, "blkio.leaf_weight", strconv.FormatUint(uint64(r.BlkioLeafWeight), 10)); err != nil {
+	if cgroup.Resources.BlkioLeafWeight != 0 {
+		if err := fscommon.WriteFile(path, "blkio.leaf_weight", strconv.FormatUint(uint64(cgroup.Resources.BlkioLeafWeight), 10)); err != nil {
 			return err
 		}
 	}
-	for _, wd := range r.BlkioWeightDevice {
+	for _, wd := range cgroup.Resources.BlkioWeightDevice {
 		if err := fscommon.WriteFile(path, "blkio.weight_device", wd.WeightString()); err != nil {
 			return err
 		}
@@ -45,22 +45,22 @@ func (s *BlkioGroup) Set(path string, r *configs.Resources) error {
 			return err
 		}
 	}
-	for _, td := range r.BlkioThrottleReadBpsDevice {
+	for _, td := range cgroup.Resources.BlkioThrottleReadBpsDevice {
 		if err := fscommon.WriteFile(path, "blkio.throttle.read_bps_device", td.String()); err != nil {
 			return err
 		}
 	}
-	for _, td := range r.BlkioThrottleWriteBpsDevice {
+	for _, td := range cgroup.Resources.BlkioThrottleWriteBpsDevice {
 		if err := fscommon.WriteFile(path, "blkio.throttle.write_bps_device", td.String()); err != nil {
 			return err
 		}
 	}
-	for _, td := range r.BlkioThrottleReadIOPSDevice {
+	for _, td := range cgroup.Resources.BlkioThrottleReadIOPSDevice {
 		if err := fscommon.WriteFile(path, "blkio.throttle.read_iops_device", td.String()); err != nil {
 			return err
 		}
 	}
-	for _, td := range r.BlkioThrottleWriteIOPSDevice {
+	for _, td := range cgroup.Resources.BlkioThrottleWriteIOPSDevice {
 		if err := fscommon.WriteFile(path, "blkio.throttle.write_iops_device", td.String()); err != nil {
 			return err
 		}
diff --git a/libcontainer/cgroups/fs/cpu.go b/libcontainer/cgroups/fs/cpu.go
index 975df1c4..194f3a54 100644
--- a/libcontainer/cgroups/fs/cpu.go
+++ b/libcontainer/cgroups/fs/cpu.go
@@ -32,7 +32,7 @@ func (s *CpuGroup) Apply(path string, d *cgroupData) error {
 	// We should set the real-Time group scheduling settings before moving
 	// in the process because if the process is already in SCHED_RR mode
 	// and no RT bandwidth is set, adding it will fail.
-	if err := s.SetRtSched(path, d.config.Resources); err != nil {
+	if err := s.SetRtSched(path, d.config); err != nil {
 		return err
 	}
 	// Since we are not using join(), we need to place the pid
@@ -40,23 +40,23 @@ func (s *CpuGroup) Apply(path string, d *cgroupData) error {
 	return cgroups.WriteCgroupProc(path, d.pid)
 }
 
-func (s *CpuGroup) SetRtSched(path string, r *configs.Resources) error {
-	if r.CpuRtPeriod != 0 {
-		if err := fscommon.WriteFile(path, "cpu.rt_period_us", strconv.FormatUint(r.CpuRtPeriod, 10)); err != nil {
+func (s *CpuGroup) SetRtSched(path string, cgroup *configs.Cgroup) error {
+	if cgroup.Resources.CpuRtPeriod != 0 {
+		if err := fscommon.WriteFile(path, "cpu.rt_period_us", strconv.FormatUint(cgroup.Resources.CpuRtPeriod, 10)); err != nil {
 			return err
 		}
 	}
-	if r.CpuRtRuntime != 0 {
-		if err := fscommon.WriteFile(path, "cpu.rt_runtime_us", strconv.FormatInt(r.CpuRtRuntime, 10)); err != nil {
+	if cgroup.Resources.CpuRtRuntime != 0 {
+		if err := fscommon.WriteFile(path, "cpu.rt_runtime_us", strconv.FormatInt(cgroup.Resources.CpuRtRuntime, 10)); err != nil {
 			return err
 		}
 	}
 	return nil
 }
 
-func (s *CpuGroup) Set(path string, r *configs.Resources) error {
-	if r.CpuShares != 0 {
-		shares := r.CpuShares
+func (s *CpuGroup) Set(path string, cgroup *configs.Cgroup) error {
+	if cgroup.Resources.CpuShares != 0 {
+		shares := cgroup.Resources.CpuShares
 		if err := fscommon.WriteFile(path, "cpu.shares", strconv.FormatUint(shares, 10)); err != nil {
 			return err
 		}
@@ -72,17 +72,17 @@ func (s *CpuGroup) Set(path string, r *configs.Resources) error {
 			return fmt.Errorf("the minimum allowed cpu-shares is %d", sharesRead)
 		}
 	}
-	if r.CpuPeriod != 0 {
-		if err := fscommon.WriteFile(path, "cpu.cfs_period_us", strconv.FormatUint(r.CpuPeriod, 10)); err != nil {
+	if cgroup.Resources.CpuPeriod != 0 {
+		if err := fscommon.WriteFile(path, "cpu.cfs_period_us", strconv.FormatUint(cgroup.Resources.CpuPeriod, 10)); err != nil {
 			return err
 		}
 	}
-	if r.CpuQuota != 0 {
-		if err := fscommon.WriteFile(path, "cpu.cfs_quota_us", strconv.FormatInt(r.CpuQuota, 10)); err != nil {
+	if cgroup.Resources.CpuQuota != 0 {
+		if err := fscommon.WriteFile(path, "cpu.cfs_quota_us", strconv.FormatInt(cgroup.Resources.CpuQuota, 10)); err != nil {
 			return err
 		}
 	}
-	return s.SetRtSched(path, r)
+	return s.SetRtSched(path, cgroup)
 }
 
 func (s *CpuGroup) GetStats(path string, stats *cgroups.Stats) error {
diff --git a/libcontainer/cgroups/fs/cpuacct.go b/libcontainer/cgroups/fs/cpuacct.go
index 0445cd45..129de6a0 100644
--- a/libcontainer/cgroups/fs/cpuacct.go
+++ b/libcontainer/cgroups/fs/cpuacct.go
@@ -43,7 +43,7 @@ func (s *CpuacctGroup) Apply(path string, d *cgroupData) error {
 	return join(path, d.pid)
 }
 
-func (s *CpuacctGroup) Set(_ string, _ *configs.Resources) error {
+func (s *CpuacctGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 }
 
diff --git a/libcontainer/cgroups/fs/cpuset.go b/libcontainer/cgroups/fs/cpuset.go
index 0591122b..5bde025b 100644
--- a/libcontainer/cgroups/fs/cpuset.go
+++ b/libcontainer/cgroups/fs/cpuset.go
@@ -24,17 +24,17 @@ func (s *CpusetGroup) Name() string {
 }
 
 func (s *CpusetGroup) Apply(path string, d *cgroupData) error {
-	return s.ApplyDir(path, d.config.Resources, d.pid)
+	return s.ApplyDir(path, d.config, d.pid)
 }
 
-func (s *CpusetGroup) Set(path string, r *configs.Resources) error {
-	if r.CpusetCpus != "" {
-		if err := fscommon.WriteFile(path, "cpuset.cpus", r.CpusetCpus); err != nil {
+func (s *CpusetGroup) Set(path string, cgroup *configs.Cgroup) error {
+	if cgroup.Resources.CpusetCpus != "" {
+		if err := fscommon.WriteFile(path, "cpuset.cpus", cgroup.Resources.CpusetCpus); err != nil {
 			return err
 		}
 	}
-	if r.CpusetMems != "" {
-		if err := fscommon.WriteFile(path, "cpuset.mems", r.CpusetMems); err != nil {
+	if cgroup.Resources.CpusetMems != "" {
+		if err := fscommon.WriteFile(path, "cpuset.mems", cgroup.Resources.CpusetMems); err != nil {
 			return err
 		}
 	}
@@ -144,7 +144,7 @@ func (s *CpusetGroup) GetStats(path string, stats *cgroups.Stats) error {
 	return nil
 }
 
-func (s *CpusetGroup) ApplyDir(dir string, r *configs.Resources, pid int) error {
+func (s *CpusetGroup) ApplyDir(dir string, cgroup *configs.Cgroup, pid int) error {
 	// This might happen if we have no cpuset cgroup mounted.
 	// Just do nothing and don't fail.
 	if dir == "" {
@@ -166,7 +166,7 @@ func (s *CpusetGroup) ApplyDir(dir string, r *configs.Resources, pid int) error
 	// specified configs, otherwise, inherit from parent. This makes
 	// cpuset configs work correctly with 'cpuset.cpu_exclusive', and
 	// keep backward compatibility.
-	if err := s.ensureCpusAndMems(dir, r); err != nil {
+	if err := s.ensureCpusAndMems(dir, cgroup); err != nil {
 		return err
 	}
 
@@ -241,8 +241,8 @@ func isEmptyCpuset(str string) bool {
 	return str == "" || str == "\n"
 }
 
-func (s *CpusetGroup) ensureCpusAndMems(path string, r *configs.Resources) error {
-	if err := s.Set(path, r); err != nil {
+func (s *CpusetGroup) ensureCpusAndMems(path string, cgroup *configs.Cgroup) error {
+	if err := s.Set(path, cgroup); err != nil {
 		return err
 	}
 	return cpusetCopyIfNeeded(path, filepath.Dir(path))
diff --git a/libcontainer/cgroups/fs/devices.go b/libcontainer/cgroups/fs/devices.go
index 048f1139..a098e3b7 100644
--- a/libcontainer/cgroups/fs/devices.go
+++ b/libcontainer/cgroups/fs/devices.go
@@ -54,8 +54,8 @@ func buildEmulator(rules []*devices.Rule) (*cgroupdevices.Emulator, error) {
 	return emu, nil
 }
 
-func (s *DevicesGroup) Set(path string, r *configs.Resources) error {
-	if userns.RunningInUserNS() || r.SkipDevices {
+func (s *DevicesGroup) Set(path string, cgroup *configs.Cgroup) error {
+	if userns.RunningInUserNS() || cgroup.SkipDevices {
 		return nil
 	}
 
@@ -65,7 +65,7 @@ func (s *DevicesGroup) Set(path string, r *configs.Resources) error {
 	if err != nil {
 		return err
 	}
-	target, err := buildEmulator(r.Devices)
+	target, err := buildEmulator(cgroup.Resources.Devices)
 	if err != nil {
 		return err
 	}
diff --git a/libcontainer/cgroups/fs/freezer.go b/libcontainer/cgroups/fs/freezer.go
index 37bbf38f..5aefdf51 100644
--- a/libcontainer/cgroups/fs/freezer.go
+++ b/libcontainer/cgroups/fs/freezer.go
@@ -27,8 +27,8 @@ func (s *FreezerGroup) Apply(path string, d *cgroupData) error {
 	return join(path, d.pid)
 }
 
-func (s *FreezerGroup) Set(path string, r *configs.Resources) (Err error) {
-	switch r.Freezer {
+func (s *FreezerGroup) Set(path string, cgroup *configs.Cgroup) (Err error) {
+	switch cgroup.Resources.Freezer {
 	case configs.Frozen:
 		defer func() {
 			if Err != nil {
@@ -90,7 +90,7 @@ func (s *FreezerGroup) Set(path string, r *configs.Resources) (Err error) {
 	case configs.Undefined:
 		return nil
 	default:
-		return fmt.Errorf("Invalid argument '%s' to freezer.state", string(r.Freezer))
+		return fmt.Errorf("Invalid argument '%s' to freezer.state", string(cgroup.Resources.Freezer))
 	}
 }
 
diff --git a/libcontainer/cgroups/fs/fs.go b/libcontainer/cgroups/fs/fs.go
index 7dc4b9e3..e8f38908 100644
--- a/libcontainer/cgroups/fs/fs.go
+++ b/libcontainer/cgroups/fs/fs.go
@@ -44,8 +44,8 @@ type subsystem interface {
 	GetStats(path string, stats *cgroups.Stats) error
 	// Creates and joins the cgroup represented by 'cgroupData'.
 	Apply(path string, c *cgroupData) error
-	// Set sets the cgroup resources.
-	Set(path string, r *configs.Resources) error
+	// Set the cgroup represented by cgroup.
+	Set(path string, cgroup *configs.Cgroup) error
 }
 
 type manager struct {
@@ -274,8 +274,8 @@ func (m *manager) GetStats() (*cgroups.Stats, error) {
 	return stats, nil
 }
 
-func (m *manager) Set(r *configs.Resources) error {
-	if r == nil {
+func (m *manager) Set(container *configs.Config) error {
+	if container.Cgroups == nil {
 		return nil
 	}
 
@@ -284,7 +284,7 @@ func (m *manager) Set(r *configs.Resources) error {
 	if m.cgroups != nil && m.cgroups.Paths != nil {
 		return nil
 	}
-	if r.Unified != nil {
+	if container.Cgroups.Resources.Unified != nil {
 		return cgroups.ErrV1NoUnified
 	}
 
@@ -292,7 +292,7 @@ func (m *manager) Set(r *configs.Resources) error {
 	defer m.mu.Unlock()
 	for _, sys := range subsystems {
 		path := m.paths[sys.Name()]
-		if err := sys.Set(path, r); err != nil {
+		if err := sys.Set(path, container.Cgroups); err != nil {
 			if m.rootless && sys.Name() == "devices" {
 				continue
 			}
@@ -322,7 +322,7 @@ func (m *manager) Freeze(state configs.FreezerState) error {
 	prevState := m.cgroups.Resources.Freezer
 	m.cgroups.Resources.Freezer = state
 	freezer := &FreezerGroup{}
-	if err := freezer.Set(path, m.cgroups.Resources); err != nil {
+	if err := freezer.Set(path, m.cgroups); err != nil {
 		m.cgroups.Resources.Freezer = prevState
 		return err
 	}
diff --git a/libcontainer/cgroups/fs/hugetlb.go b/libcontainer/cgroups/fs/hugetlb.go
index cf2b93bc..86179341 100644
--- a/libcontainer/cgroups/fs/hugetlb.go
+++ b/libcontainer/cgroups/fs/hugetlb.go
@@ -22,8 +22,8 @@ func (s *HugetlbGroup) Apply(path string, d *cgroupData) error {
 	return join(path, d.pid)
 }
 
-func (s *HugetlbGroup) Set(path string, r *configs.Resources) error {
-	for _, hugetlb := range r.HugetlbLimit {
+func (s *HugetlbGroup) Set(path string, cgroup *configs.Cgroup) error {
+	for _, hugetlb := range cgroup.Resources.HugetlbLimit {
 		if err := fscommon.WriteFile(path, "hugetlb."+hugetlb.Pagesize+".limit_in_bytes", strconv.FormatUint(hugetlb.Limit, 10)); err != nil {
 			return err
 		}
diff --git a/libcontainer/cgroups/fs/memory.go b/libcontainer/cgroups/fs/memory.go
index dc27cb9e..2007f18a 100644
--- a/libcontainer/cgroups/fs/memory.go
+++ b/libcontainer/cgroups/fs/memory.go
@@ -110,32 +110,32 @@ func setMemoryAndSwap(path string, r *configs.Resources) error {
 	return nil
 }
 
-func (s *MemoryGroup) Set(path string, r *configs.Resources) error {
-	if err := setMemoryAndSwap(path, r); err != nil {
+func (s *MemoryGroup) Set(path string, cgroup *configs.Cgroup) error {
+	if err := setMemoryAndSwap(path, cgroup.Resources); err != nil {
 		return err
 	}
 
 	// ignore KernelMemory and KernelMemoryTCP
 
-	if r.MemoryReservation != 0 {
-		if err := fscommon.WriteFile(path, "memory.soft_limit_in_bytes", strconv.FormatInt(r.MemoryReservation, 10)); err != nil {
+	if cgroup.Resources.MemoryReservation != 0 {
+		if err := fscommon.WriteFile(path, "memory.soft_limit_in_bytes", strconv.FormatInt(cgroup.Resources.MemoryReservation, 10)); err != nil {
 			return err
 		}
 	}
 
-	if r.OomKillDisable {
+	if cgroup.Resources.OomKillDisable {
 		if err := fscommon.WriteFile(path, "memory.oom_control", "1"); err != nil {
 			return err
 		}
 	}
-	if r.MemorySwappiness == nil || int64(*r.MemorySwappiness) == -1 {
+	if cgroup.Resources.MemorySwappiness == nil || int64(*cgroup.Resources.MemorySwappiness) == -1 {
 		return nil
-	} else if *r.MemorySwappiness <= 100 {
-		if err := fscommon.WriteFile(path, "memory.swappiness", strconv.FormatUint(*r.MemorySwappiness, 10)); err != nil {
+	} else if *cgroup.Resources.MemorySwappiness <= 100 {
+		if err := fscommon.WriteFile(path, "memory.swappiness", strconv.FormatUint(*cgroup.Resources.MemorySwappiness, 10)); err != nil {
 			return err
 		}
 	} else {
-		return fmt.Errorf("invalid value:%d. valid memory swappiness range is 0-100", *r.MemorySwappiness)
+		return fmt.Errorf("invalid value:%d. valid memory swappiness range is 0-100", *cgroup.Resources.MemorySwappiness)
 	}
 
 	return nil
diff --git a/libcontainer/cgroups/fs/name.go b/libcontainer/cgroups/fs/name.go
index 94a94b5e..7cada914 100644
--- a/libcontainer/cgroups/fs/name.go
+++ b/libcontainer/cgroups/fs/name.go
@@ -24,7 +24,7 @@ func (s *NameGroup) Apply(path string, d *cgroupData) error {
 	return nil
 }
 
-func (s *NameGroup) Set(_ string, _ *configs.Resources) error {
+func (s *NameGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 }
 
diff --git a/libcontainer/cgroups/fs/net_cls.go b/libcontainer/cgroups/fs/net_cls.go
index c824db34..901e9554 100644
--- a/libcontainer/cgroups/fs/net_cls.go
+++ b/libcontainer/cgroups/fs/net_cls.go
@@ -21,9 +21,9 @@ func (s *NetClsGroup) Apply(path string, d *cgroupData) error {
 	return join(path, d.pid)
 }
 
-func (s *NetClsGroup) Set(path string, r *configs.Resources) error {
-	if r.NetClsClassid != 0 {
-		if err := fscommon.WriteFile(path, "net_cls.classid", strconv.FormatUint(uint64(r.NetClsClassid), 10)); err != nil {
+func (s *NetClsGroup) Set(path string, cgroup *configs.Cgroup) error {
+	if cgroup.Resources.NetClsClassid != 0 {
+		if err := fscommon.WriteFile(path, "net_cls.classid", strconv.FormatUint(uint64(cgroup.Resources.NetClsClassid), 10)); err != nil {
 			return err
 		}
 	}
diff --git a/libcontainer/cgroups/fs/net_prio.go b/libcontainer/cgroups/fs/net_prio.go
index ce4bebc2..a9645de2 100644
--- a/libcontainer/cgroups/fs/net_prio.go
+++ b/libcontainer/cgroups/fs/net_prio.go
@@ -19,8 +19,8 @@ func (s *NetPrioGroup) Apply(path string, d *cgroupData) error {
 	return join(path, d.pid)
 }
 
-func (s *NetPrioGroup) Set(path string, r *configs.Resources) error {
-	for _, prioMap := range r.NetPrioIfpriomap {
+func (s *NetPrioGroup) Set(path string, cgroup *configs.Cgroup) error {
+	for _, prioMap := range cgroup.Resources.NetPrioIfpriomap {
 		if err := fscommon.WriteFile(path, "net_prio.ifpriomap", prioMap.CgroupString()); err != nil {
 			return err
 		}
diff --git a/libcontainer/cgroups/fs/perf_event.go b/libcontainer/cgroups/fs/perf_event.go
index 5da4845f..dd1e98d0 100644
--- a/libcontainer/cgroups/fs/perf_event.go
+++ b/libcontainer/cgroups/fs/perf_event.go
@@ -18,7 +18,7 @@ func (s *PerfEventGroup) Apply(path string, d *cgroupData) error {
 	return join(path, d.pid)
 }
 
-func (s *PerfEventGroup) Set(_ string, _ *configs.Resources) error {
+func (s *PerfEventGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 }
 
diff --git a/libcontainer/cgroups/fs/pids.go b/libcontainer/cgroups/fs/pids.go
index c12dafd1..6614df88 100644
--- a/libcontainer/cgroups/fs/pids.go
+++ b/libcontainer/cgroups/fs/pids.go
@@ -23,13 +23,13 @@ func (s *PidsGroup) Apply(path string, d *cgroupData) error {
 	return join(path, d.pid)
 }
 
-func (s *PidsGroup) Set(path string, r *configs.Resources) error {
-	if r.PidsLimit != 0 {
+func (s *PidsGroup) Set(path string, cgroup *configs.Cgroup) error {
+	if cgroup.Resources.PidsLimit != 0 {
 		// "max" is the fallback value.
 		limit := "max"
 
-		if r.PidsLimit > 0 {
-			limit = strconv.FormatInt(r.PidsLimit, 10)
+		if cgroup.Resources.PidsLimit > 0 {
+			limit = strconv.FormatInt(cgroup.Resources.PidsLimit, 10)
 		}
 
 		if err := fscommon.WriteFile(path, "pids.max", limit); err != nil {
diff --git a/libcontainer/cgroups/fs2/cpu.go b/libcontainer/cgroups/fs2/cpu.go
index 404800e9..8ace0ce7 100644
--- a/libcontainer/cgroups/fs2/cpu.go
+++ b/libcontainer/cgroups/fs2/cpu.go
@@ -12,14 +12,15 @@ import (
 	"github.com/opencontainers/runc/libcontainer/configs"
 )
 
-func isCpuSet(r *configs.Resources) bool {
-	return r.CpuWeight != 0 || r.CpuQuota != 0 || r.CpuPeriod != 0
+func isCpuSet(cgroup *configs.Cgroup) bool {
+	return cgroup.Resources.CpuWeight != 0 || cgroup.Resources.CpuQuota != 0 || cgroup.Resources.CpuPeriod != 0
 }
 
-func setCpu(dirPath string, r *configs.Resources) error {
-	if !isCpuSet(r) {
+func setCpu(dirPath string, cgroup *configs.Cgroup) error {
+	if !isCpuSet(cgroup) {
 		return nil
 	}
+	r := cgroup.Resources
 
 	// NOTE: .CpuShares is not used here. Conversion is the caller's responsibility.
 	if r.CpuWeight != 0 {
diff --git a/libcontainer/cgroups/fs2/cpuset.go b/libcontainer/cgroups/fs2/cpuset.go
index 713c430d..fb4456b4 100644
--- a/libcontainer/cgroups/fs2/cpuset.go
+++ b/libcontainer/cgroups/fs2/cpuset.go
@@ -7,22 +7,22 @@ import (
 	"github.com/opencontainers/runc/libcontainer/configs"
 )
 
-func isCpusetSet(r *configs.Resources) bool {
-	return r.CpusetCpus != "" || r.CpusetMems != ""
+func isCpusetSet(cgroup *configs.Cgroup) bool {
+	return cgroup.Resources.CpusetCpus != "" || cgroup.Resources.CpusetMems != ""
 }
 
-func setCpuset(dirPath string, r *configs.Resources) error {
-	if !isCpusetSet(r) {
+func setCpuset(dirPath string, cgroup *configs.Cgroup) error {
+	if !isCpusetSet(cgroup) {
 		return nil
 	}
 
-	if r.CpusetCpus != "" {
-		if err := fscommon.WriteFile(dirPath, "cpuset.cpus", r.CpusetCpus); err != nil {
+	if cgroup.Resources.CpusetCpus != "" {
+		if err := fscommon.WriteFile(dirPath, "cpuset.cpus", cgroup.Resources.CpusetCpus); err != nil {
 			return err
 		}
 	}
-	if r.CpusetMems != "" {
-		if err := fscommon.WriteFile(dirPath, "cpuset.mems", r.CpusetMems); err != nil {
+	if cgroup.Resources.CpusetMems != "" {
+		if err := fscommon.WriteFile(dirPath, "cpuset.mems", cgroup.Resources.CpusetMems); err != nil {
 			return err
 		}
 	}
diff --git a/libcontainer/cgroups/fs2/create.go b/libcontainer/cgroups/fs2/create.go
index f7a9999b..30cf51ee 100644
--- a/libcontainer/cgroups/fs2/create.go
+++ b/libcontainer/cgroups/fs2/create.go
@@ -10,7 +10,7 @@ import (
 	"github.com/opencontainers/runc/libcontainer/configs"
 )
 
-func supportedControllers() (string, error) {
+func supportedControllers(cgroup *configs.Cgroup) (string, error) {
 	return fscommon.ReadFile(UnifiedMountpoint, "/cgroup.controllers")
 }
 
@@ -18,13 +18,13 @@ func supportedControllers() (string, error) {
 // based on (1) controllers available and (2) resources that are being set.
 // We don't check "pseudo" controllers such as
 // "freezer" and "devices".
-func needAnyControllers(r *configs.Resources) (bool, error) {
-	if r == nil {
+func needAnyControllers(cgroup *configs.Cgroup) (bool, error) {
+	if cgroup == nil {
 		return false, nil
 	}
 
 	// list of all available controllers
-	content, err := supportedControllers()
+	content, err := supportedControllers(cgroup)
 	if err != nil {
 		return false, err
 	}
@@ -39,22 +39,22 @@ func needAnyControllers(r *configs.Resources) (bool, error) {
 		return ok
 	}
 
-	if isPidsSet(r) && have("pids") {
+	if isPidsSet(cgroup) && have("pids") {
 		return true, nil
 	}
-	if isMemorySet(r) && have("memory") {
+	if isMemorySet(cgroup) && have("memory") {
 		return true, nil
 	}
-	if isIoSet(r) && have("io") {
+	if isIoSet(cgroup) && have("io") {
 		return true, nil
 	}
-	if isCpuSet(r) && have("cpu") {
+	if isCpuSet(cgroup) && have("cpu") {
 		return true, nil
 	}
-	if isCpusetSet(r) && have("cpuset") {
+	if isCpusetSet(cgroup) && have("cpuset") {
 		return true, nil
 	}
-	if isHugeTlbSet(r) && have("hugetlb") {
+	if isHugeTlbSet(cgroup) && have("hugetlb") {
 		return true, nil
 	}
 
@@ -64,8 +64,8 @@ func needAnyControllers(r *configs.Resources) (bool, error) {
 // containsDomainController returns whether the current config contains domain controller or not.
 // Refer to: http://man7.org/linux/man-pages/man7/cgroups.7.html
 // As at Linux 4.19, the following controllers are threaded: cpu, perf_event, and pids.
-func containsDomainController(r *configs.Resources) bool {
-	return isMemorySet(r) || isIoSet(r) || isCpuSet(r) || isHugeTlbSet(r)
+func containsDomainController(cg *configs.Cgroup) bool {
+	return isMemorySet(cg) || isIoSet(cg) || isCpuSet(cg) || isHugeTlbSet(cg)
 }
 
 // CreateCgroupPath creates cgroupv2 path, enabling all the supported controllers.
@@ -74,7 +74,7 @@ func CreateCgroupPath(path string, c *configs.Cgroup) (Err error) {
 		return fmt.Errorf("invalid cgroup path %s", path)
 	}
 
-	content, err := supportedControllers()
+	content, err := supportedControllers(c)
 	if err != nil {
 		return err
 	}
@@ -115,7 +115,7 @@ func CreateCgroupPath(path string, c *configs.Cgroup) (Err error) {
 			// the controllers requested are thread-aware we can simply put the cgroup into
 			// threaded mode.
 			case "domain invalid":
-				if containsDomainController(c.Resources) {
+				if containsDomainController(c) {
 					return fmt.Errorf("cannot enter cgroupv2 %q with domain controllers -- it is in an invalid state", current)
 				} else {
 					// Not entirely correct (in theory we'd always want to be a domain --
@@ -129,7 +129,7 @@ func CreateCgroupPath(path string, c *configs.Cgroup) (Err error) {
 			case "domain threaded":
 				fallthrough
 			case "threaded":
-				if containsDomainController(c.Resources) {
+				if containsDomainController(c) {
 					return fmt.Errorf("cannot enter cgroupv2 %q with domain controllers -- it is in %s mode", current, cgType)
 				}
 			}
diff --git a/libcontainer/cgroups/fs2/devices.go b/libcontainer/cgroups/fs2/devices.go
index fa9194b5..61c00a96 100644
--- a/libcontainer/cgroups/fs2/devices.go
+++ b/libcontainer/cgroups/fs2/devices.go
@@ -30,7 +30,7 @@ func isRWM(perms devices.Permissions) bool {
 
 // This is similar to the logic applied in crun for handling errors from bpf(2)
 // <https://github.com/containers/crun/blob/0.17/src/libcrun/cgroup.c#L2438-L2470>.
-func canSkipEBPFError(r *configs.Resources) bool {
+func canSkipEBPFError(cgroup *configs.Cgroup) bool {
 	// If we're running in a user namespace we can ignore eBPF rules because we
 	// usually cannot use bpf(2), as well as rootless containers usually don't
 	// have the necessary privileges to mknod(2) device inodes or access
@@ -46,7 +46,7 @@ func canSkipEBPFError(r *configs.Resources) bool {
 	// NOTE: This will sometimes trigger in cases where access modes are split
 	//       between different rules but to handle this correctly would require
 	//       using ".../libcontainer/cgroup/devices".Emulator.
-	for _, dev := range r.Devices {
+	for _, dev := range cgroup.Resources.Devices {
 		if !dev.Allow || !isRWM(dev.Permissions) {
 			return false
 		}
@@ -54,14 +54,15 @@ func canSkipEBPFError(r *configs.Resources) bool {
 	return true
 }
 
-func setDevices(dirPath string, r *configs.Resources) error {
-	if r.SkipDevices {
+func setDevices(dirPath string, cgroup *configs.Cgroup) error {
+	if cgroup.SkipDevices {
 		return nil
 	}
 	// XXX: This is currently a white-list (but all callers pass a blacklist of
 	//      devices). This is bad for a whole variety of reasons, but will need
 	//      to be fixed with co-ordinated effort with downstreams.
-	insts, license, err := devicefilter.DeviceFilter(r.Devices)
+	devices := cgroup.Devices
+	insts, license, err := devicefilter.DeviceFilter(devices)
 	if err != nil {
 		return err
 	}
@@ -82,7 +83,7 @@ func setDevices(dirPath string, r *configs.Resources) error {
 	//      programs. You could temporarily insert a deny-everything program
 	//      but that would result in spurrious failures during updates.
 	if _, err := ebpf.LoadAttachCgroupDeviceFilter(insts, license, dirFD); err != nil {
-		if !canSkipEBPFError(r) {
+		if !canSkipEBPFError(cgroup) {
 			return err
 		}
 	}
diff --git a/libcontainer/cgroups/fs2/fs2.go b/libcontainer/cgroups/fs2/fs2.go
index 5da6c51e..2db442a3 100644
--- a/libcontainer/cgroups/fs2/fs2.go
+++ b/libcontainer/cgroups/fs2/fs2.go
@@ -75,7 +75,7 @@ func (m *manager) Apply(pid int) error {
 		// - "runc create (rootless + limits + no cgrouppath + no permission) fails with informative error"
 		if m.rootless {
 			if m.config.Path == "" {
-				if blNeed, nErr := needAnyControllers(m.config.Resources); nErr == nil && !blNeed {
+				if blNeed, nErr := needAnyControllers(m.config); nErr == nil && !blNeed {
 					return nil
 				}
 				return errors.Wrap(err, "rootless needs no limits + no cgrouppath when no permission is granted for cgroups")
@@ -147,24 +147,27 @@ func (m *manager) Path(_ string) string {
 	return m.dirPath
 }
 
-func (m *manager) Set(r *configs.Resources) error {
+func (m *manager) Set(container *configs.Config) error {
+	if container == nil || container.Cgroups == nil {
+		return nil
+	}
 	if err := m.getControllers(); err != nil {
 		return err
 	}
 	// pids (since kernel 4.5)
-	if err := setPids(m.dirPath, r); err != nil {
+	if err := setPids(m.dirPath, container.Cgroups); err != nil {
 		return err
 	}
 	// memory (since kernel 4.5)
-	if err := setMemory(m.dirPath, r); err != nil {
+	if err := setMemory(m.dirPath, container.Cgroups); err != nil {
 		return err
 	}
 	// io (since kernel 4.5)
-	if err := setIo(m.dirPath, r); err != nil {
+	if err := setIo(m.dirPath, container.Cgroups); err != nil {
 		return err
 	}
 	// cpu (since kernel 4.15)
-	if err := setCpu(m.dirPath, r); err != nil {
+	if err := setCpu(m.dirPath, container.Cgroups); err != nil {
 		return err
 	}
 	// devices (since kernel 4.15, pseudo-controller)
@@ -172,25 +175,25 @@ func (m *manager) Set(r *configs.Resources) error {
 	// When m.rootless is true, errors from the device subsystem are ignored because it is really not expected to work.
 	// However, errors from other subsystems are not ignored.
 	// see @test "runc create (rootless + limits + no cgrouppath + no permission) fails with informative error"
-	if err := setDevices(m.dirPath, r); err != nil && !m.rootless {
+	if err := setDevices(m.dirPath, container.Cgroups); err != nil && !m.rootless {
 		return err
 	}
 	// cpuset (since kernel 5.0)
-	if err := setCpuset(m.dirPath, r); err != nil {
+	if err := setCpuset(m.dirPath, container.Cgroups); err != nil {
 		return err
 	}
 	// hugetlb (since kernel 5.6)
-	if err := setHugeTlb(m.dirPath, r); err != nil {
+	if err := setHugeTlb(m.dirPath, container.Cgroups); err != nil {
 		return err
 	}
 	// freezer (since kernel 5.2, pseudo-controller)
-	if err := setFreezer(m.dirPath, r.Freezer); err != nil {
+	if err := setFreezer(m.dirPath, container.Cgroups.Freezer); err != nil {
 		return err
 	}
-	if err := m.setUnified(r.Unified); err != nil {
+	if err := m.setUnified(container.Cgroups.Unified); err != nil {
 		return err
 	}
-	m.config.Resources = r
+	m.config = container.Cgroups
 	return nil
 }
 
diff --git a/libcontainer/cgroups/fs2/hugetlb.go b/libcontainer/cgroups/fs2/hugetlb.go
index 76df7701..feddc7aa 100644
--- a/libcontainer/cgroups/fs2/hugetlb.go
+++ b/libcontainer/cgroups/fs2/hugetlb.go
@@ -12,15 +12,15 @@ import (
 	"github.com/opencontainers/runc/libcontainer/configs"
 )
 
-func isHugeTlbSet(r *configs.Resources) bool {
-	return len(r.HugetlbLimit) > 0
+func isHugeTlbSet(cgroup *configs.Cgroup) bool {
+	return len(cgroup.Resources.HugetlbLimit) > 0
 }
 
-func setHugeTlb(dirPath string, r *configs.Resources) error {
-	if !isHugeTlbSet(r) {
+func setHugeTlb(dirPath string, cgroup *configs.Cgroup) error {
+	if !isHugeTlbSet(cgroup) {
 		return nil
 	}
-	for _, hugetlb := range r.HugetlbLimit {
+	for _, hugetlb := range cgroup.Resources.HugetlbLimit {
 		if err := fscommon.WriteFile(dirPath, "hugetlb."+hugetlb.Pagesize+".max", strconv.FormatUint(hugetlb.Limit, 10)); err != nil {
 			return err
 		}
diff --git a/libcontainer/cgroups/fs2/io.go b/libcontainer/cgroups/fs2/io.go
index c07a0086..34262d3c 100644
--- a/libcontainer/cgroups/fs2/io.go
+++ b/libcontainer/cgroups/fs2/io.go
@@ -13,50 +13,50 @@ import (
 	"github.com/opencontainers/runc/libcontainer/configs"
 )
 
-func isIoSet(r *configs.Resources) bool {
-	return r.BlkioWeight != 0 ||
-		len(r.BlkioThrottleReadBpsDevice) > 0 ||
-		len(r.BlkioThrottleWriteBpsDevice) > 0 ||
-		len(r.BlkioThrottleReadIOPSDevice) > 0 ||
-		len(r.BlkioThrottleWriteIOPSDevice) > 0
+func isIoSet(cgroup *configs.Cgroup) bool {
+	return cgroup.Resources.BlkioWeight != 0 ||
+		len(cgroup.Resources.BlkioThrottleReadBpsDevice) > 0 ||
+		len(cgroup.Resources.BlkioThrottleWriteBpsDevice) > 0 ||
+		len(cgroup.Resources.BlkioThrottleReadIOPSDevice) > 0 ||
+		len(cgroup.Resources.BlkioThrottleWriteIOPSDevice) > 0
 }
 
-func setIo(dirPath string, r *configs.Resources) error {
-	if !isIoSet(r) {
+func setIo(dirPath string, cgroup *configs.Cgroup) error {
+	if !isIoSet(cgroup) {
 		return nil
 	}
 
-	if r.BlkioWeight != 0 {
+	if cgroup.Resources.BlkioWeight != 0 {
 		filename := "io.bfq.weight"
 		if err := fscommon.WriteFile(dirPath, filename,
-			strconv.FormatUint(uint64(r.BlkioWeight), 10)); err != nil {
+			strconv.FormatUint(uint64(cgroup.Resources.BlkioWeight), 10)); err != nil {
 			// if io.bfq.weight does not exist, then bfq module is not loaded.
 			// Fallback to use io.weight with a conversion scheme
 			if !os.IsNotExist(err) {
 				return err
 			}
-			v := cgroups.ConvertBlkIOToIOWeightValue(r.BlkioWeight)
+			v := cgroups.ConvertBlkIOToIOWeightValue(cgroup.Resources.BlkioWeight)
 			if err := fscommon.WriteFile(dirPath, "io.weight", strconv.FormatUint(v, 10)); err != nil {
 				return err
 			}
 		}
 	}
-	for _, td := range r.BlkioThrottleReadBpsDevice {
+	for _, td := range cgroup.Resources.BlkioThrottleReadBpsDevice {
 		if err := fscommon.WriteFile(dirPath, "io.max", td.StringName("rbps")); err != nil {
 			return err
 		}
 	}
-	for _, td := range r.BlkioThrottleWriteBpsDevice {
+	for _, td := range cgroup.Resources.BlkioThrottleWriteBpsDevice {
 		if err := fscommon.WriteFile(dirPath, "io.max", td.StringName("wbps")); err != nil {
 			return err
 		}
 	}
-	for _, td := range r.BlkioThrottleReadIOPSDevice {
+	for _, td := range cgroup.Resources.BlkioThrottleReadIOPSDevice {
 		if err := fscommon.WriteFile(dirPath, "io.max", td.StringName("riops")); err != nil {
 			return err
 		}
 	}
-	for _, td := range r.BlkioThrottleWriteIOPSDevice {
+	for _, td := range cgroup.Resources.BlkioThrottleWriteIOPSDevice {
 		if err := fscommon.WriteFile(dirPath, "io.max", td.StringName("wiops")); err != nil {
 			return err
 		}
diff --git a/libcontainer/cgroups/fs2/memory.go b/libcontainer/cgroups/fs2/memory.go
index 7308f5a2..3d1284a7 100644
--- a/libcontainer/cgroups/fs2/memory.go
+++ b/libcontainer/cgroups/fs2/memory.go
@@ -33,20 +33,21 @@ func numToStr(value int64) (ret string) {
 	return ret
 }
 
-func isMemorySet(r *configs.Resources) bool {
-	return r.MemoryReservation != 0 || r.Memory != 0 || r.MemorySwap != 0
+func isMemorySet(cgroup *configs.Cgroup) bool {
+	return cgroup.Resources.MemoryReservation != 0 ||
+		cgroup.Resources.Memory != 0 || cgroup.Resources.MemorySwap != 0
 }
 
-func setMemory(dirPath string, r *configs.Resources) error {
-	if !isMemorySet(r) {
+func setMemory(dirPath string, cgroup *configs.Cgroup) error {
+	if !isMemorySet(cgroup) {
 		return nil
 	}
-	swap, err := cgroups.ConvertMemorySwapToCgroupV2Value(r.MemorySwap, r.Memory)
+	swap, err := cgroups.ConvertMemorySwapToCgroupV2Value(cgroup.Resources.MemorySwap, cgroup.Resources.Memory)
 	if err != nil {
 		return err
 	}
 	swapStr := numToStr(swap)
-	if swapStr == "" && swap == 0 && r.MemorySwap > 0 {
+	if swapStr == "" && swap == 0 && cgroup.Resources.MemorySwap > 0 {
 		// memory and memorySwap set to the same value -- disable swap
 		swapStr = "0"
 	}
@@ -57,7 +58,7 @@ func setMemory(dirPath string, r *configs.Resources) error {
 		}
 	}
 
-	if val := numToStr(r.Memory); val != "" {
+	if val := numToStr(cgroup.Resources.Memory); val != "" {
 		if err := fscommon.WriteFile(dirPath, "memory.max", val); err != nil {
 			return err
 		}
@@ -65,7 +66,7 @@ func setMemory(dirPath string, r *configs.Resources) error {
 
 	// cgroup.Resources.KernelMemory is ignored
 
-	if val := numToStr(r.MemoryReservation); val != "" {
+	if val := numToStr(cgroup.Resources.MemoryReservation); val != "" {
 		if err := fscommon.WriteFile(dirPath, "memory.low", val); err != nil {
 			return err
 		}
diff --git a/libcontainer/cgroups/fs2/pids.go b/libcontainer/cgroups/fs2/pids.go
index 346fdb67..36621234 100644
--- a/libcontainer/cgroups/fs2/pids.go
+++ b/libcontainer/cgroups/fs2/pids.go
@@ -14,15 +14,15 @@ import (
 	"golang.org/x/sys/unix"
 )
 
-func isPidsSet(r *configs.Resources) bool {
-	return r.PidsLimit != 0
+func isPidsSet(cgroup *configs.Cgroup) bool {
+	return cgroup.Resources.PidsLimit != 0
 }
 
-func setPids(dirPath string, r *configs.Resources) error {
-	if !isPidsSet(r) {
+func setPids(dirPath string, cgroup *configs.Cgroup) error {
+	if !isPidsSet(cgroup) {
 		return nil
 	}
-	if val := numToStr(r.PidsLimit); val != "" {
+	if val := numToStr(cgroup.Resources.PidsLimit); val != "" {
 		if err := fscommon.WriteFile(dirPath, "pids.max", val); err != nil {
 			return err
 		}
diff --git a/libcontainer/cgroups/fscommon/open.go b/libcontainer/cgroups/fscommon/open.go
index 49af83b3..0a7e3d95 100644
--- a/libcontainer/cgroups/fscommon/open.go
+++ b/libcontainer/cgroups/fscommon/open.go
@@ -5,6 +5,7 @@ import (
 	"strings"
 	"sync"
 
+	securejoin "github.com/cyphar/filepath-securejoin"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 	"golang.org/x/sys/unix"
@@ -16,7 +17,7 @@ const (
 )
 
 var (
-	// TestMode is set to true by unit tests that need "fake" cgroupfs.
+	// Set to true by fs unit tests
 	TestMode bool
 
 	cgroupFd     int = -1
@@ -70,12 +71,12 @@ func OpenFile(dir, file string, flags int) (*os.File, error) {
 		flags |= os.O_TRUNC | os.O_CREATE
 		mode = 0o600
 	}
-	if prepareOpenat2() != nil {
-		return openFallback(dir, file, flags, mode)
-	}
 	reldir := strings.TrimPrefix(dir, cgroupfsPrefix)
 	if len(reldir) == len(dir) { // non-standard path, old system?
-		return openFallback(dir, file, flags, mode)
+		return openWithSecureJoin(dir, file, flags, mode)
+	}
+	if prepareOpenat2() != nil {
+		return openWithSecureJoin(dir, file, flags, mode)
 	}
 
 	relname := reldir + "/" + file
@@ -92,29 +93,11 @@ func OpenFile(dir, file string, flags int) (*os.File, error) {
 	return os.NewFile(uintptr(fd), cgroupfsPrefix+relname), nil
 }
 
-var errNotCgroupfs = errors.New("not a cgroup file")
-
-// openFallback is used when openat2(2) is not available. It checks the opened
-// file is on cgroupfs, returning an error otherwise.
-func openFallback(dir, file string, flags int, mode os.FileMode) (*os.File, error) {
-	path := dir + "/" + file
-	fd, err := os.OpenFile(path, flags, mode)
+func openWithSecureJoin(dir, file string, flags int, mode os.FileMode) (*os.File, error) {
+	path, err := securejoin.SecureJoin(dir, file)
 	if err != nil {
 		return nil, err
 	}
-	if TestMode {
-		return fd, nil
-	}
-	// Check this is a cgroupfs file.
-	var st unix.Statfs_t
-	if err := unix.Fstatfs(int(fd.Fd()), &st); err != nil {
-		_ = fd.Close()
-		return nil, &os.PathError{Op: "statfs", Path: path, Err: err}
-	}
-	if st.Type != unix.CGROUP_SUPER_MAGIC && st.Type != unix.CGROUP2_SUPER_MAGIC {
-		_ = fd.Close()
-		return nil, &os.PathError{Op: "open", Path: path, Err: errNotCgroupfs}
-	}
 
-	return fd, nil
+	return os.OpenFile(path, flags, mode)
 }
diff --git a/libcontainer/cgroups/systemd/common.go b/libcontainer/cgroups/systemd/common.go
index 8d2aa5da..268b713c 100644
--- a/libcontainer/cgroups/systemd/common.go
+++ b/libcontainer/cgroups/systemd/common.go
@@ -2,7 +2,6 @@ package systemd
 
 import (
 	"bufio"
-	"context"
 	"fmt"
 	"math"
 	"os"
@@ -322,7 +321,7 @@ func isUnitExists(err error) bool {
 func startUnit(cm *dbusConnManager, unitName string, properties []systemdDbus.Property) error {
 	statusChan := make(chan string, 1)
 	err := cm.retryOnDisconnect(func(c *systemdDbus.Conn) error {
-		_, err := c.StartTransientUnitContext(context.TODO(), unitName, "replace", properties, statusChan)
+		_, err := c.StartTransientUnit(unitName, "replace", properties, statusChan)
 		return err
 	})
 	if err == nil {
@@ -332,7 +331,7 @@ func startUnit(cm *dbusConnManager, unitName string, properties []systemdDbus.Pr
 		select {
 		case s := <-statusChan:
 			close(statusChan)
-			// Please refer to https://pkg.go.dev/github.com/coreos/go-systemd/v22/dbus#Conn.StartUnit
+			// Please refer to https://godoc.org/github.com/coreos/go-systemd/dbus#Conn.StartUnit
 			if s != "done" {
 				resetFailedUnit(cm, unitName)
 				return errors.Errorf("error creating systemd unit `%s`: got `%s`", unitName, s)
@@ -351,14 +350,14 @@ func startUnit(cm *dbusConnManager, unitName string, properties []systemdDbus.Pr
 func stopUnit(cm *dbusConnManager, unitName string) error {
 	statusChan := make(chan string, 1)
 	err := cm.retryOnDisconnect(func(c *systemdDbus.Conn) error {
-		_, err := c.StopUnitContext(context.TODO(), unitName, "replace", statusChan)
+		_, err := c.StopUnit(unitName, "replace", statusChan)
 		return err
 	})
 	if err == nil {
 		select {
 		case s := <-statusChan:
 			close(statusChan)
-			// Please refer to https://godoc.org/github.com/coreos/go-systemd/v22/dbus#Conn.StartUnit
+			// Please refer to https://godoc.org/github.com/coreos/go-systemd/dbus#Conn.StartUnit
 			if s != "done" {
 				logrus.Warnf("error removing unit `%s`: got `%s`. Continuing...", unitName, s)
 			}
@@ -371,7 +370,7 @@ func stopUnit(cm *dbusConnManager, unitName string) error {
 
 func resetFailedUnit(cm *dbusConnManager, name string) {
 	err := cm.retryOnDisconnect(func(c *systemdDbus.Conn) error {
-		return c.ResetFailedUnitContext(context.TODO(), name)
+		return c.ResetFailedUnit(name)
 	})
 	if err != nil {
 		logrus.Warnf("unable to reset failed unit: %v", err)
@@ -380,7 +379,7 @@ func resetFailedUnit(cm *dbusConnManager, name string) {
 
 func setUnitProperties(cm *dbusConnManager, name string, properties ...systemdDbus.Property) error {
 	return cm.retryOnDisconnect(func(c *systemdDbus.Conn) error {
-		return c.SetUnitPropertiesContext(context.TODO(), name, true, properties...)
+		return c.SetUnitProperties(name, true, properties...)
 	})
 }
 
diff --git a/libcontainer/cgroups/systemd/v1.go b/libcontainer/cgroups/systemd/v1.go
index 41de6e8b..842fee20 100644
--- a/libcontainer/cgroups/systemd/v1.go
+++ b/libcontainer/cgroups/systemd/v1.go
@@ -36,8 +36,8 @@ type subsystem interface {
 	Name() string
 	// Returns the stats, as 'stats', corresponding to the cgroup under 'path'.
 	GetStats(path string, stats *cgroups.Stats) error
-	// Set sets cgroup resource limits.
-	Set(path string, r *configs.Resources) error
+	// Set the cgroup represented by cgroup.
+	Set(path string, cgroup *configs.Cgroup) error
 }
 
 var errSubsystemDoesNotExist = errors.New("cgroup: subsystem does not exist")
@@ -58,8 +58,9 @@ var legacySubsystems = []subsystem{
 	&fs.NameGroup{GroupName: "name=systemd"},
 }
 
-func genV1ResourcesProperties(r *configs.Resources, cm *dbusConnManager) ([]systemdDbus.Property, error) {
+func genV1ResourcesProperties(c *configs.Cgroup, cm *dbusConnManager) ([]systemdDbus.Property, error) {
 	var properties []systemdDbus.Property
+	r := c.Resources
 
 	deviceProperties, err := generateDeviceProperties(r.Devices)
 	if err != nil {
@@ -231,7 +232,7 @@ func (m *legacyManager) joinCgroups(pid int) error {
 		case "cpuset":
 			if path, ok := m.paths[name]; ok {
 				s := &fs.CpusetGroup{}
-				if err := s.ApplyDir(path, m.cgroups.Resources, pid); err != nil {
+				if err := s.ApplyDir(path, m.cgroups, pid); err != nil {
 					return err
 				}
 			}
@@ -284,7 +285,7 @@ func (m *legacyManager) Freeze(state configs.FreezerState) error {
 	prevState := m.cgroups.Resources.Freezer
 	m.cgroups.Resources.Freezer = state
 	freezer := &fs.FreezerGroup{}
-	if err := freezer.Set(path, m.cgroups.Resources); err != nil {
+	if err := freezer.Set(path, m.cgroups); err != nil {
 		m.cgroups.Resources.Freezer = prevState
 		return err
 	}
@@ -324,16 +325,16 @@ func (m *legacyManager) GetStats() (*cgroups.Stats, error) {
 	return stats, nil
 }
 
-func (m *legacyManager) Set(r *configs.Resources) error {
+func (m *legacyManager) Set(container *configs.Config) error {
 	// If Paths are set, then we are just joining cgroups paths
 	// and there is no need to set any values.
 	if m.cgroups.Paths != nil {
 		return nil
 	}
-	if r.Unified != nil {
+	if container.Cgroups.Resources.Unified != nil {
 		return cgroups.ErrV1NoUnified
 	}
-	properties, err := genV1ResourcesProperties(r, m.dbus)
+	properties, err := genV1ResourcesProperties(container.Cgroups, m.dbus)
 	if err != nil {
 		return err
 	}
@@ -361,7 +362,7 @@ func (m *legacyManager) Set(r *configs.Resources) error {
 		}
 	}
 
-	if err := setUnitProperties(m.dbus, getUnitName(m.cgroups), properties...); err != nil {
+	if err := setUnitProperties(m.dbus, getUnitName(container.Cgroups), properties...); err != nil {
 		_ = m.Freeze(targetFreezerState)
 		return err
 	}
@@ -376,7 +377,7 @@ func (m *legacyManager) Set(r *configs.Resources) error {
 		if !ok {
 			continue
 		}
-		if err := sys.Set(path, r); err != nil {
+		if err := sys.Set(path, container.Cgroups); err != nil {
 			return err
 		}
 	}
diff --git a/libcontainer/cgroups/systemd/v2.go b/libcontainer/cgroups/systemd/v2.go
index 9dcde423..7a59181b 100644
--- a/libcontainer/cgroups/systemd/v2.go
+++ b/libcontainer/cgroups/systemd/v2.go
@@ -164,8 +164,9 @@ func unifiedResToSystemdProps(cm *dbusConnManager, res map[string]string) (props
 	return props, nil
 }
 
-func genV2ResourcesProperties(r *configs.Resources, cm *dbusConnManager) ([]systemdDbus.Property, error) {
+func genV2ResourcesProperties(c *configs.Cgroup, cm *dbusConnManager) ([]systemdDbus.Property, error) {
 	var properties []systemdDbus.Property
+	r := c.Resources
 
 	// NOTE: This is of questionable correctness because we insert our own
 	//       devices eBPF program later. Two programs with identical rules
@@ -419,8 +420,8 @@ func (m *unifiedManager) GetStats() (*cgroups.Stats, error) {
 	return fsMgr.GetStats()
 }
 
-func (m *unifiedManager) Set(r *configs.Resources) error {
-	properties, err := genV2ResourcesProperties(r, m.dbus)
+func (m *unifiedManager) Set(container *configs.Config) error {
+	properties, err := genV2ResourcesProperties(m.cgroups, m.dbus)
 	if err != nil {
 		return err
 	}
@@ -461,7 +462,7 @@ func (m *unifiedManager) Set(r *configs.Resources) error {
 	if err != nil {
 		return err
 	}
-	return fsMgr.Set(r)
+	return fsMgr.Set(container)
 }
 
 func (m *unifiedManager) GetPaths() map[string]string {
diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go
index 945a0fa0..5e89285d 100644
--- a/libcontainer/container_linux.go
+++ b/libcontainer/container_linux.go
@@ -225,9 +225,9 @@ func (c *linuxContainer) Set(config configs.Config) error {
 	if status == Stopped {
 		return newGenericError(errors.New("container not running"), ContainerNotRunning)
 	}
-	if err := c.cgroupManager.Set(config.Cgroups.Resources); err != nil {
+	if err := c.cgroupManager.Set(&config); err != nil {
 		// Set configs back
-		if err2 := c.cgroupManager.Set(c.config.Cgroups.Resources); err2 != nil {
+		if err2 := c.cgroupManager.Set(c.config); err2 != nil {
 			logrus.Warnf("Setting back cgroup configs failed due to error: %v, your state.json and actual configs might be inconsistent.", err2)
 		}
 		return err
@@ -235,7 +235,7 @@ func (c *linuxContainer) Set(config configs.Config) error {
 	if c.intelRdtManager != nil {
 		if err := c.intelRdtManager.Set(&config); err != nil {
 			// Set configs back
-			if err2 := c.cgroupManager.Set(c.config.Cgroups.Resources); err2 != nil {
+			if err2 := c.cgroupManager.Set(c.config); err2 != nil {
 				logrus.Warnf("Setting back cgroup configs failed due to error: %v, your state.json and actual configs might be inconsistent.", err2)
 			}
 			if err2 := c.intelRdtManager.Set(c.config); err2 != nil {
@@ -1462,7 +1462,7 @@ func (c *linuxContainer) criuApplyCgroups(pid int, req *criurpc.CriuReq) error {
 		return err
 	}
 
-	if err := c.cgroupManager.Set(c.config.Cgroups.Resources); err != nil {
+	if err := c.cgroupManager.Set(c.config); err != nil {
 		return newSystemError(err)
 	}
 
diff --git a/libcontainer/nsenter/cloned_binary.c b/libcontainer/nsenter/cloned_binary.c
index 4268ebda..b9a4a14c 100644
--- a/libcontainer/nsenter/cloned_binary.c
+++ b/libcontainer/nsenter/cloned_binary.c
@@ -75,12 +75,12 @@
 #      define SYS_memfd_create 385
 #    elif defined(__aarch64__)
 #      define SYS_memfd_create 279
-#    elif defined(__ppc__) || defined(__PPC64__) || defined(__powerpc64__)
+#    elif defined(__ppc__) || defined(__ppc64__)
 #      define SYS_memfd_create 360
 #    elif defined(__s390__) || defined(__s390x__)
 #      define SYS_memfd_create 350
 #    else
-#      warning "unknown architecture -- cannot hard-code SYS_memfd_create"
+#      error "unknown architecture -- cannot hard-code SYS_memfd_create"
 #    endif
 #  endif
 #endif
diff --git a/libcontainer/process_linux.go b/libcontainer/process_linux.go
index 053971b9..10465949 100644
--- a/libcontainer/process_linux.go
+++ b/libcontainer/process_linux.go
@@ -448,7 +448,7 @@ func (p *initProcess) start() (retErr error) {
 			// call prestart and CreateRuntime hooks
 			if !p.config.Config.Namespaces.Contains(configs.NEWNS) {
 				// Setup cgroup before the hook, so that the prestart and CreateRuntime hook could apply cgroup permissions.
-				if err := p.manager.Set(p.config.Config.Cgroups.Resources); err != nil {
+				if err := p.manager.Set(p.config.Config); err != nil {
 					return newSystemErrorWithCause(err, "setting cgroup config for ready process")
 				}
 				if p.intelRdtManager != nil {
@@ -504,7 +504,7 @@ func (p *initProcess) start() (retErr error) {
 			sentRun = true
 		case procHooks:
 			// Setup cgroup before prestart hook, so that the prestart hook could apply cgroup permissions.
-			if err := p.manager.Set(p.config.Config.Cgroups.Resources); err != nil {
+			if err := p.manager.Set(p.config.Config); err != nil {
 				return newSystemErrorWithCause(err, "setting cgroup config for procHooks process")
 			}
 			if p.intelRdtManager != nil {
diff --git a/script/release.sh b/script/release.sh
index 2156fca3..b04fe009 100755
--- a/script/release.sh
+++ b/script/release.sh
@@ -30,25 +30,6 @@ function build_project() {
 	# Due to libseccomp being LGPL we must include its sources,
 	# so download, install and build against it.
 
-	# Sanity check: check that the build won't use distro-provided
-	# libseccomp.a. If this is the case, explain and abort.
-	#
-	# Note go is not used here as it caches the build heavily,
-	# including, apparently, the results of pkg-config.
-	# shellcheck disable=SC2046
-	if read -ra flags < <(pkg-config --libs --cflags libseccomp 2>/dev/null) &&
-		cat <<EOF | gcc -static -x c -o /dev/null - "${flags[@]}"; then
-#include <seccomp.h>
-int main(void) { seccomp_version(); return 0; }
-EOF
-		set +x
-		echo >&2
-		echo "Distro-provided libseccomp static library is installed." >&2
-		echo "Unable to build a static binary against own libsecomp." >&2
-		echo "Please uninstall libseccomp-static to fix." >&2
-		exit 1
-	fi
-
 	local libseccomp_ver='2.5.1'
 	local tarball="libseccomp-${libseccomp_ver}.tar.gz"
 	local prefix
@@ -62,7 +43,10 @@ EOF
 	)
 	mv "$tarball"{,.asc} "$builddir"
 
-	make -C "$root" PKG_CONFIG_PATH="${prefix}/lib/pkgconfig" COMMIT_NO= static
+	# Add -a to go build flags to make sure it links against
+	# the provided libseccomp, not the system one (otherwise
+	# it can reuse cached pkg-config results).
+	make -C "$root" PKG_CONFIG_PATH="${prefix}/lib/pkgconfig" COMMIT_NO= EXTRA_FLAGS="-a" static
 	rm -rf "$prefix"
 	mv "$root/$project" "$1"
 }
diff --git a/vendor/modules.txt b/vendor/modules.txt
index dac28f3a..792a957b 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -1,7 +1,9 @@
 # github.com/checkpoint-restore/go-criu/v5 v5.0.0
+## explicit
 github.com/checkpoint-restore/go-criu/v5
 github.com/checkpoint-restore/go-criu/v5/rpc
 # github.com/cilium/ebpf v0.5.0
+## explicit
 github.com/cilium/ebpf
 github.com/cilium/ebpf/asm
 github.com/cilium/ebpf/internal
@@ -9,59 +11,78 @@ github.com/cilium/ebpf/internal/btf
 github.com/cilium/ebpf/internal/unix
 github.com/cilium/ebpf/link
 # github.com/containerd/console v1.0.2
+## explicit
 github.com/containerd/console
 # github.com/coreos/go-systemd/v22 v22.3.1
+## explicit
 github.com/coreos/go-systemd/v22/activation
 github.com/coreos/go-systemd/v22/dbus
 # github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d
 github.com/cpuguy83/go-md2man/v2/md2man
 # github.com/cyphar/filepath-securejoin v0.2.2
+## explicit
 github.com/cyphar/filepath-securejoin
 # github.com/docker/go-units v0.4.0
+## explicit
 github.com/docker/go-units
 # github.com/godbus/dbus/v5 v5.0.4
+## explicit
 github.com/godbus/dbus/v5
 # github.com/golang/protobuf v1.4.3
 github.com/golang/protobuf/proto
 # github.com/moby/sys/mountinfo v0.4.1
+## explicit
 github.com/moby/sys/mountinfo
 # github.com/mrunalp/fileutils v0.5.0
+## explicit
 github.com/mrunalp/fileutils
 # github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
+## explicit
 github.com/opencontainers/runtime-spec/specs-go
 # github.com/opencontainers/selinux v1.8.0
+## explicit
 github.com/opencontainers/selinux/go-selinux
 github.com/opencontainers/selinux/go-selinux/label
 github.com/opencontainers/selinux/pkg/pwalk
 # github.com/pkg/errors v0.9.1
+## explicit
 github.com/pkg/errors
 # github.com/russross/blackfriday/v2 v2.0.1
 github.com/russross/blackfriday/v2
 # github.com/seccomp/libseccomp-golang v0.9.1
+## explicit
 github.com/seccomp/libseccomp-golang
 # github.com/shurcooL/sanitized_anchor_name v1.0.0
 github.com/shurcooL/sanitized_anchor_name
 # github.com/sirupsen/logrus v1.7.0
+## explicit
 github.com/sirupsen/logrus
 github.com/sirupsen/logrus/hooks/test
 # github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635
+## explicit
 github.com/syndtr/gocapability/capability
 # github.com/urfave/cli v1.22.1
+## explicit
 github.com/urfave/cli
 # github.com/vishvananda/netlink v1.1.0
+## explicit
 github.com/vishvananda/netlink
 github.com/vishvananda/netlink/nl
 # github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df
 github.com/vishvananda/netns
 # github.com/willf/bitset v1.1.11
+## explicit
 github.com/willf/bitset
 # golang.org/x/net v0.0.0-20201224014010-6772e930b67b
+## explicit
 golang.org/x/net/bpf
 # golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
+## explicit
 golang.org/x/sys/internal/unsafeheader
 golang.org/x/sys/unix
 golang.org/x/sys/windows
 # google.golang.org/protobuf v1.25.0
+## explicit
 google.golang.org/protobuf/encoding/prototext
 google.golang.org/protobuf/encoding/protowire
 google.golang.org/protobuf/internal/descfmt


Test patch:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index f125887c..0aa834e6 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -19,8 +19,7 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        # Dockre/Moby still builds runc with Go 1.13, so we should still support Go 1.13.
-        go-version: [1.13.x, 1.15.x, 1.16.x]
+        go-version: [1.14.x, 1.15.x, 1.16.x]
         rootless: ["rootless", ""]
         race: ["-race", ""]
 
diff --git a/libcontainer/cgroups/fs/blkio_test.go b/libcontainer/cgroups/fs/blkio_test.go
index bd96d242..23564805 100644
--- a/libcontainer/cgroups/fs/blkio_test.go
+++ b/libcontainer/cgroups/fs/blkio_test.go
@@ -185,7 +185,7 @@ func TestBlkioSetWeight(t *testing.T) {
 
 	helper.CgroupData.config.Resources.BlkioWeight = weightAfter
 	blkio := &BlkioGroup{}
-	if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil {
+	if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config); err != nil {
 		t.Fatal(err)
 	}
 
@@ -216,7 +216,7 @@ func TestBlkioSetWeightDevice(t *testing.T) {
 
 	helper.CgroupData.config.Resources.BlkioWeightDevice = []*configs.WeightDevice{wd}
 	blkio := &BlkioGroup{}
-	if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil {
+	if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config); err != nil {
 		t.Fatal(err)
 	}
 
@@ -253,7 +253,7 @@ func TestBlkioSetMultipleWeightDevice(t *testing.T) {
 
 	helper.CgroupData.config.Resources.BlkioWeightDevice = []*configs.WeightDevice{wd1, wd2}
 	blkio := &BlkioGroup{}
-	if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil {
+	if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config); err != nil {
 		t.Fatal(err)
 	}
 
@@ -746,7 +746,7 @@ func TestBlkioSetThrottleReadBpsDevice(t *testing.T) {
 
 	helper.CgroupData.config.Resources.BlkioThrottleReadBpsDevice = []*configs.ThrottleDevice{td}
 	blkio := &BlkioGroup{}
-	if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil {
+	if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config); err != nil {
 		t.Fatal(err)
 	}
 
@@ -776,7 +776,7 @@ func TestBlkioSetThrottleWriteBpsDevice(t *testing.T) {
 
 	helper.CgroupData.config.Resources.BlkioThrottleWriteBpsDevice = []*configs.ThrottleDevice{td}
 	blkio := &BlkioGroup{}
-	if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil {
+	if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config); err != nil {
 		t.Fatal(err)
 	}
 
@@ -806,7 +806,7 @@ func TestBlkioSetThrottleReadIOpsDevice(t *testing.T) {
 
 	helper.CgroupData.config.Resources.BlkioThrottleReadIOPSDevice = []*configs.ThrottleDevice{td}
 	blkio := &BlkioGroup{}
-	if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil {
+	if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config); err != nil {
 		t.Fatal(err)
 	}
 
@@ -836,7 +836,7 @@ func TestBlkioSetThrottleWriteIOpsDevice(t *testing.T) {
 
 	helper.CgroupData.config.Resources.BlkioThrottleWriteIOPSDevice = []*configs.ThrottleDevice{td}
 	blkio := &BlkioGroup{}
-	if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil {
+	if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config); err != nil {
 		t.Fatal(err)
 	}
 
diff --git a/libcontainer/cgroups/fs/cpu_test.go b/libcontainer/cgroups/fs/cpu_test.go
index b615594e..9adc9b31 100644
--- a/libcontainer/cgroups/fs/cpu_test.go
+++ b/libcontainer/cgroups/fs/cpu_test.go
@@ -26,7 +26,7 @@ func TestCpuSetShares(t *testing.T) {
 
 	helper.CgroupData.config.Resources.CpuShares = sharesAfter
 	cpu := &CpuGroup{}
-	if err := cpu.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil {
+	if err := cpu.Set(helper.CgroupPath, helper.CgroupData.config); err != nil {
 		t.Fatal(err)
 	}
 
@@ -67,7 +67,7 @@ func TestCpuSetBandWidth(t *testing.T) {
 	helper.CgroupData.config.Resources.CpuRtRuntime = rtRuntimeAfter
 	helper.CgroupData.config.Resources.CpuRtPeriod = rtPeriodAfter
 	cpu := &CpuGroup{}
-	if err := cpu.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil {
+	if err := cpu.Set(helper.CgroupPath, helper.CgroupData.config); err != nil {
 		t.Fatal(err)
 	}
 
diff --git a/libcontainer/cgroups/fs/cpuset_test.go b/libcontainer/cgroups/fs/cpuset_test.go
index 5ac9a037..8a49e440 100644
--- a/libcontainer/cgroups/fs/cpuset_test.go
+++ b/libcontainer/cgroups/fs/cpuset_test.go
@@ -53,7 +53,7 @@ func TestCPUSetSetCpus(t *testing.T) {
 
 	helper.CgroupData.config.Resources.CpusetCpus = cpusAfter
 	cpuset := &CpusetGroup{}
-	if err := cpuset.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil {
+	if err := cpuset.Set(helper.CgroupPath, helper.CgroupData.config); err != nil {
 		t.Fatal(err)
 	}
 
@@ -82,7 +82,7 @@ func TestCPUSetSetMems(t *testing.T) {
 
 	helper.CgroupData.config.Resources.CpusetMems = memsAfter
 	cpuset := &CpusetGroup{}
-	if err := cpuset.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil {
+	if err := cpuset.Set(helper.CgroupPath, helper.CgroupData.config); err != nil {
 		t.Fatal(err)
 	}
 
diff --git a/libcontainer/cgroups/fs/devices_test.go b/libcontainer/cgroups/fs/devices_test.go
index a0ef145d..752fadd9 100644
--- a/libcontainer/cgroups/fs/devices_test.go
+++ b/libcontainer/cgroups/fs/devices_test.go
@@ -30,7 +30,7 @@ func TestDevicesSetAllow(t *testing.T) {
 	}
 
 	d := &DevicesGroup{testingSkipFinalCheck: true}
-	if err := d.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil {
+	if err := d.Set(helper.CgroupPath, helper.CgroupData.config); err != nil {
 		t.Fatal(err)
 	}
 
diff --git a/libcontainer/cgroups/fs/freezer_test.go b/libcontainer/cgroups/fs/freezer_test.go
index e41b1ad4..ad80261c 100644
--- a/libcontainer/cgroups/fs/freezer_test.go
+++ b/libcontainer/cgroups/fs/freezer_test.go
@@ -19,7 +19,7 @@ func TestFreezerSetState(t *testing.T) {
 
 	helper.CgroupData.config.Resources.Freezer = configs.Thawed
 	freezer := &FreezerGroup{}
-	if err := freezer.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil {
+	if err := freezer.Set(helper.CgroupPath, helper.CgroupData.config); err != nil {
 		t.Fatal(err)
 	}
 
@@ -42,7 +42,7 @@ func TestFreezerSetInvalidState(t *testing.T) {
 
 	helper.CgroupData.config.Resources.Freezer = invalidArg
 	freezer := &FreezerGroup{}
-	if err := freezer.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err == nil {
+	if err := freezer.Set(helper.CgroupPath, helper.CgroupData.config); err == nil {
 		t.Fatal("Failed to return invalid argument error")
 	}
 }
diff --git a/libcontainer/cgroups/fs/fs_test.go b/libcontainer/cgroups/fs/fs_test.go
index b19b26e4..c899ff8f 100644
--- a/libcontainer/cgroups/fs/fs_test.go
+++ b/libcontainer/cgroups/fs/fs_test.go
@@ -8,7 +8,6 @@ import (
 	"testing"
 
 	"github.com/opencontainers/runc/libcontainer/cgroups"
-	"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
 	"github.com/opencontainers/runc/libcontainer/configs"
 )
 
@@ -105,42 +104,3 @@ func TestTryDefaultCgroupRoot(t *testing.T) {
 		t.Errorf("tryDefaultCgroupRoot: want %q, got %q", exp, res)
 	}
 }
-
-func BenchmarkGetStats(b *testing.B) {
-	if cgroups.IsCgroup2UnifiedMode() {
-		b.Skip("cgroup v2 is not supported")
-	}
-
-	// Unset TestMode as we work with real cgroupfs here,
-	// and we want OpenFile to perform the fstype check.
-	fscommon.TestMode = false
-	defer func() {
-		fscommon.TestMode = true
-	}()
-
-	cg := &configs.Cgroup{
-		Path:      "/some/kind/of/a/path/here",
-		Resources: &configs.Resources{},
-	}
-	m := NewManager(cg, nil, false)
-	err := m.Apply(-1)
-	if err != nil {
-		b.Fatal(err)
-	}
-	defer func() {
-		_ = m.Destroy()
-	}()
-
-	var st *cgroups.Stats
-
-	b.ResetTimer()
-	for i := 0; i < b.N; i++ {
-		st, err = m.GetStats()
-		if err != nil {
-			b.Fatal(err)
-		}
-	}
-	if st.CpuStats.CpuUsage.TotalUsage != 0 {
-		b.Fatalf("stats: %+v", st)
-	}
-}
diff --git a/libcontainer/cgroups/fs/hugetlb_test.go b/libcontainer/cgroups/fs/hugetlb_test.go
index 01b6889d..2d17ca67 100644
--- a/libcontainer/cgroups/fs/hugetlb_test.go
+++ b/libcontainer/cgroups/fs/hugetlb_test.go
@@ -48,7 +48,7 @@ func TestHugetlbSetHugetlb(t *testing.T) {
 			},
 		}
 		hugetlb := &HugetlbGroup{}
-		if err := hugetlb.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil {
+		if err := hugetlb.Set(helper.CgroupPath, helper.CgroupData.config); err != nil {
 			t.Fatal(err)
 		}
 	}
diff --git a/libcontainer/cgroups/fs/memory_test.go b/libcontainer/cgroups/fs/memory_test.go
index 589e2be3..701c99da 100644
--- a/libcontainer/cgroups/fs/memory_test.go
+++ b/libcontainer/cgroups/fs/memory_test.go
@@ -58,7 +58,7 @@ func TestMemorySetMemory(t *testing.T) {
 	helper.CgroupData.config.Resources.Memory = memoryAfter
 	helper.CgroupData.config.Resources.MemoryReservation = reservationAfter
 	memory := &MemoryGroup{}
-	if err := memory.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil {
+	if err := memory.Set(helper.CgroupPath, helper.CgroupData.config); err != nil {
 		t.Fatal(err)
 	}
 
@@ -94,7 +94,7 @@ func TestMemorySetMemoryswap(t *testing.T) {
 
 	helper.CgroupData.config.Resources.MemorySwap = memoryswapAfter
 	memory := &MemoryGroup{}
-	if err := memory.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil {
+	if err := memory.Set(helper.CgroupPath, helper.CgroupData.config); err != nil {
 		t.Fatal(err)
 	}
 
@@ -131,7 +131,7 @@ func TestMemorySetMemoryLargerThanSwap(t *testing.T) {
 	helper.CgroupData.config.Resources.Memory = memoryAfter
 	helper.CgroupData.config.Resources.MemorySwap = memoryswapAfter
 	memory := &MemoryGroup{}
-	if err := memory.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil {
+	if err := memory.Set(helper.CgroupPath, helper.CgroupData.config); err != nil {
 		t.Fatal(err)
 	}
 
@@ -170,7 +170,7 @@ func TestMemorySetSwapSmallerThanMemory(t *testing.T) {
 	helper.CgroupData.config.Resources.Memory = memoryAfter
 	helper.CgroupData.config.Resources.MemorySwap = memoryswapAfter
 	memory := &MemoryGroup{}
-	if err := memory.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil {
+	if err := memory.Set(helper.CgroupPath, helper.CgroupData.config); err != nil {
 		t.Fatal(err)
 	}
 
@@ -203,7 +203,7 @@ func TestMemorySetMemorySwappinessDefault(t *testing.T) {
 
 	helper.CgroupData.config.Resources.MemorySwappiness = &swappinessAfter
 	memory := &MemoryGroup{}
-	if err := memory.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil {
+	if err := memory.Set(helper.CgroupPath, helper.CgroupData.config); err != nil {
 		t.Fatal(err)
 	}
 
@@ -414,7 +414,7 @@ func TestMemorySetOomControl(t *testing.T) {
 	})
 
 	memory := &MemoryGroup{}
-	if err := memory.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil {
+	if err := memory.Set(helper.CgroupPath, helper.CgroupData.config); err != nil {
 		t.Fatal(err)
 	}
 
diff --git a/libcontainer/cgroups/fs/net_cls_test.go b/libcontainer/cgroups/fs/net_cls_test.go
index 1bb99eb2..602133a2 100644
--- a/libcontainer/cgroups/fs/net_cls_test.go
+++ b/libcontainer/cgroups/fs/net_cls_test.go
@@ -24,7 +24,7 @@ func TestNetClsSetClassid(t *testing.T) {
 
 	helper.CgroupData.config.Resources.NetClsClassid = classidAfter
 	netcls := &NetClsGroup{}
-	if err := netcls.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil {
+	if err := netcls.Set(helper.CgroupPath, helper.CgroupData.config); err != nil {
 		t.Fatal(err)
 	}
 
diff --git a/libcontainer/cgroups/fs/net_prio_test.go b/libcontainer/cgroups/fs/net_prio_test.go
index ef7cdb04..2ce8e192 100644
--- a/libcontainer/cgroups/fs/net_prio_test.go
+++ b/libcontainer/cgroups/fs/net_prio_test.go
@@ -25,7 +25,7 @@ func TestNetPrioSetIfPrio(t *testing.T) {
 
 	helper.CgroupData.config.Resources.NetPrioIfpriomap = prioMap
 	netPrio := &NetPrioGroup{}
-	if err := netPrio.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil {
+	if err := netPrio.Set(helper.CgroupPath, helper.CgroupData.config); err != nil {
 		t.Fatal(err)
 	}
 
diff --git a/libcontainer/cgroups/fs/pids_test.go b/libcontainer/cgroups/fs/pids_test.go
index 7f315747..66f3aa33 100644
--- a/libcontainer/cgroups/fs/pids_test.go
+++ b/libcontainer/cgroups/fs/pids_test.go
@@ -25,7 +25,7 @@ func TestPidsSetMax(t *testing.T) {
 
 	helper.CgroupData.config.Resources.PidsLimit = maxLimited
 	pids := &PidsGroup{}
-	if err := pids.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil {
+	if err := pids.Set(helper.CgroupPath, helper.CgroupData.config); err != nil {
 		t.Fatal(err)
 	}
 
@@ -49,7 +49,7 @@ func TestPidsSetUnlimited(t *testing.T) {
 
 	helper.CgroupData.config.Resources.PidsLimit = maxUnlimited
 	pids := &PidsGroup{}
-	if err := pids.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil {
+	if err := pids.Set(helper.CgroupPath, helper.CgroupData.config); err != nil {
 		t.Fatal(err)
 	}
 
diff --git a/libcontainer/cgroups/fscommon/utils_test.go b/libcontainer/cgroups/fscommon/utils_test.go
index f56cdd7e..d0c5668b 100644
--- a/libcontainer/cgroups/fscommon/utils_test.go
+++ b/libcontainer/cgroups/fscommon/utils_test.go
@@ -17,10 +17,6 @@ const (
 	floatString = "2048"
 )
 
-func init() {
-	TestMode = true
-}
-
 func TestGetCgroupParamsInt(t *testing.T) {
 	// Setup tempdir.
 	tempDir, err := ioutil.TempDir("", "cgroup_utils_test")
diff --git a/libcontainer/container_linux_test.go b/libcontainer/container_linux_test.go
index 880998d9..78071a92 100644
--- a/libcontainer/container_linux_test.go
+++ b/libcontainer/container_linux_test.go
@@ -42,7 +42,7 @@ func (m *mockCgroupManager) Apply(pid int) error {
 	return nil
 }
 
-func (m *mockCgroupManager) Set(_ *configs.Resources) error {
+func (m *mockCgroupManager) Set(container *configs.Config) error {
 	return nil
 }
 
diff --git a/libcontainer/logs/logs_linux_test.go b/libcontainer/logs/logs_linux_test.go
index 89912c46..7e2b59d9 100644
--- a/libcontainer/logs/logs_linux_test.go
+++ b/libcontainer/logs/logs_linux_test.go
@@ -13,7 +13,6 @@ import (
 
 func TestLoggingToFile(t *testing.T) {
 	l := runLogForwarding(t)
-	defer l.cleanup()
 
 	logToLogWriter(t, l, `{"level": "info","msg":"kitten"}`)
 	finish(t, l)
@@ -22,7 +21,6 @@ func TestLoggingToFile(t *testing.T) {
 
 func TestLogForwardingDoesNotStopOnJsonDecodeErr(t *testing.T) {
 	l := runLogForwarding(t)
-	defer l.cleanup()
 
 	logToLogWriter(t, l, "invalid-json-with-kitten")
 	checkWait(t, l, "failed to decode")
@@ -36,7 +34,6 @@ func TestLogForwardingDoesNotStopOnJsonDecodeErr(t *testing.T) {
 
 func TestLogForwardingDoesNotStopOnLogLevelParsingErr(t *testing.T) {
 	l := runLogForwarding(t)
-	defer l.cleanup()
 
 	logToLogWriter(t, l, `{"level": "alert","msg":"puppy"}`)
 	checkWait(t, l, "failed to parse log level")
@@ -50,7 +47,6 @@ func TestLogForwardingDoesNotStopOnLogLevelParsingErr(t *testing.T) {
 
 func TestLogForwardingStopsAfterClosingTheWriter(t *testing.T) {
 	l := runLogForwarding(t)
-	defer l.cleanup()
 
 	logToLogWriter(t, l, `{"level": "info","msg":"sync"}`)
 
@@ -77,9 +73,6 @@ type log struct {
 	w    io.WriteCloser
 	file string
 	done chan error
-
-	// TODO: use t.Cleanup after dropping support for Go 1.13
-	cleanup func()
 }
 
 func runLogForwarding(t *testing.T) *log {
@@ -88,6 +81,10 @@ func runLogForwarding(t *testing.T) *log {
 	if err != nil {
 		t.Fatal(err)
 	}
+	t.Cleanup(func() {
+		logR.Close()
+		logW.Close()
+	})
 
 	tempFile, err := ioutil.TempFile("", "")
 	if err != nil {
@@ -95,6 +92,7 @@ func runLogForwarding(t *testing.T) *log {
 	}
 	tempFile.Close()
 	logFile := tempFile.Name()
+	t.Cleanup(func() { os.Remove(logFile) })
 
 	logConfig := Config{LogLevel: logrus.InfoLevel, LogFormat: "json", LogFilePath: logFile}
 	loggingConfigured = false
@@ -104,13 +102,7 @@ func runLogForwarding(t *testing.T) *log {
 
 	doneForwarding := ForwardLogs(logR)
 
-	cleanup := func() {
-		os.Remove(logFile)
-		logR.Close()
-		logW.Close()
-	}
-
-	return &log{w: logW, done: doneForwarding, file: logFile, cleanup: cleanup}
+	return &log{w: logW, done: doneForwarding, file: logFile}
 }
 
 func finish(t *testing.T, l *log) {