From 3d98676626409c3d619c37f3325cce4e444ccba9 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Wed, 13 Oct 2021 12:36:17 -0700 Subject: [PATCH 1/4] ci/gha: install latest stable Go version Jobs verify/compile-buildtags and verify/deps relied on whatever Go version is available from the Ubuntu-20.04 image, which seems to be 1.15.x). Job test/cross-i386 was installing whatever Go version is considered to be the default one by actions/setup-go@v2, which seems to be go 1.15.15 at the moment. Fix all three jobs to install Go 1.x (which should translate to latest stable Go version, i.e. 1.17.2 as of now). Signed-off-by: Kir Kolyshkin --- .github/workflows/test.yml | 4 +++- .github/workflows/validate.yml | 8 ++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 653c5c9fdbb..36e8f2a52a2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -119,7 +119,9 @@ jobs: sudo apt -q install libseccomp-dev libseccomp-dev:i386 gcc-multilib criu - name: install go - uses: actions/setup-go@v2 # use default Go version + uses: actions/setup-go@v2 + with: + go-version: 1.x # Latest stable - name: unit test # cgo is disabled by default when cross-compiling diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 0a812a5cd32..80a14db7419 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -30,6 +30,10 @@ jobs: CGO_CFLAGS: -g -O2 -Werror steps: - uses: actions/checkout@v2 + - name: install go + uses: actions/setup-go@v2 + with: + go-version: 1.x # Latest stable - name: compile with no build tags run: make BUILDTAGS="" @@ -93,6 +97,10 @@ jobs: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 + - name: install go + uses: actions/setup-go@v2 + with: + go-version: 1.x # Latest stable - name: cache go mod and $GOCACHE uses: actions/cache@v2 with: From 12e99a0f8df0e6ac59e82ec6941c70dbe12d7142 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Wed, 13 Oct 2021 12:25:29 -0700 Subject: [PATCH 2/4] Require Go >= 1.16 Go 1.15 is not supported since Go 1.17 release (16 Aug 2021), and some packages that we use already require Go 1.16+ (notably, github.com/cilium/ebpf v0.7.0). Let's require Go 1.16+. Remove Go version requirement from README when describing dependencies, since it is no longer needed: $ GO=go1.15.15 make vendor go1.15.15 mod tidy go mod tidy: go.mod file indicates go 1.16, but maximum supported version is 1.15 make: *** [Makefile:141: vendor] Error 1 Signed-off-by: Kir Kolyshkin --- .github/workflows/test.yml | 2 +- README.md | 4 ++-- go.mod | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 36e8f2a52a2..3eaeb3aeb03 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,7 +21,7 @@ jobs: strategy: fail-fast: false matrix: - go-version: [1.15.x, 1.16.x, 1.17.x] + go-version: [1.16.x, 1.17.x] rootless: ["rootless", ""] race: ["-race", ""] criu: [""] diff --git a/README.md b/README.md index d7797653379..0d701a3452f 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ 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.15 or higher. +`runc` only supports Linux. It must be built with Go version 1.16 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 @@ -110,7 +110,7 @@ You can run a test using your container engine's flags by setting `CONTAINER_ENG `runc` uses [Go Modules](https://github.com/golang/go/wiki/Modules) for dependencies management. Please refer to [Go Modules](https://github.com/golang/go/wiki/Modules) for how to add or update -new dependencies. When updating dependencies, be sure that you are running Go `1.14` or newer. +new dependencies. ``` # Update vendored dependencies diff --git a/go.mod b/go.mod index 9442f1dd211..a57f29a4369 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/opencontainers/runc -go 1.15 +go 1.16 require ( github.com/checkpoint-restore/go-criu/v5 v5.1.0 From 6a4f4a6a370383365f2ae9d515e94a784be85bb8 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Wed, 13 Oct 2021 12:45:54 -0700 Subject: [PATCH 3/4] libcontainer/ignoreTerminateErrors: simplify for Go 1.16+ One less TODO in the code, yay! Signed-off-by: Kir Kolyshkin --- libcontainer/container_linux.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go index df78a950f0a..d0969a27c63 100644 --- a/libcontainer/container_linux.go +++ b/libcontainer/container_linux.go @@ -2150,13 +2150,11 @@ func ignoreTerminateErrors(err error) error { if errors.As(err, &exitErr) { return nil } - // TODO: use errors.Is(err, os.ErrProcessDone) here and - // remove "process already finished" string comparison below - // once go 1.16 is minimally supported version. - + if errors.Is(err, os.ErrProcessDone) { + return nil + } s := err.Error() - if strings.Contains(s, "process already finished") || - strings.Contains(s, "Wait was already called") { + if strings.Contains(s, "Wait was already called") { return nil } return err From 55162941720ba91b87c7d05f9e6a91b9f308f33d Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Wed, 13 Oct 2021 13:24:01 -0700 Subject: [PATCH 4/4] Remove io/ioutil use See https://golang.org/doc/go1.16#ioutil Signed-off-by: Kir Kolyshkin --- contrib/cmd/recvtty/recvtty.go | 5 +-- contrib/cmd/seccompagent/seccompagent.go | 3 +- libcontainer/apparmor/apparmor_linux.go | 3 +- .../capabilities/capabilities_linux_test.go | 4 +- libcontainer/cgroups/fs/blkio_test.go | 2 +- libcontainer/cgroups/fs2/io_test.go | 4 +- libcontainer/cgroups/fscommon/utils_test.go | 11 +++--- libcontainer/cgroups/utils.go | 3 +- libcontainer/configs/config_test.go | 3 +- libcontainer/container_linux.go | 9 ++--- libcontainer/devices/device_unix.go | 7 ++-- .../devices/device_unix_go116_test.go | 39 +++++++++++++++++++ .../devices/device_unix_go117_test.go | 8 ++++ libcontainer/devices/device_unix_test.go | 14 +++---- libcontainer/init_linux.go | 3 +- libcontainer/integration/exec_test.go | 3 +- libcontainer/intelrdt/intelrdt.go | 9 ++--- libcontainer/intelrdt/monitoring.go | 3 +- libcontainer/intelrdt/monitoring_test.go | 3 +- libcontainer/logs/logs_linux_test.go | 5 +-- libcontainer/network_linux.go | 4 +- libcontainer/notify_linux.go | 3 +- libcontainer/notify_linux_test.go | 7 ++-- libcontainer/rootfs_linux.go | 7 ++-- libcontainer/system/proc.go | 4 +- libcontainer/utils/utils_unix.go | 2 +- list.go | 13 ++++--- spec.go | 3 +- 28 files changed, 108 insertions(+), 76 deletions(-) create mode 100644 libcontainer/devices/device_unix_go116_test.go create mode 100644 libcontainer/devices/device_unix_go117_test.go diff --git a/contrib/cmd/recvtty/recvtty.go b/contrib/cmd/recvtty/recvtty.go index 14f71154806..35c293de642 100644 --- a/contrib/cmd/recvtty/recvtty.go +++ b/contrib/cmd/recvtty/recvtty.go @@ -20,7 +20,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "net" "os" "strings" @@ -177,7 +176,7 @@ func handleNull(path string) error { return } - _, _ = io.Copy(ioutil.Discard, master) + _, _ = io.Copy(io.Discard, master) }(conn) } } @@ -225,7 +224,7 @@ func main() { pidPath := ctx.String("pid-file") if pidPath != "" { pid := fmt.Sprintf("%d\n", os.Getpid()) - if err := ioutil.WriteFile(pidPath, []byte(pid), 0o644); err != nil { + if err := os.WriteFile(pidPath, []byte(pid), 0o644); err != nil { return err } } diff --git a/contrib/cmd/seccompagent/seccompagent.go b/contrib/cmd/seccompagent/seccompagent.go index efc400c670c..9a6abc8f0b6 100644 --- a/contrib/cmd/seccompagent/seccompagent.go +++ b/contrib/cmd/seccompagent/seccompagent.go @@ -9,7 +9,6 @@ import ( "errors" "flag" "fmt" - "io/ioutil" "net" "os" "path/filepath" @@ -246,7 +245,7 @@ func main() { if pidFile != "" { pid := fmt.Sprintf("%d", os.Getpid()) - if err := ioutil.WriteFile(pidFile, []byte(pid), 0o644); err != nil { + if err := os.WriteFile(pidFile, []byte(pid), 0o644); err != nil { logrus.Fatalf("Cannot write pid file: %v", err) } } diff --git a/libcontainer/apparmor/apparmor_linux.go b/libcontainer/apparmor/apparmor_linux.go index 17262913e0b..8b1483c7de7 100644 --- a/libcontainer/apparmor/apparmor_linux.go +++ b/libcontainer/apparmor/apparmor_linux.go @@ -3,7 +3,6 @@ package apparmor import ( "errors" "fmt" - "io/ioutil" "os" "sync" @@ -19,7 +18,7 @@ var ( func isEnabled() bool { checkAppArmor.Do(func() { if _, err := os.Stat("/sys/kernel/security/apparmor"); err == nil { - buf, err := ioutil.ReadFile("/sys/module/apparmor/parameters/enabled") + buf, err := os.ReadFile("/sys/module/apparmor/parameters/enabled") appArmorEnabled = err == nil && len(buf) > 1 && buf[0] == 'Y' } }) diff --git a/libcontainer/capabilities/capabilities_linux_test.go b/libcontainer/capabilities/capabilities_linux_test.go index 13a50e83349..dfbb44b4a3f 100644 --- a/libcontainer/capabilities/capabilities_linux_test.go +++ b/libcontainer/capabilities/capabilities_linux_test.go @@ -1,7 +1,7 @@ package capabilities import ( - "io/ioutil" + "io" "os" "testing" @@ -24,7 +24,7 @@ func TestNew(t *testing.T) { hook := test.NewGlobal() defer hook.Reset() - logrus.SetOutput(ioutil.Discard) + logrus.SetOutput(io.Discard) caps, err := New(&conf) logrus.SetOutput(os.Stderr) diff --git a/libcontainer/cgroups/fs/blkio_test.go b/libcontainer/cgroups/fs/blkio_test.go index 7810a67fc31..5f93cd0ad5b 100644 --- a/libcontainer/cgroups/fs/blkio_test.go +++ b/libcontainer/cgroups/fs/blkio_test.go @@ -258,7 +258,7 @@ func TestBlkioSetMultipleWeightDevice(t *testing.T) { wd1 := configs.NewWeightDevice(8, 0, 500, 0) wd2 := configs.NewWeightDevice(8, 16, 500, 0) - // we cannot actually set and check both because normal ioutil.WriteFile + // we cannot actually set and check both because normal os.WriteFile // when writing to cgroup file will overwrite the whole file content instead // of updating it as the kernel is doing. Just check the second device // is present will suffice for the test to ensure multiple writes are done. diff --git a/libcontainer/cgroups/fs2/io_test.go b/libcontainer/cgroups/fs2/io_test.go index d7ad1c56c97..15bb64a1d2d 100644 --- a/libcontainer/cgroups/fs2/io_test.go +++ b/libcontainer/cgroups/fs2/io_test.go @@ -1,7 +1,7 @@ package fs2 import ( - "io/ioutil" + "os" "path/filepath" "reflect" "sort" @@ -62,7 +62,7 @@ func TestStatIo(t *testing.T) { fakeCgroupDir := t.TempDir() statPath := filepath.Join(fakeCgroupDir, "io.stat") - if err := ioutil.WriteFile(statPath, []byte(exampleIoStatData), 0o644); err != nil { + if err := os.WriteFile(statPath, []byte(exampleIoStatData), 0o644); err != nil { t.Fatal(err) } diff --git a/libcontainer/cgroups/fscommon/utils_test.go b/libcontainer/cgroups/fscommon/utils_test.go index 6470a47a1c6..0339e998904 100644 --- a/libcontainer/cgroups/fscommon/utils_test.go +++ b/libcontainer/cgroups/fscommon/utils_test.go @@ -1,7 +1,6 @@ package fscommon import ( - "io/ioutil" "math" "os" "path/filepath" @@ -27,7 +26,7 @@ func TestGetCgroupParamsInt(t *testing.T) { tempFile := filepath.Join(tempDir, cgroupFile) // Success. - if err := ioutil.WriteFile(tempFile, []byte(floatString), 0o755); err != nil { + if err := os.WriteFile(tempFile, []byte(floatString), 0o755); err != nil { t.Fatal(err) } value, err := GetCgroupParamUint(tempDir, cgroupFile) @@ -38,7 +37,7 @@ func TestGetCgroupParamsInt(t *testing.T) { } // Success with new line. - err = ioutil.WriteFile(tempFile, []byte(floatString+"\n"), 0o755) + err = os.WriteFile(tempFile, []byte(floatString+"\n"), 0o755) if err != nil { t.Fatal(err) } @@ -50,7 +49,7 @@ func TestGetCgroupParamsInt(t *testing.T) { } // Success with negative values - err = ioutil.WriteFile(tempFile, []byte("-12345"), 0o755) + err = os.WriteFile(tempFile, []byte("-12345"), 0o755) if err != nil { t.Fatal(err) } @@ -63,7 +62,7 @@ func TestGetCgroupParamsInt(t *testing.T) { // Success with negative values lesser than min int64 s := strconv.FormatFloat(math.MinInt64, 'f', -1, 64) - err = ioutil.WriteFile(tempFile, []byte(s), 0o755) + err = os.WriteFile(tempFile, []byte(s), 0o755) if err != nil { t.Fatal(err) } @@ -75,7 +74,7 @@ func TestGetCgroupParamsInt(t *testing.T) { } // Not a float. - err = ioutil.WriteFile(tempFile, []byte("not-a-float"), 0o755) + err = os.WriteFile(tempFile, []byte("not-a-float"), 0o755) if err != nil { t.Fatal(err) } diff --git a/libcontainer/cgroups/utils.go b/libcontainer/cgroups/utils.go index 3bab0e75a95..6c96882c680 100644 --- a/libcontainer/cgroups/utils.go +++ b/libcontainer/cgroups/utils.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "os" "path/filepath" "strconv" @@ -243,7 +242,7 @@ func RemovePath(path string) error { return nil } - infos, err := ioutil.ReadDir(path) + infos, err := os.ReadDir(path) if err != nil { if os.IsNotExist(err) { err = nil diff --git a/libcontainer/configs/config_test.go b/libcontainer/configs/config_test.go index ca825153fd0..5c29b747fce 100644 --- a/libcontainer/configs/config_test.go +++ b/libcontainer/configs/config_test.go @@ -3,7 +3,6 @@ package configs_test import ( "encoding/json" "fmt" - "io/ioutil" "os" "reflect" "testing" @@ -190,7 +189,7 @@ exit 0 verifyCommand := fmt.Sprintf(verifyCommandTemplate, stateJson) filename := "/tmp/runc-hooktest.sh" os.Remove(filename) - if err := ioutil.WriteFile(filename, []byte(verifyCommand), 0o700); err != nil { + if err := os.WriteFile(filename, []byte(verifyCommand), 0o700); err != nil { t.Fatalf("Failed to create tmp file: %v", err) } defer os.Remove(filename) diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go index d0969a27c63..50fa621475d 100644 --- a/libcontainer/container_linux.go +++ b/libcontainer/container_linux.go @@ -6,7 +6,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "net" "os" "os/exec" @@ -286,7 +285,7 @@ func (c *linuxContainer) exec() error { } func readFromExecFifo(execFifo io.Reader) error { - data, err := ioutil.ReadAll(execFifo) + data, err := io.ReadAll(execFifo) if err != nil { return err } @@ -1151,7 +1150,7 @@ func (c *linuxContainer) Checkpoint(criuOpts *CriuOpts) error { return err } - err = ioutil.WriteFile(filepath.Join(criuOpts.ImagesDirectory, descriptorsFilename), fdsJSON, 0o600) + err = os.WriteFile(filepath.Join(criuOpts.ImagesDirectory, descriptorsFilename), fdsJSON, 0o600) if err != nil { return err } @@ -1455,7 +1454,7 @@ func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error { fds []string fdJSON []byte ) - if fdJSON, err = ioutil.ReadFile(filepath.Join(criuOpts.ImagesDirectory, descriptorsFilename)); err != nil { + if fdJSON, err = os.ReadFile(filepath.Join(criuOpts.ImagesDirectory, descriptorsFilename)); err != nil { return err } @@ -1850,7 +1849,7 @@ func (c *linuxContainer) updateState(process parentProcess) (*State, error) { } func (c *linuxContainer) saveState(s *State) (retErr error) { - tmpFile, err := ioutil.TempFile(c.root, "state-") + tmpFile, err := os.CreateTemp(c.root, "state-") if err != nil { return err } diff --git a/libcontainer/devices/device_unix.go b/libcontainer/devices/device_unix.go index e2af4ff2cce..7d8e9fc3104 100644 --- a/libcontainer/devices/device_unix.go +++ b/libcontainer/devices/device_unix.go @@ -5,7 +5,6 @@ package devices import ( "errors" - "io/ioutil" "os" "path/filepath" @@ -17,8 +16,8 @@ var ErrNotADevice = errors.New("not a device node") // Testing dependencies var ( - unixLstat = unix.Lstat - ioutilReadDir = ioutil.ReadDir + unixLstat = unix.Lstat + osReadDir = os.ReadDir ) func mkDev(d *Rule) (uint64, error) { @@ -77,7 +76,7 @@ func HostDevices() ([]*Device, error) { // GetDevices recursively traverses a directory specified by path // and returns all devices found there. func GetDevices(path string) ([]*Device, error) { - files, err := ioutilReadDir(path) + files, err := osReadDir(path) if err != nil { return nil, err } diff --git a/libcontainer/devices/device_unix_go116_test.go b/libcontainer/devices/device_unix_go116_test.go new file mode 100644 index 00000000000..5e1cdf272de --- /dev/null +++ b/libcontainer/devices/device_unix_go116_test.go @@ -0,0 +1,39 @@ +//go:build !go1.17 +// +build !go1.17 + +package devices + +import "io/fs" + +// The following code is adapted from go1.17.1/src/io/fs/readdir.go +// to compensate for the lack of fs.FileInfoToDirEntry in Go 1.16. + +// dirInfo is a DirEntry based on a FileInfo. +type dirInfo struct { + fileInfo fs.FileInfo +} + +func (di dirInfo) IsDir() bool { + return di.fileInfo.IsDir() +} + +func (di dirInfo) Type() fs.FileMode { + return di.fileInfo.Mode().Type() +} + +func (di dirInfo) Info() (fs.FileInfo, error) { + return di.fileInfo, nil +} + +func (di dirInfo) Name() string { + return di.fileInfo.Name() +} + +// fileInfoToDirEntry returns a DirEntry that returns information from info. +// If info is nil, FileInfoToDirEntry returns nil. +func fileInfoToDirEntry(info fs.FileInfo) fs.DirEntry { + if info == nil { + return nil + } + return dirInfo{fileInfo: info} +} diff --git a/libcontainer/devices/device_unix_go117_test.go b/libcontainer/devices/device_unix_go117_test.go new file mode 100644 index 00000000000..d74db8f1598 --- /dev/null +++ b/libcontainer/devices/device_unix_go117_test.go @@ -0,0 +1,8 @@ +//go:build go1.17 +// +build go1.17 + +package devices + +import "io/fs" + +var fileInfoToDirEntry = fs.FileInfoToDirEntry diff --git a/libcontainer/devices/device_unix_test.go b/libcontainer/devices/device_unix_test.go index 9a93359f4ff..c58256cd0da 100644 --- a/libcontainer/devices/device_unix_test.go +++ b/libcontainer/devices/device_unix_test.go @@ -5,7 +5,7 @@ package devices import ( "errors" - "io/ioutil" + "io/fs" "os" "testing" @@ -14,7 +14,7 @@ import ( func cleanupTest() { unixLstat = unix.Lstat - ioutilReadDir = ioutil.ReadDir + osReadDir = os.ReadDir } func TestDeviceFromPathLstatFailure(t *testing.T) { @@ -35,8 +35,8 @@ func TestDeviceFromPathLstatFailure(t *testing.T) { func TestHostDevicesIoutilReadDirFailure(t *testing.T) { testError := errors.New("test error") - // Override ioutil.ReadDir to inject error. - ioutilReadDir = func(dirname string) ([]os.FileInfo, error) { + // Override os.ReadDir to inject error. + osReadDir = func(dirname string) ([]fs.DirEntry, error) { return nil, testError } defer cleanupTest() @@ -51,8 +51,8 @@ func TestHostDevicesIoutilReadDirDeepFailure(t *testing.T) { testError := errors.New("test error") called := false - // Override ioutil.ReadDir to inject error after the first call. - ioutilReadDir = func(dirname string) ([]os.FileInfo, error) { + // Override os.ReadDir to inject error after the first call. + osReadDir = func(dirname string) ([]fs.DirEntry, error) { if called { return nil, testError } @@ -64,7 +64,7 @@ func TestHostDevicesIoutilReadDirDeepFailure(t *testing.T) { t.Fatalf("Unexpected error %v", err) } - return []os.FileInfo{fi}, nil + return []fs.DirEntry{fileInfoToDirEntry(fi)}, nil } defer cleanupTest() diff --git a/libcontainer/init_linux.go b/libcontainer/init_linux.go index 9f7dc75f2e9..216e5efa97b 100644 --- a/libcontainer/init_linux.go +++ b/libcontainer/init_linux.go @@ -6,7 +6,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "net" "os" "strings" @@ -358,7 +357,7 @@ func setupUser(config *initConfig) error { return err } - setgroups, err := ioutil.ReadFile("/proc/self/setgroups") + setgroups, err := os.ReadFile("/proc/self/setgroups") if err != nil && !os.IsNotExist(err) { return err } diff --git a/libcontainer/integration/exec_test.go b/libcontainer/integration/exec_test.go index 28f2e10d2c0..0c79c9f7e22 100644 --- a/libcontainer/integration/exec_test.go +++ b/libcontainer/integration/exec_test.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/json" "fmt" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -879,7 +878,7 @@ func TestMountCmds(t *testing.T) { // Wait for process waitProcess(&pconfig, t) - entries, err := ioutil.ReadDir(tmpDir) + entries, err := os.ReadDir(tmpDir) ok(t, err) expected := []string{"hello", "hello-backup", "world", "world-backup"} for i, e := range entries { diff --git a/libcontainer/intelrdt/intelrdt.go b/libcontainer/intelrdt/intelrdt.go index 62179f01f64..23931c5b1ff 100644 --- a/libcontainer/intelrdt/intelrdt.go +++ b/libcontainer/intelrdt/intelrdt.go @@ -6,7 +6,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "os" "path/filepath" "strconv" @@ -367,7 +366,7 @@ func parseCpuInfoFile(path string) (cpuInfoFlags, error) { // Gets a single uint64 value from the specified file. func getIntelRdtParamUint(path, file string) (uint64, error) { fileName := filepath.Join(path, file) - contents, err := ioutil.ReadFile(fileName) + contents, err := os.ReadFile(fileName) if err != nil { return 0, err } @@ -381,7 +380,7 @@ func getIntelRdtParamUint(path, file string) (uint64, error) { // Gets a string value from the specified file func getIntelRdtParamString(path, file string) (string, error) { - contents, err := ioutil.ReadFile(filepath.Join(path, file)) + contents, err := os.ReadFile(filepath.Join(path, file)) if err != nil { return "", err } @@ -393,7 +392,7 @@ func writeFile(dir, file, data string) error { if dir == "" { return fmt.Errorf("no such directory for %s", file) } - if err := ioutil.WriteFile(filepath.Join(dir, file), []byte(data+"\n"), 0o600); err != nil { + if err := os.WriteFile(filepath.Join(dir, file), []byte(data+"\n"), 0o600); err != nil { return newLastCmdError(fmt.Errorf("intelrdt: unable to write %v: %w", data, err)) } return nil @@ -488,7 +487,7 @@ func WriteIntelRdtTasks(dir string, pid int) error { // Don't attach any pid if -1 is specified as a pid if pid != -1 { - if err := ioutil.WriteFile(filepath.Join(dir, intelRdtTasks), []byte(strconv.Itoa(pid)), 0o600); err != nil { + if err := os.WriteFile(filepath.Join(dir, intelRdtTasks), []byte(strconv.Itoa(pid)), 0o600); err != nil { return newLastCmdError(fmt.Errorf("intelrdt: unable to add pid %d: %w", pid, err)) } } diff --git a/libcontainer/intelrdt/monitoring.go b/libcontainer/intelrdt/monitoring.go index 547c15470f2..82e0002efad 100644 --- a/libcontainer/intelrdt/monitoring.go +++ b/libcontainer/intelrdt/monitoring.go @@ -3,7 +3,6 @@ package intelrdt import ( "bufio" "io" - "io/ioutil" "os" "path/filepath" @@ -49,7 +48,7 @@ func parseMonFeatures(reader io.Reader) (monFeatures, error) { } func getMonitoringStats(containerPath string, stats *Stats) error { - numaFiles, err := ioutil.ReadDir(filepath.Join(containerPath, "mon_data")) + numaFiles, err := os.ReadDir(filepath.Join(containerPath, "mon_data")) if err != nil { return err } diff --git a/libcontainer/intelrdt/monitoring_test.go b/libcontainer/intelrdt/monitoring_test.go index 7685fa31bd2..0a89ef2f7b8 100644 --- a/libcontainer/intelrdt/monitoring_test.go +++ b/libcontainer/intelrdt/monitoring_test.go @@ -1,7 +1,6 @@ package intelrdt import ( - "io/ioutil" "os" "path/filepath" "strconv" @@ -51,7 +50,7 @@ func mockResctrlL3_MON(t *testing.T, NUMANodes []string, mocks map[string]uint64 } for fileName, value := range mocks { - err := ioutil.WriteFile(filepath.Join(numaPath, fileName), []byte(strconv.FormatUint(value, 10)), 0o644) + err := os.WriteFile(filepath.Join(numaPath, fileName), []byte(strconv.FormatUint(value, 10)), 0o644) if err != nil { t.Fatal(err) } diff --git a/libcontainer/logs/logs_linux_test.go b/libcontainer/logs/logs_linux_test.go index d6563fd2e0e..12640483b10 100644 --- a/libcontainer/logs/logs_linux_test.go +++ b/libcontainer/logs/logs_linux_test.go @@ -3,7 +3,6 @@ package logs import ( "bytes" "io" - "io/ioutil" "os" "testing" "time" @@ -93,7 +92,7 @@ func runLogForwarding(t *testing.T) *log { logW.Close() }) - tempFile, err := ioutil.TempFile("", "") + tempFile, err := os.CreateTemp("", "") if err != nil { t.Fatal(err) } @@ -129,7 +128,7 @@ func truncateLogFile(t *testing.T, file *os.File) { // check checks that the file contains txt and does not contain notxt. func check(t *testing.T, l *log, txt, notxt string) { t.Helper() - contents, err := ioutil.ReadFile(l.file.Name()) + contents, err := os.ReadFile(l.file.Name()) if err != nil { t.Fatal(err) } diff --git a/libcontainer/network_linux.go b/libcontainer/network_linux.go index aa2be8ffc17..8915548b3bc 100644 --- a/libcontainer/network_linux.go +++ b/libcontainer/network_linux.go @@ -3,7 +3,7 @@ package libcontainer import ( "bytes" "fmt" - "io/ioutil" + "os" "path/filepath" "strconv" @@ -73,7 +73,7 @@ func getNetworkInterfaceStats(interfaceName string) (*types.NetworkInterface, er // Reads the specified statistics available under /sys/class/net//statistics func readSysfsNetworkStats(ethInterface, statsFile string) (uint64, error) { - data, err := ioutil.ReadFile(filepath.Join("/sys/class/net", ethInterface, "statistics", statsFile)) + data, err := os.ReadFile(filepath.Join("/sys/class/net", ethInterface, "statistics", statsFile)) if err != nil { return 0, err } diff --git a/libcontainer/notify_linux.go b/libcontainer/notify_linux.go index 0ec1a55c3f5..a8762842e8f 100644 --- a/libcontainer/notify_linux.go +++ b/libcontainer/notify_linux.go @@ -3,7 +3,6 @@ package libcontainer import ( "errors" "fmt" - "io/ioutil" "os" "path/filepath" @@ -33,7 +32,7 @@ func registerMemoryEvent(cgDir string, evName string, arg string) (<-chan struct eventControlPath := filepath.Join(cgDir, "cgroup.event_control") data := fmt.Sprintf("%d %d %s", eventfd.Fd(), evFile.Fd(), arg) - if err := ioutil.WriteFile(eventControlPath, []byte(data), 0o700); err != nil { + if err := os.WriteFile(eventControlPath, []byte(data), 0o700); err != nil { eventfd.Close() evFile.Close() return nil, err diff --git a/libcontainer/notify_linux_test.go b/libcontainer/notify_linux_test.go index cf0f90f4d2c..3967f07f007 100644 --- a/libcontainer/notify_linux_test.go +++ b/libcontainer/notify_linux_test.go @@ -3,7 +3,6 @@ package libcontainer import ( "encoding/binary" "fmt" - "io/ioutil" "os" "path/filepath" "testing" @@ -18,10 +17,10 @@ func testMemoryNotification(t *testing.T, evName string, notify notifyFunc, targ memoryPath := t.TempDir() evFile := filepath.Join(memoryPath, evName) eventPath := filepath.Join(memoryPath, "cgroup.event_control") - if err := ioutil.WriteFile(evFile, []byte{}, 0o700); err != nil { + if err := os.WriteFile(evFile, []byte{}, 0o700); err != nil { t.Fatal(err) } - if err := ioutil.WriteFile(eventPath, []byte{}, 0o700); err != nil { + if err := os.WriteFile(eventPath, []byte{}, 0o700); err != nil { t.Fatal(err) } ch, err := notify(memoryPath) @@ -29,7 +28,7 @@ func testMemoryNotification(t *testing.T, evName string, notify notifyFunc, targ t.Fatal("expected no error, got:", err) } - data, err := ioutil.ReadFile(eventPath) + data, err := os.ReadFile(eventPath) if err != nil { t.Fatal("couldn't read event control file:", err) } diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go index 19bc96d55d0..72eb2b429d2 100644 --- a/libcontainer/rootfs_linux.go +++ b/libcontainer/rootfs_linux.go @@ -4,7 +4,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "os" "os/exec" "path" @@ -182,7 +181,7 @@ func finalizeRootfs(config *configs.Config) (err error) { // /tmp has to be mounted as private to allow MS_MOVE to work in all situations func prepareTmp(topTmpDir string) (string, error) { - tmpdir, err := ioutil.TempDir(topTmpDir, "runctop") + tmpdir, err := os.MkdirTemp(topTmpDir, "runctop") if err != nil { return "", err } @@ -337,7 +336,7 @@ func doTmpfsCopyUp(m *configs.Mount, rootfs, mountLabel string) (Err error) { return fmt.Errorf("tmpcopyup: failed to setup tmpdir: %w", err) } defer cleanupTmp(tmpdir) - tmpDir, err := ioutil.TempDir(tmpdir, "runctmpdir") + tmpDir, err := os.MkdirTemp(tmpdir, "runctmpdir") if err != nil { return fmt.Errorf("tmpcopyup: failed to create tmpdir: %w", err) } @@ -1034,7 +1033,7 @@ func maskPath(path string, mountLabel string) error { // For e.g. net.ipv4.ip_forward translated to /proc/sys/net/ipv4/ip_forward. func writeSystemProperty(key, value string) error { keyPath := strings.Replace(key, ".", "/", -1) - return ioutil.WriteFile(path.Join("/proc/sys", keyPath), []byte(value), 0o644) + return os.WriteFile(path.Join("/proc/sys", keyPath), []byte(value), 0o644) } func remount(m *configs.Mount, rootfs string) error { diff --git a/libcontainer/system/proc.go b/libcontainer/system/proc.go index 8f0a68afd12..774443ec9d2 100644 --- a/libcontainer/system/proc.go +++ b/libcontainer/system/proc.go @@ -2,7 +2,7 @@ package system import ( "fmt" - "io/ioutil" + "os" "path/filepath" "strconv" "strings" @@ -67,7 +67,7 @@ type Stat_t struct { // Stat returns a Stat_t instance for the specified process. func Stat(pid int) (stat Stat_t, err error) { - bytes, err := ioutil.ReadFile(filepath.Join("/proc", strconv.Itoa(pid), "stat")) + bytes, err := os.ReadFile(filepath.Join("/proc", strconv.Itoa(pid), "stat")) if err != nil { return stat, err } diff --git a/libcontainer/utils/utils_unix.go b/libcontainer/utils/utils_unix.go index 3b303e189ef..220d0b43937 100644 --- a/libcontainer/utils/utils_unix.go +++ b/libcontainer/utils/utils_unix.go @@ -53,7 +53,7 @@ func CloseExecFrom(minFd int) error { // Intentionally ignore errors from unix.CloseOnExec -- the cases where // this might fail are basically file descriptors that have already // been closed (including and especially the one that was created when - // ioutil.ReadDir did the "opendir" syscall). + // os.ReadDir did the "opendir" syscall). unix.CloseOnExec(fd) } return nil diff --git a/list.go b/list.go index 38d9869d41b..3503dcd2f5e 100644 --- a/list.go +++ b/list.go @@ -4,7 +4,6 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" "os" "path/filepath" "syscall" @@ -121,7 +120,7 @@ func getContainers(context *cli.Context) ([]containerState, error) { if err != nil { return nil, err } - list, err := ioutil.ReadDir(absRoot) + list, err := os.ReadDir(absRoot) if err != nil { fatal(err) } @@ -129,11 +128,15 @@ func getContainers(context *cli.Context) ([]containerState, error) { var s []containerState for _, item := range list { if item.IsDir() { + st, err := os.Stat(filepath.Join(absRoot, item.Name())) + if err != nil { + fatal(err) + } // This cast is safe on Linux. - stat := item.Sys().(*syscall.Stat_t) - owner, err := user.LookupUid(int(stat.Uid)) + uid := st.Sys().(*syscall.Stat_t).Uid + owner, err := user.LookupUid(int(uid)) if err != nil { - owner.Name = fmt.Sprintf("#%d", stat.Uid) + owner.Name = fmt.Sprintf("#%d", uid) } container, err := factory.Load(item.Name()) diff --git a/spec.go b/spec.go index 87d6ebea871..806d2f15f86 100644 --- a/spec.go +++ b/spec.go @@ -3,7 +3,6 @@ package main import ( "encoding/json" "fmt" - "io/ioutil" "os" "github.com/opencontainers/runc/libcontainer/configs" @@ -109,7 +108,7 @@ created by an unprivileged user. if err != nil { return err } - return ioutil.WriteFile(specConfig, data, 0o666) + return os.WriteFile(specConfig, data, 0o666) }, }