Skip to content

Commit 41fc4b7

Browse files
committed
mountinfo: run filter after all fields are parsed
Previously, the filter would be run before all of the fields were parsed (this behaviour also was not documented) -- this resulted in users of the function accidentally assuming that fields like fsinfo.Root would actually be filled correctly. It seems that the performance overhead of parsing a few extra fields is not exorbitant, and optimising this just leads to incorrect user code. For a concrete example, this optimisation actually made this runc change[1] regress a security hardening feature because it relied on fsinfo.Root being filled correctly. [1]: opencontainers/runc#2647 Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
1 parent 99cfd57 commit 41fc4b7

2 files changed

Lines changed: 11 additions & 16 deletions

File tree

mountinfo/mountinfo_filters.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ import "strings"
66
// used to filter out mountinfo entries we're not interested in,
77
// and/or stop further processing if we found what we wanted.
88
//
9-
// It takes a pointer to the Info struct (not fully populated,
10-
// currently only Mountpoint, FSType, Source, and (on Linux)
11-
// VFSOptions are filled in), and returns two booleans:
9+
// It takes a pointer to the Info struct (fully populated with all available
10+
// fields on the GOOS platform), and returns two booleans:
1211
//
1312
// skip: true if the entry should be skipped;
1413
//

mountinfo/mountinfo_linux.go

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ func GetMountsFromReader(r io.Reader, filter FilterFunc) ([]*Info, error) {
7272

7373
p := &Info{}
7474

75-
// Fill in the fields that a filter might check
7675
p.Mountpoint, err = unescape(fields[4])
7776
if err != nil {
7877
return nil, fmt.Errorf("Parsing '%s' failed: mount point: %w", fields[4], err)
@@ -87,18 +86,6 @@ func GetMountsFromReader(r io.Reader, filter FilterFunc) ([]*Info, error) {
8786
}
8887
p.VFSOptions = fields[sepIdx+3]
8988

90-
// Run a filter early so we can skip parsing/adding entries
91-
// the caller is not interested in
92-
var skip, stop bool
93-
if filter != nil {
94-
skip, stop = filter(p)
95-
if skip {
96-
continue
97-
}
98-
}
99-
100-
// Fill in the rest of the fields
101-
10289
// ignore any numbers parsing errors, as there should not be any
10390
p.ID, _ = strconv.Atoi(fields[0])
10491
p.Parent, _ = strconv.Atoi(fields[1])
@@ -126,6 +113,15 @@ func GetMountsFromReader(r io.Reader, filter FilterFunc) ([]*Info, error) {
126113
p.Optional = strings.Join(fields[6:sepIdx-1], " ")
127114
}
128115

116+
// Run the filter after parsing all of the fields.
117+
var skip, stop bool
118+
if filter != nil {
119+
skip, stop = filter(p)
120+
if skip {
121+
continue
122+
}
123+
}
124+
129125
out = append(out, p)
130126
if stop {
131127
break

0 commit comments

Comments
 (0)