From 2e55f8b5eb8ab6c5146b3962104c063b2dbd3204 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 fef2f90f099..30337fff22b 100644 --- a/libcontainer/cgroups/file.go +++ b/libcontainer/cgroups/file.go @@ -4,6 +4,7 @@ import ( "bytes" "os" "path" + "strconv" "strings" "sync" @@ -134,6 +135,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} }