@@ -37,14 +37,14 @@ type Handle struct {
3737
3838// OpenProcRoot tries to open a "safer" handle to "/proc" (i.e., one with the
3939// "subset=pid" mount option applied, available from Linux 5.8). Unless you
40- // plan to do many operations with [ProcRoot] , users should prefer to use this
41- // over [OpenUnsafeProcRoot] which is far more dangerous to keep open.
40+ // plan to do many [Handle.OpenRoot] operations , users should prefer to use
41+ // this over [OpenUnsafeProcRoot] which is far more dangerous to keep open.
4242//
4343// If a safe handle cannot be opened, OpenProcRoot will fall back to opening a
4444// regular "/proc" handle.
4545//
46- // Note that using [ProcRoot ] will still work with handles returned by this
47- // function. If a [ProcRoot] subpath cannot be operated on with a safe "/proc"
46+ // Note that using [Handle.OpenRoot ] will still work with handles returned by
47+ // this function. If a subpath cannot be operated on with a safe "/proc"
4848// handle, then [OpenUnsafeProcRoot] will be called internally and a temporary
4949// unsafe handle will be used.
5050func OpenProcRoot () (* Handle , error ) {
@@ -60,12 +60,13 @@ func OpenProcRoot() (*Handle, error) {
6060// never leaked to a container and that you program cannot be tricked into
6161// writing to arbitrary paths within it.
6262//
63- // This is not necessary if you just wish to use [ProcRoot ], as handles
63+ // This is not necessary if you just wish to use [Handle.OpenRoot ], as handles
6464// returned by [OpenProcRoot] will fall back to using a *temporary* unsafe
6565// handle in that case. You should only really use this if you need to do many
66- // operations on [ProcRoot] and the performance overhead of making many procfs
67- // handles is an issue, and you should make sure to close the handle as soon as
68- // possible to avoid known-fd-number attacks.
66+ // operations with [Handle.OpenRoot] and the performance overhead of making
67+ // many procfs handles is an issue. If you do use OpenUnsafeProcRoot, you
68+ // should make sure to close the handle as soon as possible to avoid
69+ // known-fd-number attacks.
6970func OpenUnsafeProcRoot () (* Handle , error ) {
7071 proc , err := procfs .OpenUnsafeProcRoot ()
7172 if err != nil {
@@ -77,8 +78,10 @@ func OpenUnsafeProcRoot() (*Handle, error) {
7778// OpenThreadSelf returns a handle to "/proc/thread-self/<subpath>" (or an
7879// equivalent handle on older kernels where "/proc/thread-self" doesn't exist).
7980// Once finished with the handle, you must call the returned closer function
80- // (runtime.UnlockOSThread). You must not pass the returned *os.File to other
81+ // ([ runtime.UnlockOSThread] ). You must not pass the returned *os.File to other
8182// Go threads or use the handle after calling the closer.
83+ //
84+ // [runtime.UnlockOSThread]: https://pkg.go.dev/runtime#UnlockOSThread
8285func (proc * Handle ) OpenThreadSelf (subpath string ) (* os.File , ProcThreadSelfCloser , error ) {
8386 return proc .inner .OpenThreadSelf (subpath )
8487}
@@ -87,20 +90,24 @@ func (proc *Handle) OpenThreadSelf(subpath string) (*os.File, ProcThreadSelfClos
8790//
8891// Note that in Go programs with non-homogenous threads, this may result in
8992// spurious errors. If you are monkeying around with APIs that are
90- // thread-specific, you probably want to use [ProcThreadSelf ] instead which
91- // will guarantee that the handle refers to the same thread as the caller is
92- // executing on.
93+ // thread-specific, you probably want to use [Handle.OpenThreadSelf ] instead
94+ // which will guarantee that the handle refers to the same thread as the caller
95+ // is executing on.
9396func (proc * Handle ) OpenSelf (subpath string ) (* os.File , error ) {
9497 return proc .inner .OpenSelf (subpath )
9598}
9699
97100// OpenRoot returns a handle to /proc/<subpath>.
98101//
99102// You should only use this when you need to operate on global procfs files
100- // (such as sysctls in /proc/sys). Unlike [OpenThreadSelf], [OpenSelf], and
101- // [ProcPid], the procfs handle used internally for this operation will never
102- // use subset=pids, which makes it a more juicy target for CVE-2024-21626-style
103- // attacks.
103+ // (such as sysctls in /proc/sys). Unlike [Handle.OpenThreadSelf],
104+ // [Handle.OpenSelf], and [Handle.OpenPid], the procfs handle used internally
105+ // for this operation will never use "subset=pid", which makes it a more juicy
106+ // target for [CVE-2024-21626]-style attacks (and doing something like opening
107+ // a directory with OpenRoot effectively leaks [OpenUnsafeProcRoot] as long as
108+ // the file descriptor is open).
109+ //
110+ // [CVE-2024-21626]: https://github.com/opencontainers/runc/security/advisories/GHSA-xr7r-f8xq-vfvv
104111func (proc * Handle ) OpenRoot (subpath string ) (* os.File , error ) {
105112 return proc .inner .OpenRoot (subpath )
106113}
@@ -110,19 +117,35 @@ func (proc *Handle) OpenRoot(subpath string) (*os.File, error) {
110117//
111118// You should not use this for the current thread, as special handling is
112119// needed for /proc/thread-self (or /proc/self/task/<tid>) when dealing with
113- // goroutine scheduling -- use [OpenThreadSelf] instead.
114- //
115- // To refer to the current thread-group, you should use prefer [OpenSelf] to
116- // passing os.Getpid as the pid argument.
120+ // goroutine scheduling -- use [Handle.OpenThreadSelf] instead.
117121//
118- // If you want to operate on the top-level /proc filesystem , you should use
119- // [OpenRoot] instead .
122+ // To refer to the current thread-group , you should use prefer
123+ // [Handle.OpenSelf] to passing os.Getpid as the pid argument .
120124func (proc * Handle ) OpenPid (pid int , subpath string ) (* os.File , error ) {
121125 return proc .inner .OpenPid (pid , subpath )
122126}
123127
124128// ProcSelfFdReadlink gets the real path of the given file by looking at
125- // readlink(/proc/thread-self/fd/$n).
129+ // /proc/self/fd/<fd> with [readlink]. It is effectively just shorthand for
130+ // something along the lines of:
131+ //
132+ // proc, err := procfs.OpenProcRoot()
133+ // if err != nil {
134+ // return err
135+ // }
136+ // link, err := proc.OpenThreadSelf(fmt.Sprintf("fd/%d", f.Fd()))
137+ // if err != nil {
138+ // return err
139+ // }
140+ // defer link.Close()
141+ // var buf [4096]byte
142+ // n, err := unix.Readlinkat(int(link.Fd()), "", buf[:])
143+ // if err != nil {
144+ // return err
145+ // }
146+ // pathname := buf[:n]
147+ //
148+ // [readlink]: https://pkg.go.dev/golang.org/x/sys/unix#Readlinkat
126149func ProcSelfFdReadlink (f * os.File ) (string , error ) {
127150 return procfs .ProcSelfFdReadlink (f )
128151}
0 commit comments