mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 12:15:52 +00:00
Make sure auto-mounted subpath mount source is already mounted
For example, we have two filesystems, one is embedded into another: /a/test # first filesystem with a directory "/a/test/b2" /a/test/b2 # not auto mounted yet second filesystem, notice "/a/test/b2" is # a new directory on this filesystem after this filesystem is mounted For subpath mount "/a/test/b2", `openat("/a/test", "b2")` gets directory "b2" on the first filesystem, then "mount -c" will use this wrong directory as source directory. `fstatat("/a/test", "b2/")` forces triggering auto mount of second filesystem, so `openat("/a/test", "b2")` gets correct source directory for "mount -c". This fixes issue https://github.com/kubernetes/kubernetes/issues/110818#issuecomment-1175736550 References: 1. https://man7.org/linux/man-pages/man2/openat.2.html If pathname refers to an automount point that has not yet been triggered, so no other filesystem is mounted on it, then the call returns a file descriptor referring to the automount directory without triggering a mount. 2. https://man7.org/linux/man-pages/man2/open_by_handle_at.2.html name_to_handle_at() does not trigger a mount when the final component of the pathname is an automount point. When a filesystem supports both file handles and automount points, a name_to_handle_at() call on an automount point will return with error EOVERFLOW without having increased handle_bytes. This can happen since Linux 4.13 with NFS when accessing a directory which is on a separate filesystem on the server. In this case, the automount can be triggered by adding a "/" to the end of the pathname.
This commit is contained in:
parent
29705ce027
commit
834ce75f88
@ -566,18 +566,23 @@ func doSafeOpen(pathname string, base string) (int, error) {
|
||||
// Follow the segments one by one using openat() to make
|
||||
// sure the user cannot change already existing directories into symlinks.
|
||||
for _, seg := range segments {
|
||||
var deviceStat unix.Stat_t
|
||||
|
||||
currentPath = filepath.Join(currentPath, seg)
|
||||
if !mount.PathWithinBase(currentPath, base) {
|
||||
return -1, fmt.Errorf("path %s is outside of allowed base %s", currentPath, base)
|
||||
}
|
||||
|
||||
// Trigger auto mount if it's an auto-mounted directory, ignore error if not a directory.
|
||||
// Notice the trailing slash is mandatory, see "automount" in openat(2) and open_by_handle_at(2).
|
||||
unix.Fstatat(parentFD, seg+"/", &deviceStat, unix.AT_SYMLINK_NOFOLLOW)
|
||||
|
||||
klog.V(5).Infof("Opening path %s", currentPath)
|
||||
childFD, err = syscall.Openat(parentFD, seg, openFDFlags|unix.O_CLOEXEC, 0)
|
||||
if err != nil {
|
||||
return -1, fmt.Errorf("cannot open %s: %s", currentPath, err)
|
||||
}
|
||||
|
||||
var deviceStat unix.Stat_t
|
||||
err := unix.Fstat(childFD, &deviceStat)
|
||||
if err != nil {
|
||||
return -1, fmt.Errorf("error running fstat on %s with %v", currentPath, err)
|
||||
|
Loading…
Reference in New Issue
Block a user