mirror of https://github.com/k3s-io/k3s
Use O_PATH to avoid errors on Openat
Also add tests for sockets and fifos Replace use of syscall for flags with unixpull/8/head
parent
52ed0368f8
commit
32de642fa1
|
@ -54,7 +54,9 @@ const (
|
||||||
// place for subpath mounts
|
// place for subpath mounts
|
||||||
containerSubPathDirectoryName = "volume-subpaths"
|
containerSubPathDirectoryName = "volume-subpaths"
|
||||||
// syscall.Openat flags used to traverse directories not following symlinks
|
// syscall.Openat flags used to traverse directories not following symlinks
|
||||||
nofollowFlags = syscall.O_RDONLY | syscall.O_NOFOLLOW
|
nofollowFlags = unix.O_RDONLY | unix.O_NOFOLLOW
|
||||||
|
// flags for getting file descriptor without following the symlink
|
||||||
|
openFDFlags = unix.O_NOFOLLOW | unix.O_PATH
|
||||||
)
|
)
|
||||||
|
|
||||||
// Mounter provides the default implementation of mount.Interface
|
// Mounter provides the default implementation of mount.Interface
|
||||||
|
@ -1074,7 +1076,9 @@ func findExistingPrefix(base, pathname string) (string, []string, error) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
for i, dir := range dirs {
|
for i, dir := range dirs {
|
||||||
childFD, err := syscall.Openat(fd, dir, syscall.O_RDONLY, 0)
|
// Using O_PATH here will prevent hangs in case user replaces directory with
|
||||||
|
// fifo
|
||||||
|
childFD, err := syscall.Openat(fd, dir, unix.O_PATH, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return currentPath, dirs[i:], nil
|
return currentPath, dirs[i:], nil
|
||||||
|
@ -1136,11 +1140,21 @@ func doSafeOpen(pathname string, base string) (int, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
glog.V(5).Infof("Opening path %s", currentPath)
|
glog.V(5).Infof("Opening path %s", currentPath)
|
||||||
childFD, err = syscall.Openat(parentFD, seg, nofollowFlags, 0)
|
childFD, err = syscall.Openat(parentFD, seg, openFDFlags, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, fmt.Errorf("cannot open %s: %s", currentPath, err)
|
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)
|
||||||
|
}
|
||||||
|
fileFmt := deviceStat.Mode & syscall.S_IFMT
|
||||||
|
if fileFmt == syscall.S_IFLNK {
|
||||||
|
return -1, fmt.Errorf("Unexpected symlink found %s", currentPath)
|
||||||
|
}
|
||||||
|
|
||||||
// Close parentFD
|
// Close parentFD
|
||||||
if err = syscall.Close(parentFD); err != nil {
|
if err = syscall.Close(parentFD); err != nil {
|
||||||
return -1, fmt.Errorf("closing fd for %q failed: %v", filepath.Dir(currentPath), err)
|
return -1, fmt.Errorf("closing fd for %q failed: %v", filepath.Dir(currentPath), err)
|
||||||
|
|
|
@ -21,6 +21,7 @@ package mount
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
@ -1179,6 +1180,44 @@ func TestBindSubPath(t *testing.T) {
|
||||||
},
|
},
|
||||||
expectError: false,
|
expectError: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "subpath-mounting-unix-socket",
|
||||||
|
prepare: func(base string) ([]string, string, string, error) {
|
||||||
|
volpath, subpathMount := getTestPaths(base)
|
||||||
|
mounts := []string{subpathMount}
|
||||||
|
if err := os.MkdirAll(volpath, defaultPerm); err != nil {
|
||||||
|
return nil, "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.MkdirAll(subpathMount, defaultPerm); err != nil {
|
||||||
|
return nil, "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
testSocketFile := filepath.Join(volpath, "mount_test.sock")
|
||||||
|
_, err := net.Listen("unix", testSocketFile)
|
||||||
|
return mounts, volpath, testSocketFile, err
|
||||||
|
},
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "subpath-mounting-fifo",
|
||||||
|
prepare: func(base string) ([]string, string, string, error) {
|
||||||
|
volpath, subpathMount := getTestPaths(base)
|
||||||
|
mounts := []string{subpathMount}
|
||||||
|
if err := os.MkdirAll(volpath, defaultPerm); err != nil {
|
||||||
|
return nil, "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.MkdirAll(subpathMount, defaultPerm); err != nil {
|
||||||
|
return nil, "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
testFifo := filepath.Join(volpath, "mount_test.fifo")
|
||||||
|
err := syscall.Mkfifo(testFifo, 0)
|
||||||
|
return mounts, volpath, testFifo, err
|
||||||
|
},
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
@ -1308,6 +1347,7 @@ func TestParseMountInfo(t *testing.T) {
|
||||||
|
|
||||||
func TestSafeOpen(t *testing.T) {
|
func TestSafeOpen(t *testing.T) {
|
||||||
defaultPerm := os.FileMode(0750)
|
defaultPerm := os.FileMode(0750)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
// Function that prepares directory structure for the test under given
|
// Function that prepares directory structure for the test under given
|
||||||
|
@ -1435,6 +1475,32 @@ func TestSafeOpen(t *testing.T) {
|
||||||
"test",
|
"test",
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"mounting-unix-socket",
|
||||||
|
func(base string) error {
|
||||||
|
testSocketFile := filepath.Join(base, "mount_test.sock")
|
||||||
|
_, err := net.Listen("unix", testSocketFile)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error preparing socket file %s with %v", testSocketFile, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
"mount_test.sock",
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mounting-unix-socket-in-middle",
|
||||||
|
func(base string) error {
|
||||||
|
testSocketFile := filepath.Join(base, "mount_test.sock")
|
||||||
|
_, err := net.Listen("unix", testSocketFile)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error preparing socket file %s with %v", testSocketFile, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
"mount_test.sock/bar",
|
||||||
|
true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
@ -1551,6 +1617,17 @@ func TestFindExistingPrefix(t *testing.T) {
|
||||||
[]string{"test", "directory"},
|
[]string{"test", "directory"},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"with-fifo-in-middle",
|
||||||
|
func(base string) error {
|
||||||
|
testFifo := filepath.Join(base, "mount_test.fifo")
|
||||||
|
return syscall.Mkfifo(testFifo, 0)
|
||||||
|
},
|
||||||
|
"mount_test.fifo/directory",
|
||||||
|
"",
|
||||||
|
nil,
|
||||||
|
true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
|
Loading…
Reference in New Issue