Repository: opencontainers/runc
Pull request #4292 (2024-05-25 00:04:56)

Stop blacklisting Go 1.22+, drop Go < 1.21 support, use Go 1.22 in CI
High level overview:
 - remove nsenter compile restriction since Go 1.22.4 and Go 1.23 can now be used. THIS PART NEEDS TO BE BACKPORTED TO 1.1.
 - switch to Go 1.22 in CI whether possible (everywhere except Ubuntu 20.04 and CentOS 7 and 8).
 - set minimum requirement to Go 1.21
 - rm some old code.

See individual commits for details.

kolyshkin: We'll probably need to port the first 3 patches to release-1.1 (so that it will work with Go 1.22).
kolyshkin: > btw, it seems the ubuntu builds are stalled.

This PR drops go 1.20.x tests, but they are marked as required in repo config -- this is why they are shown as "Expected -- waiting ...". I will fix the repo config accordingly (rm go 1.20.x, require go 1.22.x) once this PR will be ready to be merged (I guess once Go 1.21.4 is out).
kolyshkin: @opencontainers/runc-maintainers wdyt?
kolyshkin: @lifubang @cyphar PTAL
AkihiroSuda: CentOS tests seem failing
thaJeztah: > CentOS tests seem failing

For CentOS stream 8, that may be expected; it's EOL since May 31 (just got hit by that in some CI pipeline that als had it in the Matrix)
AkihiroSuda: > > CentOS tests seem failing
> 
> For CentOS stream 8, that may be expected; it's EOL since May 31 (just got hit by that in some CI pipeline that als had it in the Matrix)

I guess we now have to replace CentOS with Alma, Rocky, or Oracle Linux?
lifubang: This one should be merged after go 1.22.4 has released.
kolyshkin: Go 1.22.4 is out, this PR is rebased with the following change:

