// EnsureProcHandle returns whether or not the given file handle is on procfs. func EnsureProcHandle(fh *os.File) error { … } var haveCloseRangeCloexecBool … var haveCloseRangeCloexecOnce … func haveCloseRangeCloexec() bool { … } type fdFunc … // fdRangeFrom calls the passed fdFunc for each file descriptor that is open in // the current process. func fdRangeFrom(minFd int, fn fdFunc) error { … } // CloseExecFrom sets the O_CLOEXEC flag on all file descriptors greater or // equal to minFd in the current process. func CloseExecFrom(minFd int) error { … } // In order to make sure we do not close the internal epoll descriptors the Go // runtime uses, we need to ensure that we skip descriptors that match // "internal/poll".IsPollDescriptor. Yes, this is a Go runtime internal thing, // unfortunately there's no other way to be sure we're only keeping the file // descriptors the Go runtime needs. Hopefully nothing blows up doing this... func runtime_IsPollDescriptor(fd uintptr) bool // UnsafeCloseFrom closes all file descriptors greater or equal to minFd in the // current process, except for those critical to Go's runtime (such as the // netpoll management descriptors). // // NOTE: That this function is incredibly dangerous to use in most Go code, as // closing file descriptors from underneath *os.File handles can lead to very // bad behaviour (the closed file descriptor can be re-used and then any // *os.File operations would apply to the wrong file). This function is only // intended to be called from the last stage of runc init. func UnsafeCloseFrom(minFd int) error { … } // NewSockPair returns a new SOCK_STREAM unix socket pair. func NewSockPair(name string) (parent, child *os.File, err error) { … } // WithProcfd runs the passed closure with a procfd path (/proc/self/fd/...) // corresponding to the unsafePath resolved within the root. Before passing the // fd, this path is verified to have been inside the root -- so operating on it // through the passed fdpath should be safe. Do not access this path through // the original path strings, and do not attempt to use the pathname outside of // the passed closure (the file handle will be freed once the closure returns). func WithProcfd(root, unsafePath string, fn func(procfd string) error) error { … } type ProcThreadSelfCloser … var haveProcThreadSelf … var haveProcThreadSelfOnce … // ProcThreadSelf returns a string that is equivalent to // /proc/thread-self/<subpath>, with a graceful fallback on older kernels where // /proc/thread-self doesn't exist. This method DOES NOT use SecureJoin, // meaning that the passed string needs to be trusted. The caller _must_ call // the returned procThreadSelfCloser function (which is runtime.UnlockOSThread) // *only once* after it has finished using the returned path string. func ProcThreadSelf(subpath string) (string, ProcThreadSelfCloser) { … } // ProcThreadSelfFd is small wrapper around ProcThreadSelf to make it easier to // create a /proc/thread-self handle for given file descriptor. // // It is basically equivalent to ProcThreadSelf(fmt.Sprintf("fd/%d", fd)), but // without using fmt.Sprintf to avoid unneeded overhead. func ProcThreadSelfFd(fd uintptr) (string, ProcThreadSelfCloser) { … } // IsLexicallyInRoot is shorthand for strings.HasPrefix(path+"/", root+"/"), // but properly handling the case where path or root are "/". // // NOTE: The return value only make sense if the path doesn't contain "..". func IsLexicallyInRoot(root, path string) bool { … } // MkdirAllInRootOpen attempts to make // // path, _ := securejoin.SecureJoin(root, unsafePath) // os.MkdirAll(path, mode) // os.Open(path) // // safer against attacks where components in the path are changed between // SecureJoin returning and MkdirAll (or Open) being called. In particular, we // try to detect any symlink components in the path while we are doing the // MkdirAll. // // NOTE: Unlike os.MkdirAll, mode is not Go's os.FileMode, it is the unix mode // (the suid/sgid/sticky bits are not the same as for os.FileMode). // // NOTE: If unsafePath is a subpath of root, we assume that you have already // called SecureJoin and so we use the provided path verbatim without resolving // any symlinks (this is done in a way that avoids symlink-exchange races). // This means that the path also must not contain ".." elements, otherwise an // error will occur. // // This uses securejoin.MkdirAllHandle under the hood, but it has special // handling if unsafePath has already been scoped within the rootfs (this is // needed for a lot of runc callers and fixing this would require reworking a // lot of path logic). func MkdirAllInRootOpen(root, unsafePath string, mode uint32) (_ *os.File, Err error) { … } // MkdirAllInRoot is a wrapper around MkdirAllInRootOpen which closes the // returned handle, for callers that don't need to use it. func MkdirAllInRoot(root, unsafePath string, mode uint32) error { … } // Openat is a Go-friendly openat(2) wrapper. func Openat(dir *os.File, path string, flags int, mode uint32) (*os.File, error) { … }