Skip to content

Commit a4e0878

Browse files
authored
Merge pull request #128 from cyphar/mountinfo-linux-thread-self
mountinfo: linux: use /proc/thread-self/mountinfo
2 parents c0711cd + 12c61a3 commit a4e0878

File tree

1 file changed

+31
-3
lines changed

1 file changed

+31
-3
lines changed

mountinfo/mountinfo_linux.go

+31-3
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,19 @@ import (
55
"fmt"
66
"io"
77
"os"
8+
"runtime"
89
"strconv"
910
"strings"
11+
"sync"
12+
13+
"golang.org/x/sys/unix"
1014
)
1115

1216
// GetMountsFromReader retrieves a list of mounts from the
1317
// reader provided, with an optional filter applied (use nil
1418
// for no filter). This can be useful in tests or benchmarks
1519
// that provide fake mountinfo data, or when a source other
16-
// than /proc/self/mountinfo needs to be read from.
20+
// than /proc/thread-self/mountinfo needs to be read from.
1721
//
1822
// This function is Linux-specific.
1923
func GetMountsFromReader(r io.Reader, filter FilterFunc) ([]*Info, error) {
@@ -127,8 +131,32 @@ func GetMountsFromReader(r io.Reader, filter FilterFunc) ([]*Info, error) {
127131
return out, nil
128132
}
129133

130-
func parseMountTable(filter FilterFunc) ([]*Info, error) {
131-
f, err := os.Open("/proc/self/mountinfo")
134+
var (
135+
haveProcThreadSelf bool
136+
haveProcThreadSelfOnce sync.Once
137+
)
138+
139+
func parseMountTable(filter FilterFunc) (_ []*Info, err error) {
140+
haveProcThreadSelfOnce.Do(func() {
141+
_, err := os.Stat("/proc/thread-self/mountinfo")
142+
haveProcThreadSelf = err == nil
143+
})
144+
145+
// We need to lock ourselves to the current OS thread in order to make sure
146+
// that the thread referenced by /proc/thread-self stays alive until we
147+
// finish parsing the file.
148+
runtime.LockOSThread()
149+
defer runtime.UnlockOSThread()
150+
151+
var f *os.File
152+
if haveProcThreadSelf {
153+
f, err = os.Open("/proc/thread-self/mountinfo")
154+
} else {
155+
// On pre-3.17 kernels (such as CentOS 7), we don't have
156+
// /proc/thread-self/ so we need to manually construct
157+
// /proc/self/task/<tid>/ as a fallback.
158+
f, err = os.Open("/proc/self/task/" + strconv.Itoa(unix.Gettid()) + "/mountinfo")
159+
}
132160
if err != nil {
133161
return nil, err
134162
}

0 commit comments

Comments
 (0)