```diff
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 4c40b47b..7155c163 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -30,11 +30,6 @@ jobs:
         criu: ["", "criu-dev"]
         dmz: ["", "runc_nodmz"]
         exclude:
-          # Go 1.22 + glibc < 2.32 + nsenter does not play well (issue 4233),
-          # thus nsenter package won't compile. Disable ubuntu 20.04 + go 1.22.
-          # TODO: remove this once Go 1.22.4 is out.
-          - os: ubuntu-20.04
-            go-version: 1.22.x
           # Disable most of criu-dev jobs, as they are expensive
           # (need to compile criu) and don't add much value/coverage.
           - criu: criu-dev
```
kolyshkin: Ah, `actions/setup-go` still installs go 1.22.3 (given go 1.22.x). They always lag behind (see https://github.com/actions/setup-go/issues/407).

Have to wait a few days I guess (or specify the version number explicitly, which I don't want to).
kolyshkin: @lifubang PTAL (except for pinning go in ci to 1.22.4 this is all good, and we can revert this patch later)
AkihiroSuda: Needs rebase

Patch:
diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml
index e5108c32..ad4929b2 100644
--- a/.github/workflows/validate.yml
+++ b/.github/workflows/validate.yml
@@ -8,7 +8,7 @@ on:
       - release-*
   pull_request:
 env:
-  GO_VERSION: 1.20.x
+  GO_VERSION: 1.22.x
 permissions:
   contents: read
 
@@ -117,6 +117,7 @@ jobs:
       uses: actions/setup-go@v5
       with:
         go-version: "${{ env.GO_VERSION }}"
+        check-latest: true
     - name: verify deps
       run: make verify-dependencies
 
diff --git a/Dockerfile b/Dockerfile
index 79e0aafb..d04a9588 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-ARG GO_VERSION=1.21
+ARG GO_VERSION=1.22
 ARG BATS_VERSION=v1.9.0
 ARG LIBSECCOMP_VERSION=2.5.5
 
diff --git a/README.md b/README.md
index 6d8ac4d4..2d532f98 100644
--- a/README.md
+++ b/README.md
@@ -27,7 +27,11 @@ A third party security audit was performed by Cure53, you can see the full repor
 
 ## Building
 
-`runc` only supports Linux. It must be built with Go version 1.19 or higher.
+`runc` only supports Linux. It must be built with Go version 1.21 or higher.
+
+NOTE: if building with Go 1.22.x, make sure to use 1.22.4 or a later version
+(see [issue #4233](https://github.com/opencontainers/runc/issues/4233) for
+more details).
 
 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 9c15a6bf..98b23ab8 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
 module github.com/opencontainers/runc
 
-go 1.20
+go 1.21
 
 require (
 	github.com/checkpoint-restore/go-criu/v6 v6.3.0
diff --git a/go.sum b/go.sum
index 59f2fc9f..13b88a48 100644
--- a/go.sum
+++ b/go.sum
@@ -17,15 +17,19 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
 github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
 github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA=
+github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
 github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
 github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
 github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g=
 github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
 github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg=
@@ -39,6 +43,7 @@ github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M5
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
+github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
 github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/seccomp/libseccomp-golang v0.10.0 h1:aA4bp+/Zzi0BnWZ2F1wgNBs5gTpm+na2rWM6M9YjLpY=
diff --git a/libcontainer/cgroups/utils.go b/libcontainer/cgroups/utils.go
index 186cbc64..8bec8c36 100644
--- a/libcontainer/cgroups/utils.go
+++ b/libcontainer/cgroups/utils.go
@@ -275,9 +275,7 @@ func RemovePaths(paths map[string]string) (err error) {
 		}
 	}
 	if len(paths) == 0 {
-		//nolint:ineffassign,staticcheck // done to help garbage collecting: opencontainers/runc#2506
-		// TODO: switch to clear once Go < 1.21 is not supported.
-		paths = make(map[string]string)
+		clear(paths)
 		return nil
 	}
 	return fmt.Errorf("Failed to remove paths: %v", paths)
diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go
index 13be71cc..ad49244a 100644
--- a/libcontainer/container_linux.go
+++ b/libcontainer/container_linux.go
@@ -10,6 +10,7 @@ import (
 	"path"
 	"path/filepath"
 	"reflect"
+	"slices"
 	"strconv"
 	"strings"
 	"sync"
@@ -452,16 +453,6 @@ func (c *Container) includeExecFifo(cmd *exec.Cmd) error {
 	return nil
 }
 
-// No longer needed in Go 1.21.
-func slicesContains[S ~[]E, E comparable](slice S, needle E) bool {
-	for _, val := range slice {
-		if val == needle {
-			return true
-		}
-	}
-	return false
-}
-
 func isDmzBinarySafe(c *configs.Config) bool {
 	// Because we set the dumpable flag in nsexec, the only time when it is
 	// unsafe to use runc-dmz is when the container process would be able to
@@ -472,9 +463,9 @@ func isDmzBinarySafe(c *configs.Config) bool {
 	// inheritable, or ambient sets). Luckily, most containers do not have this
 	// capability.
 	if c.Capabilities == nil ||
-		(!slicesContains(c.Capabilities.Bounding, "CAP_SYS_PTRACE") &&
-			!slicesContains(c.Capabilities.Inheritable, "CAP_SYS_PTRACE") &&
-			!slicesContains(c.Capabilities.Ambient, "CAP_SYS_PTRACE")) {
+		(!slices.Contains(c.Capabilities.Bounding, "CAP_SYS_PTRACE") &&
+			!slices.Contains(c.Capabilities.Inheritable, "CAP_SYS_PTRACE") &&
+			!slices.Contains(c.Capabilities.Ambient, "CAP_SYS_PTRACE")) {
 		return true
 	}
 
diff --git a/libcontainer/eaccess_go119.go b/libcontainer/eaccess_go119.go
deleted file mode 100644
index cc1e2079..00000000
--- a/libcontainer/eaccess_go119.go
+++ /dev/null
@@ -1,17 +0,0 @@
-//go:build !go1.20
-// +build !go1.20
-
-package libcontainer
-
-import "golang.org/x/sys/unix"
-
-func eaccess(path string) error {
-	// This check is similar to access(2) with X_OK except for
-	// setuid/setgid binaries where it checks against the effective
-	// (rather than real) uid and gid. It is not needed in go 1.20
-	// and beyond and will be removed later.
-
-	// Relies on code added in https://go-review.googlesource.com/c/sys/+/468877
-	// and older CLs linked from there.
-	return unix.Faccessat(unix.AT_FDCWD, path, unix.X_OK, unix.AT_EACCESS)
-}
diff --git a/libcontainer/eaccess_stub.go b/libcontainer/eaccess_stub.go
deleted file mode 100644
index 7c049fd7..00000000
--- a/libcontainer/eaccess_stub.go
+++ /dev/null
@@ -1,10 +0,0 @@
-//go:build go1.20
-
-package libcontainer
-
-func eaccess(path string) error {
-	// Not needed in Go 1.20+ as the functionality is already in there
-	// (added by https://go.dev/cl/416115, https://go.dev/cl/414824,
-	// and fixed in Go 1.20.2 by https://go.dev/cl/469956).
-	return nil
-}
diff --git a/libcontainer/nsenter/nsenter_go122.go b/libcontainer/nsenter/nsenter_go122.go
deleted file mode 100644
index 2b9ece0a..00000000
--- a/libcontainer/nsenter/nsenter_go122.go
+++ /dev/null
@@ -1,15 +0,0 @@
-//go:build go1.22
-
-package nsenter
-
-/*
-// We know for sure that glibc has issues with pthread_self() when called from
-// Go after nsenter has run. This is likely a more general problem with how we
-// ignore the rules in signal-safety(7), and so it's possible musl will also
-// have issues, but as this is just a hotfix let's only block glibc builds.
-#include <features.h>
-#ifdef __GLIBC__
-#  error "runc does not currently work properly with Go >=1.22. See <https://github.com/opencontainers/runc/issues/4233>."
-#endif
-*/
-import "C"
diff --git a/libcontainer/setns_init_linux.go b/libcontainer/setns_init_linux.go
index de3a15f6..d1419877 100644
--- a/libcontainer/setns_init_linux.go
+++ b/libcontainer/setns_init_linux.go
@@ -117,13 +117,6 @@ func (l *linuxSetnsInit) Init() error {
 	if err != nil {
 		return err
 	}
-	// exec.LookPath in Go < 1.20 might return no error for an executable
-	// residing on a file system mounted with noexec flag, so perform this
-	// extra check now while we can still return a proper error.
-	// TODO: remove this once go < 1.20 is not supported.
-	if err := eaccess(name); err != nil {
-		return &os.PathError{Op: "eaccess", Path: name, Err: err}
-	}
 	// Set seccomp as close to execve as possible, so as few syscalls take
 	// place afterward (reducing the amount of syscalls that users need to
 	// enable in their seccomp profiles).
diff --git a/libcontainer/standard_init_linux.go b/libcontainer/standard_init_linux.go
index 4b7aa677..ec2e8143 100644
--- a/libcontainer/standard_init_linux.go
+++ b/libcontainer/standard_init_linux.go
@@ -211,13 +211,6 @@ func (l *linuxStandardInit) Init() error {
 	if err != nil {
 		return err
 	}
-	// exec.LookPath in Go < 1.20 might return no error for an executable
-	// residing on a file system mounted with noexec flag, so perform this
-	// extra check now while we can still return a proper error.
-	// TODO: remove this once go < 1.20 is not supported.
-	if err := eaccess(name); err != nil {
-		return &os.PathError{Op: "eaccess", Path: name, Err: err}
-	}
 
 	// Set seccomp as close to execve as possible, so as few syscalls take
 	// place afterward (reducing the amount of syscalls that users need to


Test patch:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index ea93554c..73cbf652 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -24,7 +24,7 @@ jobs:
       fail-fast: false
       matrix:
         os: [ubuntu-20.04, ubuntu-24.04, actuated-arm64-6cpu-8gb]
-        go-version: [1.20.x, 1.21.x]
+        go-version: [1.21.x, 1.22.x]
         rootless: ["rootless", ""]
         race: ["-race", ""]
         criu: ["", "criu-dev"]
@@ -33,7 +33,7 @@ jobs:
           # Disable most of criu-dev jobs, as they are expensive
           # (need to compile criu) and don't add much value/coverage.
           - criu: criu-dev
-            go-version: 1.20.x
+            go-version: 1.21.x
           - criu: criu-dev
             rootless: rootless
           - criu: criu-dev
@@ -45,12 +45,12 @@ jobs:
           - dmz: runc_nodmz
             os: ubuntu-20.04
           - dmz: runc_nodmz
-            go-version: 1.20.x
+            go-version: 1.21.x
           - dmz: runc_nodmz
             rootless: rootless
           - dmz: runc_nodmz
             race: -race
-          - go-version: 1.20.x
+          - go-version: 1.21.x
             os: actuated-arm64-6cpu-8gb
           - race: "-race"
             os: actuated-arm64-6cpu-8gb
@@ -147,6 +147,7 @@ jobs:
       uses: actions/setup-go@v5
       with:
         go-version: ${{ matrix.go-version }}
+        check-latest: true
 
     - name: build
       env:
@@ -225,7 +226,8 @@ jobs:
     - name: install go
       uses: actions/setup-go@v5
       with:
-        go-version: 1.21.x # TODO: switch to 1.x (latest stable) once Go 1.22 vs glibc issue is fixed.
+        go-version: 1.x # Latest stable
+        check-latest: true
 
     - name: unit test
       env: