Repository: opencontainers/runc
File: libcontainer/cgroups/file.go (Go)

Code before:
	}
	path := path.Join(dir, utils.CleanPath(file))
	if prepareOpenat2() != nil {
		return openFallback(path, flags, mode)
	}
	relPath, ok := strings.CutPrefix(path, cgroupfsPrefix)
	if !ok { // Non-standard path, old system?
		return openFallback(path, flags, mode)
	}

	fd, err := unix.Openat2(int(cgroupRootHandle.Fd()), relPath,
		&unix.OpenHow{
			Resolve: resolveFlags,
			Flags:   uint64(flags) | unix.O_CLOEXEC,
			Mode:    uint64(mode),
		})
	if err != nil {
		err = &os.PathError{Op: "openat2", Path: path, Err: err}
		// Check if cgroupRootHandle is still opened to cgroupfsDir
		// (happens when this package is incorrectly used
		// across the chroot/pivot_root/mntns boundary, or
		// when /sys/fs/cgroup is remounted).
		//
		// TODO: if such usage will ever be common, amend this
		// to reopen cgroupRootHandle and retry openat2.
		fdDest, _ := os.Readlink("/proc/thread-self/fd/" + strconv.Itoa(int(cgroupRootHandle.Fd())))
		if fdDest != cgroupfsDir {
			// Wrap the error so it is clear that cgroupRootHandle
			// is opened to an unexpected/wrong directory.
			err = fmt.Errorf("cgroupRootHandle %d unexpectedly opened to %s != %s: %w",
				cgroupRootHandle.Fd(), fdDest, cgroupfsDir, err)
		}
		return nil, err
	}

	return os.NewFile(uintptr(fd), path), nil
}

var errNotCgroupfs = errors.New("not a cgroup file")

// Can be changed by unit tests.
var openFallback = openAndCheck

// openAndCheck is used when openat2(2) is not available. It checks the opened
// file is on cgroupfs, returning an error otherwise.
func openAndCheck(path string, flags int, mode os.FileMode) (*os.File, error) {
	fd, err := os.OpenFile(path, flags, mode)
	if err != nil {
		return nil, err
	}
	if TestMode {

Review comment (bug):
Maybe there are some way to make `/proc/thread-self` inaccessible, for example:
1. Some mount options for proc fs;
2. Kernel customization;
3. Custom selinux rules.

So I think we still need to fallback to `/proc/self/task/$TID` when /proc/thread-self is inaccessible, but I think it's not very important here, because this is an error message enhancement, maybe we can change the code like this:
```go
if fdDest, err1 := os.Readlink("/proc/thread-self/fd/" + strconv.Itoa(int(cgroupRootHandle.Fd()))); err1 == nil && fdDest != cgroupfsDir {
    // Wrap the error so it is clear that cgroupRootHandle
    // is opened to an unexpected/wrong directory.
    err = fmt.Errorf("cgroupRootHandle %d unexpectedly opened to %s != %s: %w",
		cgroupRootHandle.Fd(), fdDest, cgroupfsDir, err)
}
```
Or add a check `fdDest != ""` in the next if.

Code after:
	// NOTE it is important to use filepath.Clean("/"+file) here
	// (see https://github.com/opencontainers/runc/issues/4103)!
	path := filepath.Join(dir, filepath.Clean("/"+file))

	if prepareOpenat2() != nil {
		return openFallback(path, flags, mode)
	}
	relPath, ok := strings.CutPrefix(path, cgroupfsPrefix)
	if !ok { // Non-standard path, old system?
		return openFallback(path, flags, mode)
	}

	fd, err := unix.Openat2(int(cgroupRootHandle.Fd()), relPath,
		&unix.OpenHow{
			Resolve: resolveFlags,
			Flags:   uint64(flags) | unix.O_CLOEXEC,
			Mode:    uint64(mode),
		})
	if err != nil {
		err = &os.PathError{Op: "openat2", Path: path, Err: err}
		// Check if cgroupRootHandle is still opened to cgroupfsDir
		// (happens when this package is incorrectly used
		// across the chroot/pivot_root/mntns boundary, or
		// when /sys/fs/cgroup is remounted).
		//
		// TODO: if such usage will ever be common, amend this
		// to reopen cgroupRootHandle and retry openat2.
		fdDest, fdErr := os.Readlink("/proc/thread-self/fd/" + strconv.Itoa(int(cgroupRootHandle.Fd())))
		if fdErr == nil && fdDest != cgroupfsDir {
			// Wrap the error so it is clear that cgroupRootHandle
			// is opened to an unexpected/wrong directory.
			err = fmt.Errorf("cgroupRootHandle %d unexpectedly opened to %s != %s: %w",
				cgroupRootHandle.Fd(), fdDest, cgroupfsDir, err)
		}
		return nil, err
	}

	return os.NewFile(uintptr(fd), path), nil
}

var errNotCgroupfs = errors.New("not a cgroup file")

// Can be changed by unit tests.
var openFallback = openAndCheck

// openAndCheck is used when openat2(2) is not available. It checks the opened
// file is on cgroupfs, returning an error otherwise.
func openAndCheck(path string, flags int, mode os.FileMode) (*os.File, error) {
	fd, err := os.OpenFile(path, flags, mode)
	if err != nil {
		return nil, err