libct: maskPaths: don't rely on ENOTDIR for mount

Currently, we rely on mount returning ENOTDIR when the destination is a
directory (and so mount tells us that the source is not), and fall back
to read-only tmpfs bind mount for such cases.

Theoretically, ENOTDIR can also be returned in some other cases,
resulting in the wrong type of mount being used.

Let's be more straightforward here -- call fstat on destination file
descriptor, and use the proper mount depending on whether it is a
directory.

Reported-by: Rodrigo Campos <rodrigoca@microsoft.com>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This commit is contained in:
Kir Kolyshkin
2025-04-22 18:02:13 -07:00
committed by Aleksa Sarai
parent 7ea4eb02e4
commit faa67dfff6
+17 -11
View File
@@ -1294,19 +1294,25 @@ func maskPaths(paths []string, mountLabel string) error {
}
return fmt.Errorf("can't mask path %q: %w", path, err)
}
dstFd := filepath.Join(procSelfFd, strconv.Itoa(int(dstFh.Fd())))
err = mountViaFds("", devNullSrc, path, dstFd, "", unix.MS_BIND, "")
st, err := dstFh.Stat()
if err != nil {
dstFh.Close()
return fmt.Errorf("can't mask path %q: %w", path, err)
}
var dstType string
if st.IsDir() {
// Destination is a directory: bind mount a ro tmpfs over it.
dstType = "dir"
err = mount("tmpfs", path, "tmpfs", unix.MS_RDONLY, label.FormatMountLabel("", mountLabel))
} else {
// Destination is a file: mount it to /dev/null.
dstType = "path"
dstFd := filepath.Join(procSelfFd, strconv.Itoa(int(dstFh.Fd())))
err = mountViaFds("", devNullSrc, path, dstFd, "", unix.MS_BIND, "")
}
dstFh.Close()
if err != nil {
if !errors.Is(err, unix.ENOTDIR) {
return fmt.Errorf("can't mask path %q: %w", path, err)
}
// Destination is a directory: bind mount a ro tmpfs over it.
err := mount("tmpfs", path, "tmpfs", unix.MS_RDONLY, label.FormatMountLabel("", mountLabel))
if err != nil {
return fmt.Errorf("can't mask dir %q: %w", path, err)
}
return fmt.Errorf("can't mask %s %q: %w", dstType, path, err)
}
}