From a0bd98c60ec1d7151d7888e7fa44ff5bb26b49c3 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Mon, 14 Jun 2021 19:50:54 -0700 Subject: [PATCH] libct/cg/OpenFile: check cgroupFd on error opencontainers/runc issue 3026 describes a scenario in which OpenFile failed to open a legitimate existing cgroupfs file. Added debug (similar to what this commit does) shown that cgroupFd is no longer opened to "/sys/fs/cgroup", but to "/" (it's not clear what caused it, and the source code is not available, but it might be caused by using the same process on the both sides of the container boundary). Consider such use incorrect, but give a helpful hint as two what is going on by enriching the Path component of the error with the fd information. NB: this can potentially be fixed by reopening the cgroupFd once we detected that it's screwed, and retrying openat2. Alas I do not have a test case for this, so left this as a TODO suggestion. Signed-off-by: Kir Kolyshkin --- libcontainer/cgroups/file.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libcontainer/cgroups/file.go b/libcontainer/cgroups/file.go index aaf0ef1c978..461bc29ebdc 100644 --- a/libcontainer/cgroups/file.go +++ b/libcontainer/cgroups/file.go @@ -6,6 +6,7 @@ import ( "fmt" "os" "path" + "strconv" "strings" "sync" @@ -137,6 +138,17 @@ func openFile(dir, file string, flags int) (*os.File, error) { Mode: uint64(mode), }) if err != nil { + // Check if cgroupFd is still opened to cgroupfsDir. + fdStr := strconv.Itoa(cgroupFd) + fdDest, _ := os.Readlink("/proc/self/fd/" + fdStr) + if fdDest != cgroupfsDir { + // TODO: reopen cgroupFd and retry openat2. + + // Enhance the Path in the error to contain the + // cgroupFd value and the directory it is opened to, + // for example: "@[fd 7:/!=/sys/fs/cgroup]/cpu.stat". + path = "@[fd " + fdStr + ":" + fdDest + "!=" + cgroupfsDir + "]/" + relPath + } return nil, &os.PathError{Op: "openat2", Path: path, Err: err} }