Skip to content

Commit 682f2bc

Browse files
committed
mountinfo.mountedByMountinfo: normalize path
Currently, the path provided to mountinfo.Mounted() must be - an absolute path; - with all symlinks resolved; - cleaned. Otherwise, the function may return a false negative (in case this is a bind mount and the kernel is too old to have openat2) -- i.e. it will return "not mounted" while the path is in fact mounted. This commit removes the above limitation by doing a path normalization. This should slow things down but it's not affecting any of the fast paths, so the slowdown will only be seen in the "bind mount and older kernel" case (which is already pretty slow since we have to parse mountinfo). v2: as in mountedByOpenat2 and mountedByStat, treat ENOENT as "not mounted". Signed-off-by: Kir Kolyshkin <[email protected]>
1 parent 0c38c02 commit 682f2bc

2 files changed

Lines changed: 25 additions & 3 deletions

File tree

mountinfo/doc.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,8 @@
1414
// parse filters while reading mountinfo. A filter can skip some entries, or stop
1515
// processing the rest of the file once the needed information is found.
1616
//
17-
// For functions that have path as an argument (such as Mounted or various filters),
18-
// the argument must be
19-
// - an absolute path;
17+
// For mountinfo filters that accept path as an argument, the path must be:
18+
// - absolute;
2019
// - having all symlinks resolved;
2120
// - being cleaned.
2221
//

mountinfo/mounted_unix.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
package mountinfo
44

55
import (
6+
"errors"
7+
"fmt"
68
"os"
79
"path/filepath"
810

@@ -33,7 +35,28 @@ func mountedByStat(path string) (bool, error) {
3335
return false, nil
3436
}
3537

38+
func normalizePath(path string) (realPath string, err error) {
39+
if realPath, err = filepath.Abs(path); err != nil {
40+
return "", fmt.Errorf("unable to get absolute path for %q: %w", path, err)
41+
}
42+
if realPath, err = filepath.EvalSymlinks(realPath); err != nil {
43+
return "", fmt.Errorf("failed to canonicalise path for %q: %w", path, err)
44+
}
45+
if _, err := os.Stat(realPath); err != nil {
46+
return "", fmt.Errorf("failed to stat target of %q: %w", path, err)
47+
}
48+
return realPath, nil
49+
}
50+
3651
func mountedByMountinfo(path string) (bool, error) {
52+
path, err := normalizePath(path)
53+
if err != nil {
54+
if errors.Is(err, unix.ENOENT) {
55+
// treat ENOENT as "not mounted"
56+
return false, nil
57+
}
58+
return false, err
59+
}
3760
entries, err := GetMounts(SingleEntryFilter(path))
3861
if err != nil {
3962
return false, err

0 commit comments

Comments
 (0)