From 60ac70da172c8cd50f343e52ae6f282e5d8bc94f Mon Sep 17 00:00:00 2001 From: Nadav Strahilevitz Date: Wed, 25 Sep 2024 13:45:10 +0000 Subject: [PATCH] fix(mount): apply to shortest mount root --- pkg/mount/mount.go | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/pkg/mount/mount.go b/pkg/mount/mount.go index 87c7823f3a15..46a0deb81794 100644 --- a/pkg/mount/mount.go +++ b/pkg/mount/mount.go @@ -4,6 +4,7 @@ import ( "bufio" "os" "path/filepath" + "slices" "strings" "syscall" @@ -217,11 +218,11 @@ func IsFileSystemSupported(fsType string) (bool, error) { // - int: The inode number of the matching mountpoint. // - error: Any error encountered while reading the /proc/mounts file. func SearchMountpointFromHost(fstype string, search string) (string, int, error) { + const mountRootIndex = 3 const mountpointIndex = 4 - const fsTypeIndex = 8 - mp := "" - inode := 0 + mp := "" // matched mountpoint search var + inode := 0 // matched mountpoint's inode file, err := os.Open(procMounts) if err != nil { @@ -236,15 +237,26 @@ func SearchMountpointFromHost(fstype string, search string) (string, int, error) scanner := bufio.NewScanner(file) for scanner.Scan() { line := strings.Split(scanner.Text(), " ") - if len(line) <= fsTypeIndex { - continue // Skip lines that do not have enough fields - } - - mountpoint := line[mountpointIndex] - currFstype := line[fsTypeIndex] - // Check if the current line matches the desired filesystem type and contains the search string. - if fstype == currFstype && strings.Contains(mountpoint, search) { + // fstype field is located right after "-" + // before - there are optional fields, which makes the location of + // the fstype field indeterminate + sepIndex := slices.Index(line, "-") + fsTypeIndex := sepIndex + 1 + + root := line[mountRootIndex] // current search mountpoint root + mountpoint := line[mountpointIndex] // current search mountpoint path + currFstype := line[fsTypeIndex] // current search mountpoint fs type + + // First check for the following 3 conditions: + // 1. The fs type is the one we search for + // 2. The mountpoint contains the path we are searching + // 3. The root path in the mounted filesystem is that of the host. + // This means, that the root of the mounted filesystem is /. + // For example, if we are searching for a mountpoint with cpuset we want + // to be sure that it is not actually /.../.../...cpuset, + // but strictly originating in the root fs. + if fstype == currFstype && strings.Contains(mountpoint, search) && root == "/" { // Try to get the inode number of the current mountpoint. var stat syscall.Stat_t if err := syscall.Stat(mountpoint, &stat); err != nil { @@ -253,9 +265,12 @@ func SearchMountpointFromHost(fstype string, search string) (string, int, error) } currInode := int(stat.Ino) - // Update the result if this is the first match or if the current mountpoint is older or shorter in path length. + // Update the result if either apply: + // 1. this is the first match + // 2. the current mountpoint inode is lower than the currently matching mountpoint + // 2. the current mountpoint shares an inode but its root has a shorter path if inode == 0 || currInode < inode || - (currInode == inode && len(mountpoint) < len(mp)) { + (currInode == inode && len(mp) < len(mountpoint)) { mp = mountpoint inode = currInode }