From 97b5299cd737c624887a39400e8377c8355a2a85 Mon Sep 17 00:00:00 2001 From: Jan Safranek Date: Wed, 23 May 2018 10:17:59 +0200 Subject: [PATCH] Add GetMode to mounter interface. Kubelet must not call os.Lstat on raw volume paths when it runs in a container. Mounter knows where the file really is. --- pkg/kubelet/cm/container_manager_linux_test.go | 4 ++++ pkg/kubelet/kubelet_pods.go | 11 +++++------ pkg/util/mount/exec_mount.go | 4 ++++ pkg/util/mount/exec_mount_test.go | 4 ++++ pkg/util/mount/exec_mount_unsupported.go | 4 ++++ pkg/util/mount/fake.go | 4 ++++ pkg/util/mount/mount.go | 2 ++ pkg/util/mount/mount_linux.go | 13 +++++++++++++ pkg/util/mount/mount_unsupported.go | 4 ++++ pkg/util/mount/mount_windows.go | 8 ++++++++ pkg/util/mount/nsenter_mount.go | 8 ++++++++ pkg/util/mount/nsenter_mount_unsupported.go | 4 ++++ pkg/util/removeall/removeall_test.go | 4 ++++ pkg/volume/host_path/host_path_test.go | 4 ++++ 14 files changed, 72 insertions(+), 6 deletions(-) diff --git a/pkg/kubelet/cm/container_manager_linux_test.go b/pkg/kubelet/cm/container_manager_linux_test.go index cd4b0460c6f..be744604f39 100644 --- a/pkg/kubelet/cm/container_manager_linux_test.go +++ b/pkg/kubelet/cm/container_manager_linux_test.go @@ -120,6 +120,10 @@ func (mi *fakeMountInterface) GetSELinuxSupport(pathname string) (bool, error) { return false, errors.New("not implemented") } +func (mi *fakeMountInterface) GetMode(pathname string) (os.FileMode, error) { + return 0, errors.New("not implemented") +} + func fakeContainerMgrMountInt() mount.Interface { return &fakeMountInterface{ []mount.MountPoint{ diff --git a/pkg/kubelet/kubelet_pods.go b/pkg/kubelet/kubelet_pods.go index 46a17a01a58..a0bd2febf39 100644 --- a/pkg/kubelet/kubelet_pods.go +++ b/pkg/kubelet/kubelet_pods.go @@ -175,12 +175,6 @@ func makeMounts(pod *v1.Pod, podDir string, container *v1.Container, hostName, h return nil, cleanupAction, fmt.Errorf("unable to provision SubPath `%s`: %v", mount.SubPath, err) } - fileinfo, err := os.Lstat(hostPath) - if err != nil { - return nil, cleanupAction, err - } - perm := fileinfo.Mode() - volumePath, err := filepath.EvalSymlinks(hostPath) if err != nil { return nil, cleanupAction, err @@ -195,6 +189,11 @@ func makeMounts(pod *v1.Pod, podDir string, container *v1.Container, hostName, h // when the pod specifies an fsGroup, and if the directory is not created here, Docker will // later auto-create it with the incorrect mode 0750 // Make extra care not to escape the volume! + perm, err := mounter.GetMode(volumePath) + if err != nil { + return nil, cleanupAction, err + } + if err := mounter.SafeMakeDir(hostPath, volumePath, perm); err != nil { glog.Errorf("failed to mkdir %q: %v", hostPath, err) return nil, cleanupAction, err diff --git a/pkg/util/mount/exec_mount.go b/pkg/util/mount/exec_mount.go index fcb948aa34e..1dab57880b0 100644 --- a/pkg/util/mount/exec_mount.go +++ b/pkg/util/mount/exec_mount.go @@ -163,3 +163,7 @@ func (m *execMounter) GetFSGroup(pathname string) (int64, error) { func (m *execMounter) GetSELinuxSupport(pathname string) (bool, error) { return m.wrappedMounter.GetSELinuxSupport(pathname) } + +func (m *execMounter) GetMode(pathname string) (os.FileMode, error) { + return m.wrappedMounter.GetMode(pathname) +} diff --git a/pkg/util/mount/exec_mount_test.go b/pkg/util/mount/exec_mount_test.go index b3af0a46fbb..c48133ba2a2 100644 --- a/pkg/util/mount/exec_mount_test.go +++ b/pkg/util/mount/exec_mount_test.go @@ -176,3 +176,7 @@ func (fm *fakeMounter) GetFSGroup(pathname string) (int64, error) { func (fm *fakeMounter) GetSELinuxSupport(pathname string) (bool, error) { return false, errors.New("not implemented") } + +func (fm *fakeMounter) GetMode(pathname string) (os.FileMode, error) { + return 0, errors.New("not implemented") +} diff --git a/pkg/util/mount/exec_mount_unsupported.go b/pkg/util/mount/exec_mount_unsupported.go index cbb5bbc1591..f7cf757f26e 100644 --- a/pkg/util/mount/exec_mount_unsupported.go +++ b/pkg/util/mount/exec_mount_unsupported.go @@ -110,3 +110,7 @@ func (mounter *execMounter) GetFSGroup(pathname string) (int64, error) { func (mounter *execMounter) GetSELinuxSupport(pathname string) (bool, error) { return false, errors.New("not implemented") } + +func (mounter *execMounter) GetMode(pathname string) (os.FileMode, error) { + return 0, errors.New("not implemented") +} diff --git a/pkg/util/mount/fake.go b/pkg/util/mount/fake.go index f82f669b2eb..be4a033649a 100644 --- a/pkg/util/mount/fake.go +++ b/pkg/util/mount/fake.go @@ -232,3 +232,7 @@ func (f *FakeMounter) GetFSGroup(pathname string) (int64, error) { func (f *FakeMounter) GetSELinuxSupport(pathname string) (bool, error) { return false, errors.New("GetSELinuxSupport not implemented") } + +func (f *FakeMounter) GetMode(pathname string) (os.FileMode, error) { + return 0, errors.New("not implemented") +} diff --git a/pkg/util/mount/mount.go b/pkg/util/mount/mount.go index 0c59ca9ebb7..d1edbfa266a 100644 --- a/pkg/util/mount/mount.go +++ b/pkg/util/mount/mount.go @@ -117,6 +117,8 @@ type Interface interface { // GetSELinuxSupport returns true if given path is on a mount that supports // SELinux. GetSELinuxSupport(pathname string) (bool, error) + // GetMode returns permissions of the path. + GetMode(pathname string) (os.FileMode, error) } type Subpath struct { diff --git a/pkg/util/mount/mount_linux.go b/pkg/util/mount/mount_linux.go index dbb864cd479..466fb9f8e03 100644 --- a/pkg/util/mount/mount_linux.go +++ b/pkg/util/mount/mount_linux.go @@ -982,6 +982,10 @@ func (mounter *Mounter) GetFSGroup(pathname string) (int64, error) { return getFSGroup(realpath) } +func (mounter *Mounter) GetMode(pathname string) (os.FileMode, error) { + return getMode(pathname) +} + // This implementation is shared between Linux and NsEnterMounter func getFSGroup(pathname string) (int64, error) { info, err := os.Stat(pathname) @@ -991,6 +995,15 @@ func getFSGroup(pathname string) (int64, error) { return int64(info.Sys().(*syscall.Stat_t).Gid), nil } +// This implementation is shared between Linux and NsEnterMounter +func getMode(pathname string) (os.FileMode, error) { + info, err := os.Stat(pathname) + if err != nil { + return 0, err + } + return info.Mode(), nil +} + // This implementation is shared between Linux and NsEnterMounter func doSafeMakeDir(pathname string, base string, perm os.FileMode) error { glog.V(4).Infof("Creating directory %q within base %q", pathname, base) diff --git a/pkg/util/mount/mount_unsupported.go b/pkg/util/mount/mount_unsupported.go index 6e268e0f43d..2b7a329340b 100644 --- a/pkg/util/mount/mount_unsupported.go +++ b/pkg/util/mount/mount_unsupported.go @@ -138,3 +138,7 @@ func (mounter *Mounter) GetFSGroup(pathname string) (int64, error) { func (mounter *Mounter) GetSELinuxSupport(pathname string) (bool, error) { return false, errors.New("not implemented") } + +func (mounter *Mounter) GetMode(pathname string) (os.FileMode, error) { + return 0, errors.New("not implemented") +} diff --git a/pkg/util/mount/mount_windows.go b/pkg/util/mount/mount_windows.go index f31f99bd66d..2c87755c9f2 100644 --- a/pkg/util/mount/mount_windows.go +++ b/pkg/util/mount/mount_windows.go @@ -461,6 +461,14 @@ func (mounter *Mounter) GetSELinuxSupport(pathname string) (bool, error) { return false, nil } +func (mounter *Mounter) GetMode(pathname string) (os.FileMode, error) { + info, err := os.Stat(pathname) + if err != nil { + return 0, err + } + return info.Mode(), nil +} + // SafeMakeDir makes sure that the created directory does not escape given base directory mis-using symlinks. func (mounter *Mounter) SafeMakeDir(pathname string, base string, perm os.FileMode) error { return doSafeMakeDir(pathname, base, perm) diff --git a/pkg/util/mount/nsenter_mount.go b/pkg/util/mount/nsenter_mount.go index 4c48d673254..1936d521e78 100644 --- a/pkg/util/mount/nsenter_mount.go +++ b/pkg/util/mount/nsenter_mount.go @@ -347,3 +347,11 @@ func (mounter *NsenterMounter) GetFSGroup(pathname string) (int64, error) { func (mounter *NsenterMounter) GetSELinuxSupport(pathname string) (bool, error) { return getSELinuxSupport(pathname, procMountInfoPath) } + +func (mounter *NsenterMounter) GetMode(pathname string) (os.FileMode, error) { + kubeletpath, err := mounter.ne.KubeletPath(pathname) + if err != nil { + return 0, err + } + return getMode(kubeletpath) +} diff --git a/pkg/util/mount/nsenter_mount_unsupported.go b/pkg/util/mount/nsenter_mount_unsupported.go index 8cf79de472c..007a456d490 100644 --- a/pkg/util/mount/nsenter_mount_unsupported.go +++ b/pkg/util/mount/nsenter_mount_unsupported.go @@ -110,3 +110,7 @@ func (*NsenterMounter) GetFSGroup(pathname string) (int64, error) { func (*NsenterMounter) GetSELinuxSupport(pathname string) (bool, error) { return false, errors.New("not implemented") } + +func (*NsenterMounter) GetMode(pathname string) (os.FileMode, error) { + return 0, errors.New("not implemented") +} diff --git a/pkg/util/removeall/removeall_test.go b/pkg/util/removeall/removeall_test.go index 134326369ff..878db734cdf 100644 --- a/pkg/util/removeall/removeall_test.go +++ b/pkg/util/removeall/removeall_test.go @@ -103,6 +103,10 @@ func (mounter *fakeMounter) GetSELinuxSupport(pathname string) (bool, error) { return false, errors.New("not implemented") } +func (mounter *fakeMounter) GetMode(pathname string) (os.FileMode, error) { + return 0, errors.New("not implemented") +} + func (mounter *fakeMounter) IsLikelyNotMountPoint(file string) (bool, error) { name := path.Base(file) if strings.HasPrefix(name, "mount") { diff --git a/pkg/volume/host_path/host_path_test.go b/pkg/volume/host_path/host_path_test.go index 199880c247e..b8ae4fa9fc0 100644 --- a/pkg/volume/host_path/host_path_test.go +++ b/pkg/volume/host_path/host_path_test.go @@ -401,6 +401,10 @@ func (fftc *fakeFileTypeChecker) GetSELinuxSupport(pathname string) (bool, error return false, errors.New("not implemented") } +func (fftc *fakeFileTypeChecker) GetMode(pathname string) (os.FileMode, error) { + return 0, errors.New("not implemented") +} + func setUp() error { err := os.MkdirAll("/tmp/ExistingFolder", os.FileMode(0755)) if err != nil {