Index: kubernetes-1.17.17/cmd/kubelet/app/server.go
===================================================================
--- kubernetes-1.17.17.orig/cmd/kubelet/app/server.go
+++ kubernetes-1.17.17/cmd/kubelet/app/server.go
@@ -371,7 +371,8 @@ func UnsecuredDependencies(s *options.Ku
 	}
 
 	mounter := mount.New(s.ExperimentalMounterPath)
-	subpather := subpath.New(mounter)
+	subpatherMounter := subpath.NewMounter(mounter, s.ExperimentalMounterPath)
+	subpather := subpath.New(subpatherMounter)
 	hu := hostutil.NewHostUtil()
 	var pluginRunner = exec.New()
 
Index: kubernetes-1.17.17/pkg/volume/util/subpath/BUILD
===================================================================
--- kubernetes-1.17.17.orig/pkg/volume/util/subpath/BUILD
+++ kubernetes-1.17.17/pkg/volume/util/subpath/BUILD
@@ -4,62 +4,57 @@ go_library(
     name = "go_default_library",
     srcs = [
         "subpath.go",
+        "subpath_fake_mounter.go",
         "subpath_linux.go",
+        "subpath_mount.go",
+        "subpath_mount_linux.go",
+        "subpath_mount_unsupported.go",
+        "subpath_mount_windows.go",
         "subpath_unsupported.go",
         "subpath_windows.go",
     ],
     importpath = "k8s.io/kubernetes/pkg/volume/util/subpath",
     visibility = ["//visibility:public"],
-    deps = select({
+    deps = [
+        "//vendor/k8s.io/utils/mount:go_default_library",
+    ] + select({
         "@io_bazel_rules_go//go/platform:android": [
             "//vendor/golang.org/x/sys/unix:go_default_library",
             "//vendor/k8s.io/klog:go_default_library",
-            "//vendor/k8s.io/utils/mount:go_default_library",
         ],
         "@io_bazel_rules_go//go/platform:darwin": [
-            "//vendor/k8s.io/utils/mount:go_default_library",
             "//vendor/k8s.io/utils/nsenter:go_default_library",
         ],
         "@io_bazel_rules_go//go/platform:dragonfly": [
-            "//vendor/k8s.io/utils/mount:go_default_library",
             "//vendor/k8s.io/utils/nsenter:go_default_library",
         ],
         "@io_bazel_rules_go//go/platform:freebsd": [
-            "//vendor/k8s.io/utils/mount:go_default_library",
             "//vendor/k8s.io/utils/nsenter:go_default_library",
         ],
         "@io_bazel_rules_go//go/platform:ios": [
-            "//vendor/k8s.io/utils/mount:go_default_library",
             "//vendor/k8s.io/utils/nsenter:go_default_library",
         ],
         "@io_bazel_rules_go//go/platform:linux": [
             "//vendor/golang.org/x/sys/unix:go_default_library",
             "//vendor/k8s.io/klog:go_default_library",
-            "//vendor/k8s.io/utils/mount:go_default_library",
         ],
         "@io_bazel_rules_go//go/platform:nacl": [
-            "//vendor/k8s.io/utils/mount:go_default_library",
             "//vendor/k8s.io/utils/nsenter:go_default_library",
         ],
         "@io_bazel_rules_go//go/platform:netbsd": [
-            "//vendor/k8s.io/utils/mount:go_default_library",
             "//vendor/k8s.io/utils/nsenter:go_default_library",
         ],
         "@io_bazel_rules_go//go/platform:openbsd": [
-            "//vendor/k8s.io/utils/mount:go_default_library",
             "//vendor/k8s.io/utils/nsenter:go_default_library",
         ],
         "@io_bazel_rules_go//go/platform:plan9": [
-            "//vendor/k8s.io/utils/mount:go_default_library",
             "//vendor/k8s.io/utils/nsenter:go_default_library",
         ],
         "@io_bazel_rules_go//go/platform:solaris": [
-            "//vendor/k8s.io/utils/mount:go_default_library",
             "//vendor/k8s.io/utils/nsenter:go_default_library",
         ],
         "@io_bazel_rules_go//go/platform:windows": [
             "//vendor/k8s.io/klog:go_default_library",
-            "//vendor/k8s.io/utils/mount:go_default_library",
             "//vendor/k8s.io/utils/nsenter:go_default_library",
         ],
         "//conditions:default": [],
Index: kubernetes-1.17.17/pkg/volume/util/subpath/subpath_fake_mounter.go
===================================================================
--- /dev/null
+++ kubernetes-1.17.17/pkg/volume/util/subpath/subpath_fake_mounter.go
@@ -0,0 +1,47 @@
+/*
+Copyright 2021 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package subpath
+
+import (
+	mountutils "k8s.io/utils/mount"
+)
+
+// FakeMounter implements MountInterface for tests.
+type FakeMounter struct {
+	*mountutils.FakeMounter
+}
+
+var _ MountInterface = &FakeMounter{}
+
+// NewFakeMounter returns a FakeMounter struct that implements Interface and is
+// suitable for testing purposes.
+func NewFakeMounter(mps []mountutils.MountPoint) *FakeMounter {
+	return &FakeMounter{
+		FakeMounter: &mountutils.FakeMounter{
+			MountPoints: mps,
+		},
+	}
+}
+
+// MountSensitiveWithFlags records the mount event and updates the in-memory mount points for FakeMounter
+// sensitiveOptions to be passed in a separate parameter from the normal
+// mount options and ensures the sensitiveOptions are never logged. This
+// method should be used by callers that pass sensitive material (like
+// passwords) as mount options.
+func (f *FakeMounter) MountSensitiveWithFlags(source string, target string, fstype string, options []string, sensitiveOptions []string, mountFlags []string) error {
+	return f.MountSensitive(source, target, fstype, options, sensitiveOptions)
+}
Index: kubernetes-1.17.17/pkg/volume/util/subpath/subpath_linux.go
===================================================================
--- kubernetes-1.17.17.orig/pkg/volume/util/subpath/subpath_linux.go
+++ kubernetes-1.17.17/pkg/volume/util/subpath/subpath_linux.go
@@ -43,11 +43,11 @@ const (
 )
 
 type subpath struct {
-	mounter mount.Interface
+	mounter MountInterface
 }
 
 // New returns a subpath.Interface for the current system
-func New(mounter mount.Interface) Interface {
+func New(mounter MountInterface) Interface {
 	return &subpath{
 		mounter: mounter,
 	}
@@ -147,7 +147,7 @@ func getSubpathBindTarget(subpath Subpat
 	return filepath.Join(subpath.PodDir, containerSubPathDirectoryName, subpath.VolumeName, subpath.ContainerName, strconv.Itoa(subpath.VolumeMountIndex))
 }
 
-func doBindSubPath(mounter mount.Interface, subpath Subpath) (hostPath string, err error) {
+func doBindSubPath(mounter MountInterface, subpath Subpath) (hostPath string, err error) {
 	// Linux, kubelet runs on the host:
 	// - safely open the subpath
 	// - bind-mount /proc/<pid of kubelet>/fd/<fd> to subpath target
@@ -196,8 +196,9 @@ func doBindSubPath(mounter mount.Interfa
 
 	// Do the bind mount
 	options := []string{"bind"}
+	mountFlags := []string{"--no-canonicalize"}
 	klog.V(5).Infof("bind mounting %q at %q", mountSource, bindPathTarget)
-	if err = mounter.Mount(mountSource, bindPathTarget, "" /*fstype*/, options); err != nil {
+	if err = mounter.MountSensitiveWithFlags(mountSource, bindPathTarget, "" /*fstype*/, options, nil /* sensitiveOptions */, mountFlags); err != nil {
 		return "", fmt.Errorf("error mounting %s: %s", subpath.Path, err)
 	}
 	success = true
Index: kubernetes-1.17.17/pkg/volume/util/subpath/subpath_linux_test.go
===================================================================
--- kubernetes-1.17.17.orig/pkg/volume/util/subpath/subpath_linux_test.go
+++ kubernetes-1.17.17/pkg/volume/util/subpath/subpath_linux_test.go
@@ -611,7 +611,7 @@ func TestCleanSubPaths(t *testing.T) {
 			t.Fatalf("failed to prepare test %q: %v", test.name, err.Error())
 		}
 
-		fm := mount.NewFakeMounter(mounts)
+		fm := NewFakeMounter(mounts)
 		fm.UnmountFunc = test.unmount
 
 		err = doCleanSubPaths(fm, base, testVol)
@@ -636,12 +636,12 @@ var (
 	testSubpath   = 1
 )
 
-func setupFakeMounter(testMounts []string) *mount.FakeMounter {
+func setupFakeMounter(testMounts []string) *FakeMounter {
 	mounts := []mount.MountPoint{}
 	for _, mountPoint := range testMounts {
 		mounts = append(mounts, mount.MountPoint{Device: "/foo", Path: mountPoint})
 	}
-	return mount.NewFakeMounter(mounts)
+	return NewFakeMounter(mounts)
 }
 
 func getTestPaths(base string) (string, string) {
Index: kubernetes-1.17.17/pkg/volume/util/subpath/subpath_mount.go
===================================================================
--- /dev/null
+++ kubernetes-1.17.17/pkg/volume/util/subpath/subpath_mount.go
@@ -0,0 +1,36 @@
+/*
+Copyright 2021 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// TODO(thockin): This whole pkg is pretty linux-centric.  As soon as we have
+// an alternate platform, we will need to abstract further.
+
+package subpath
+
+import (
+	"k8s.io/utils/mount"
+)
+
+// MountInterface defines the set of methods to allow for mount operations on a system.
+type MountInterface interface {
+	mount.Interface
+
+	// MountSensitiveWithFlags is the same as MountSensitive() with additional mount flags
+	MountSensitiveWithFlags(source string, target string, fstype string, options []string, sensitiveOptions []string, mountFlags []string) error
+}
+
+// Compile-time check to ensure all Mounter implementations satisfy
+// the mount interface.
+var _ MountInterface = &Mounter{}
Index: kubernetes-1.17.17/pkg/volume/util/subpath/subpath_mount_linux.go
===================================================================
--- /dev/null
+++ kubernetes-1.17.17/pkg/volume/util/subpath/subpath_mount_linux.go
@@ -0,0 +1,216 @@
+// +build linux
+
+/*
+Copyright 2021 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package subpath
+
+import (
+	"fmt"
+	"os/exec"
+	"strings"
+
+	"k8s.io/klog"
+	mountutils "k8s.io/utils/mount"
+)
+
+const (
+	// Default mount command if mounter path is not specified.
+	defaultMountCommand = "mount"
+	// Log message where sensitive mount options were removed
+	sensitiveOptionsRemoved = "<masked>"
+)
+
+// Mounter provides the subpath implementation of mount.Interface
+// for the linux platform.  This implementation assumes that the
+// kubelet is running in the host's root mount namespace.
+type Mounter struct {
+	mountutils.Interface
+	mounterPath string
+	withSystemd bool
+}
+
+// NewMounter returns a MountInterface for the current system.
+// It provides options to override the default mounter behavior.
+// mounterPath allows using an alternative to `/bin/mount` for mounting.
+func NewMounter(mounter mountutils.Interface, mounterPath string) MountInterface {
+	return &Mounter{
+		Interface:   mounter,
+		mounterPath: mounterPath,
+		withSystemd: detectSystemd(),
+	}
+}
+
+// MountSensitiveWithFlags is the same as MountSensitive() with additional mount flags
+func (mounter *Mounter) MountSensitiveWithFlags(source string, target string, fstype string, options []string, sensitiveOptions []string, mountFlags []string) error {
+	// Path to mounter binary if containerized mounter is needed. Otherwise, it is set to empty.
+	// All Linux distros are expected to be shipped with a mount utility that a support bind mounts.
+	mounterPath := ""
+	bind, bindOpts, bindRemountOpts, bindRemountOptsSensitive := mountutils.MakeBindOptsSensitive(options, sensitiveOptions)
+	if bind {
+		err := mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindOpts, bindRemountOptsSensitive, mountFlags)
+		if err != nil {
+			return err
+		}
+		return mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindRemountOpts, bindRemountOptsSensitive, mountFlags)
+	}
+	// The list of filesystems that require containerized mounter on GCI image cluster
+	fsTypesNeedMounter := map[string]struct{}{
+		"nfs":       {},
+		"glusterfs": {},
+		"ceph":      {},
+		"cifs":      {},
+	}
+	if _, ok := fsTypesNeedMounter[fstype]; ok {
+		mounterPath = mounter.mounterPath
+	}
+	return mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, options, sensitiveOptions, mountFlags)
+}
+
+// doMount runs the mount command. mounterPath is the path to mounter binary if containerized mounter is used.
+// sensitiveOptions is an extension of options except they will not be logged (because they may contain sensitive material)
+// mountFlags are additional flags used in the mount command that are not related with fstype and mount options
+func (mounter *Mounter) doMount(mounterPath string, mountCmd string, source string, target string, fstype string, options []string, sensitiveOptions []string, mountFlags []string) error {
+	mountArgs, mountArgsLogStr := makeMountArgsSensitiveWithMountFlags(source, target, fstype, options, sensitiveOptions, mountFlags)
+	if len(mounterPath) > 0 {
+		mountArgs = append([]string{mountCmd}, mountArgs...)
+		mountArgsLogStr = mountCmd + " " + mountArgsLogStr
+		mountCmd = mounterPath
+	}
+
+	if mounter.withSystemd {
+		// Try to run mount via systemd-run --scope. This will escape the
+		// service where kubelet runs and any fuse daemons will be started in a
+		// specific scope. kubelet service than can be restarted without killing
+		// these fuse daemons.
+		//
+		// Complete command line (when mounterPath is not used):
+		// systemd-run --description=... --scope -- mount -t <type> <what> <where>
+		//
+		// Expected flow:
+		// * systemd-run creates a transient scope (=~ cgroup) and executes its
+		//   argument (/bin/mount) there.
+		// * mount does its job, forks a fuse daemon if necessary and finishes.
+		//   (systemd-run --scope finishes at this point, returning mount's exit
+		//   code and stdout/stderr - thats one of --scope benefits).
+		// * systemd keeps the fuse daemon running in the scope (i.e. in its own
+		//   cgroup) until the fuse daemon dies (another --scope benefit).
+		//   Kubelet service can be restarted and the fuse daemon survives.
+		// * When the fuse daemon dies (e.g. during unmount) systemd removes the
+		//   scope automatically.
+		//
+		// systemd-mount is not used because it's too new for older distros
+		// (CentOS 7, Debian Jessie).
+		mountCmd, mountArgs, mountArgsLogStr = mountutils.AddSystemdScopeSensitive("systemd-run", target, mountCmd, mountArgs, mountArgsLogStr)
+		// } else {
+		// No systemd-run on the host (or we failed to check it), assume kubelet
+		// does not run as a systemd service.
+		// No code here, mountCmd and mountArgs are already populated.
+	}
+
+	// Logging with sensitive mount options removed.
+	klog.V(4).Infof("Mounting cmd (%s) with arguments (%s)", mountCmd, mountArgsLogStr)
+	command := exec.Command(mountCmd, mountArgs...)
+	output, err := command.CombinedOutput()
+	if err != nil {
+		klog.Errorf("Mount failed: %v\nMounting command: %s\nMounting arguments: %s\nOutput: %s\n", err, mountCmd, mountArgsLogStr, string(output))
+		return fmt.Errorf("mount failed: %v\nMounting command: %s\nMounting arguments: %s\nOutput: %s",
+			err, mountCmd, mountArgsLogStr, string(output))
+	}
+	return err
+}
+
+// detectSystemd returns true if OS runs with systemd as init. When not sure
+// (permission errors, ...), it returns false.
+// There may be different ways how to detect systemd, this one makes sure that
+// systemd-runs (needed by Mount()) works.
+func detectSystemd() bool {
+	if _, err := exec.LookPath("systemd-run"); err != nil {
+		klog.V(2).Infof("Detected OS without systemd")
+		return false
+	}
+	// Try to run systemd-run --scope /bin/true, that should be enough
+	// to make sure that systemd is really running and not just installed,
+	// which happens when running in a container with a systemd-based image
+	// but with different pid 1.
+	cmd := exec.Command("systemd-run", "--description=Kubernetes systemd probe", "--scope", "true")
+	output, err := cmd.CombinedOutput()
+	if err != nil {
+		klog.V(2).Infof("Cannot run systemd-run, assuming non-systemd OS")
+		klog.V(4).Infof("systemd-run failed with: %v", err)
+		klog.V(4).Infof("systemd-run output: %s", string(output))
+		return false
+	}
+	klog.V(2).Infof("Detected OS with systemd")
+	return true
+}
+
+// makeMountArgsSensitiveWithMountFlags makes the arguments to the mount(8) command.
+// sensitiveOptions is an extension of options except they will not be logged (because they may contain sensitive material)
+// mountFlags are additional mount flags that are not related with the fstype and mount options
+func makeMountArgsSensitiveWithMountFlags(source, target, fstype string, options []string, sensitiveOptions []string, mountFlags []string) (mountArgs []string, mountArgsLogStr string) {
+	// Build mount command as follows:
+	//   mount [$mountFlags] [-t $fstype] [-o $options] [$source] $target
+	mountArgs = []string{}
+	mountArgsLogStr = ""
+
+	mountArgs = append(mountArgs, mountFlags...)
+	mountArgsLogStr += strings.Join(mountFlags, " ")
+
+	if len(fstype) > 0 {
+		mountArgs = append(mountArgs, "-t", fstype)
+		mountArgsLogStr += strings.Join(mountArgs, " ")
+	}
+	if len(options) > 0 || len(sensitiveOptions) > 0 {
+		combinedOptions := []string{}
+		combinedOptions = append(combinedOptions, options...)
+		combinedOptions = append(combinedOptions, sensitiveOptions...)
+		mountArgs = append(mountArgs, "-o", strings.Join(combinedOptions, ","))
+		// exclude sensitiveOptions from log string
+		mountArgsLogStr += " -o " + sanitizedOptionsForLogging(options, sensitiveOptions)
+	}
+	if len(source) > 0 {
+		mountArgs = append(mountArgs, source)
+		mountArgsLogStr += " " + source
+	}
+	mountArgs = append(mountArgs, target)
+	mountArgsLogStr += " " + target
+
+	return mountArgs, mountArgsLogStr
+}
+
+// sanitizedOptionsForLogging will return a comma separated string containing
+// options and sensitiveOptions. Each entry in sensitiveOptions will be
+// replaced with the string sensitiveOptionsRemoved
+// e.g. o1,o2,<masked>,<masked>
+func sanitizedOptionsForLogging(options []string, sensitiveOptions []string) string {
+	separator := ""
+	if len(options) > 0 && len(sensitiveOptions) > 0 {
+		separator = ","
+	}
+
+	sensitiveOptionsStart := ""
+	sensitiveOptionsEnd := ""
+	if len(sensitiveOptions) > 0 {
+		sensitiveOptionsStart = strings.Repeat(sensitiveOptionsRemoved+",", len(sensitiveOptions)-1)
+		sensitiveOptionsEnd = sensitiveOptionsRemoved
+	}
+
+	return strings.Join(options, ",") +
+		separator +
+		sensitiveOptionsStart +
+		sensitiveOptionsEnd
+}
Index: kubernetes-1.17.17/pkg/volume/util/subpath/subpath_mount_unsupported.go
===================================================================
--- /dev/null
+++ kubernetes-1.17.17/pkg/volume/util/subpath/subpath_mount_unsupported.go
@@ -0,0 +1,48 @@
+// +build !linux,!windows
+
+/*
+Copyright 2021 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package subpath
+
+import (
+	"errors"
+
+	"k8s.io/utils/mount"
+)
+
+// Mounter implements mount.Interface for unsupported platforms
+type Mounter struct {
+	mount.Interface
+	mounterPath string
+}
+
+var errUtilsMountUnsupported = errors.New("utils/mount on this platform is not supported")
+
+// NewMounter returns a MountInterface for the current system.
+// It provides options to override the default mounter behavior.
+// mounterPath allows using an alternative to `/bin/mount` for mounting.
+func NewMounter(mounter mount.Interface, mounterPath string) MountInterface {
+	return &Mounter{
+		Interface:   mounter,
+		mounterPath: mounterPath,
+	}
+}
+
+// MountSensitiveWithFlags is the same as MountSensitive() with additional mount flags
+func (mounter *Mounter) MountSensitiveWithFlags(source string, target string, fstype string, options []string, sensitiveOptions []string, mountFlags []string) error {
+	return errUtilsMountUnsupported
+}
Index: kubernetes-1.17.17/pkg/volume/util/subpath/subpath_mount_windows.go
===================================================================
--- /dev/null
+++ kubernetes-1.17.17/pkg/volume/util/subpath/subpath_mount_windows.go
@@ -0,0 +1,47 @@
+// +build windows
+
+/*
+Copyright 2021 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package subpath
+
+import (
+	"k8s.io/utils/mount"
+)
+
+// Mounter provides the subpath implementation of mount.Interface
+// for the windows platform.  This implementation assumes that the
+// kubelet is running in the host's root mount namespace.
+type Mounter struct {
+	mount.Interface
+	mounterPath string
+}
+
+// NewMounter returns a MountInterface for the current system.
+// It provides options to override the default mounter behavior.
+// mounterPath allows using an alternative to `/bin/mount` for mounting.
+func NewMounter(mounter mount.Interface, mounterPath string) MountInterface {
+	return &Mounter{
+		Interface:   mounter,
+		mounterPath: mounterPath,
+	}
+}
+
+// MountSensitiveWithFlags is the same as MountSensitive() with additional mount flags but
+// because mountFlags are linux mount(8) flags this method is the same as MountSensitive() in Windows
+func (mounter *Mounter) MountSensitiveWithFlags(source string, target string, fstype string, options []string, sensitiveOptions []string, mountFlags []string) error {
+	return mounter.MountSensitive(source, target, fstype, options, sensitiveOptions)
+}
Index: kubernetes-1.17.17/vendor/k8s.io/utils/mount/OWNERS
===================================================================
--- kubernetes-1.17.17.orig/vendor/k8s.io/utils/mount/OWNERS
+++ kubernetes-1.17.17/vendor/k8s.io/utils/mount/OWNERS
@@ -6,6 +6,7 @@ reviewers:
   - jsafrane
   - msau42
   - andyzhangx
+  - gnufied
 approvers:
   - jingxu97
   - saad-ali
Index: kubernetes-1.17.17/vendor/k8s.io/utils/mount/fake_mounter.go
===================================================================
--- kubernetes-1.17.17.orig/vendor/k8s.io/utils/mount/fake_mounter.go
+++ kubernetes-1.17.17/vendor/k8s.io/utils/mount/fake_mounter.go
@@ -82,6 +82,15 @@ func (f *FakeMounter) GetLog() []FakeAct
 
 // Mount records the mount event and updates the in-memory mount points for FakeMounter
 func (f *FakeMounter) Mount(source string, target string, fstype string, options []string) error {
+	return f.MountSensitive(source, target, fstype, options, nil /* sensitiveOptions */)
+}
+
+// Mount records the mount event and updates the in-memory mount points for FakeMounter
+// sensitiveOptions to be passed in a separate parameter from the normal
+// mount options and ensures the sensitiveOptions are never logged. This
+// method should be used by callers that pass sensitive material (like
+// passwords) as mount options.
+func (f *FakeMounter) MountSensitive(source string, target string, fstype string, options []string, sensitiveOptions []string) error {
 	f.mutex.Lock()
 	defer f.mutex.Unlock()
 
@@ -117,7 +126,7 @@ func (f *FakeMounter) Mount(source strin
 	if err != nil {
 		absTarget = target
 	}
-	f.MountPoints = append(f.MountPoints, MountPoint{Device: source, Path: absTarget, Type: fstype, Opts: opts})
+	f.MountPoints = append(f.MountPoints, MountPoint{Device: source, Path: absTarget, Type: fstype, Opts: append(opts, sensitiveOptions...)})
 	klog.V(5).Infof("Fake mounter: mounted %s to %s", source, absTarget)
 	f.log = append(f.log, FakeAction{Action: FakeActionMount, Target: absTarget, Source: source, FSType: fstype})
 	return nil
Index: kubernetes-1.17.17/vendor/k8s.io/utils/mount/mount.go
===================================================================
--- kubernetes-1.17.17.orig/vendor/k8s.io/utils/mount/mount.go
+++ kubernetes-1.17.17/vendor/k8s.io/utils/mount/mount.go
@@ -20,6 +20,7 @@ limitations under the License.
 package mount
 
 import (
+	"fmt"
 	"os"
 	"path/filepath"
 	"strings"
@@ -30,12 +31,21 @@ import (
 const (
 	// Default mount command if mounter path is not specified.
 	defaultMountCommand = "mount"
+	// Log message where sensitive mount options were removed
+	sensitiveOptionsRemoved = "<masked>"
 )
 
 // Interface defines the set of methods to allow for mount operations on a system.
 type Interface interface {
 	// Mount mounts source to target as fstype with given options.
+	// options MUST not contain sensitive material (like passwords).
 	Mount(source string, target string, fstype string, options []string) error
+	// MountSensitive is the same as Mount() but this method allows
+	// sensitiveOptions to be passed in a separate parameter from the normal
+	// mount options and ensures the sensitiveOptions are never logged. This
+	// method should be used by callers that pass sensitive material (like
+	// passwords) as mount options.
+	MountSensitive(source string, target string, fstype string, options []string, sensitiveOptions []string) error
 	// Unmount unmounts given target.
 	Unmount(target string) error
 	// List returns a list of all mounted filesystems.  This can be large.
@@ -71,11 +81,43 @@ type MountPoint struct {
 	Device string
 	Path   string
 	Type   string
-	Opts   []string
+	Opts   []string // Opts may contain sensitive mount options (like passwords) and MUST be treated as such (e.g. not logged).
 	Freq   int
 	Pass   int
 }
 
+type MountErrorType string
+
+const (
+	FilesystemMismatch  MountErrorType = "FilesystemMismatch"
+	HasFilesystemErrors MountErrorType = "HasFilesystemErrors"
+	UnformattedReadOnly MountErrorType = "UnformattedReadOnly"
+	FormatFailed        MountErrorType = "FormatFailed"
+	GetDiskFormatFailed MountErrorType = "GetDiskFormatFailed"
+	UnknownMountError   MountErrorType = "UnknownMountError"
+)
+
+type MountError struct {
+	Type    MountErrorType
+	Message string
+}
+
+func (mountError MountError) String() string {
+	return mountError.Message
+}
+
+func (mountError MountError) Error() string {
+	return mountError.Message
+}
+
+func NewMountError(mountErrorValue MountErrorType, format string, args ...interface{}) error {
+	mountError := MountError{
+		Type:    mountErrorValue,
+		Message: fmt.Sprintf(format, args...),
+	}
+	return mountError
+}
+
 // SafeFormatAndMount probes a device to see if it is formatted.
 // Namely it checks to see if a file system is present. If so it
 // mounts it otherwise the device is formatted first then mounted.
@@ -89,8 +131,18 @@ type SafeFormatAndMount struct {
 // read-only it will format it first then mount it. Otherwise, if the
 // disk is already formatted or it is being mounted as read-only, it
 // will be mounted without formatting.
+// options MUST not contain sensitive material (like passwords).
 func (mounter *SafeFormatAndMount) FormatAndMount(source string, target string, fstype string, options []string) error {
-	return mounter.formatAndMount(source, target, fstype, options)
+	return mounter.FormatAndMountSensitive(source, target, fstype, options, nil /* sensitiveOptions */)
+}
+
+// FormatAndMountSensitive is the same as FormatAndMount but this method allows
+// sensitiveOptions to be passed in a separate parameter from the normal mount
+// options and ensures the sensitiveOptions are never logged. This method should
+// be used by callers that pass sensitive material (like passwords) as mount
+// options.
+func (mounter *SafeFormatAndMount) FormatAndMountSensitive(source string, target string, fstype string, options []string, sensitiveOptions []string) error {
+	return mounter.formatAndMountSensitive(source, target, fstype, options, sensitiveOptions)
 }
 
 // getMountRefsByDev finds all references to the device provided
@@ -207,6 +259,16 @@ func IsNotMountPoint(mounter Interface,
 // The list equals:
 //   options - 'bind' + 'remount' (no duplicate)
 func MakeBindOpts(options []string) (bool, []string, []string) {
+	bind, bindOpts, bindRemountOpts, _ := MakeBindOptsSensitive(options, nil /* sensitiveOptions */)
+	return bind, bindOpts, bindRemountOpts
+}
+
+// MakeBindOptsSensitive is the same as MakeBindOpts but this method allows
+// sensitiveOptions to be passed in a separate parameter from the normal mount
+// options and ensures the sensitiveOptions are never logged. This method should
+// be used by callers that pass sensitive material (like passwords) as mount
+// options.
+func MakeBindOptsSensitive(options []string, sensitiveOptions []string) (bool, []string, []string, []string) {
 	// Because we have an FD opened on the subpath bind mount, the "bind" option
 	// needs to be included, otherwise the mount target will error as busy if you
 	// remount as readonly.
@@ -214,12 +276,13 @@ func MakeBindOpts(options []string) (boo
 	// As a consequence, all read only bind mounts will no longer change the underlying
 	// volume mount to be read only.
 	bindRemountOpts := []string{"bind", "remount"}
+	bindRemountSensitiveOpts := []string{}
 	bind := false
 	bindOpts := []string{"bind"}
 
 	// _netdev is a userspace mount option and does not automatically get added when
 	// bind mount is created and hence we must carry it over.
-	if checkForNetDev(options) {
+	if checkForNetDev(options, sensitiveOptions) {
 		bindOpts = append(bindOpts, "_netdev")
 	}
 
@@ -235,15 +298,32 @@ func MakeBindOpts(options []string) (boo
 		}
 	}
 
-	return bind, bindOpts, bindRemountOpts
+	for _, sensitiveOption := range sensitiveOptions {
+		switch sensitiveOption {
+		case "bind":
+			bind = true
+			break
+		case "remount":
+			break
+		default:
+			bindRemountSensitiveOpts = append(bindRemountSensitiveOpts, sensitiveOption)
+		}
+	}
+
+	return bind, bindOpts, bindRemountOpts, bindRemountSensitiveOpts
 }
 
-func checkForNetDev(options []string) bool {
+func checkForNetDev(options []string, sensitiveOptions []string) bool {
 	for _, option := range options {
 		if option == "_netdev" {
 			return true
 		}
 	}
+	for _, sensitiveOption := range sensitiveOptions {
+		if sensitiveOption == "_netdev" {
+			return true
+		}
+	}
 	return false
 }
 
@@ -265,3 +345,26 @@ func StartsWithBackstep(rel string) bool
 	// normalize to / and check for ../
 	return rel == ".." || strings.HasPrefix(filepath.ToSlash(rel), "../")
 }
+
+// sanitizedOptionsForLogging will return a comma seperated string containing
+// options and sensitiveOptions. Each entry in sensitiveOptions will be
+// replaced with the string sensitiveOptionsRemoved
+// e.g. o1,o2,<masked>,<masked>
+func sanitizedOptionsForLogging(options []string, sensitiveOptions []string) string {
+	seperator := ""
+	if len(options) > 0 && len(sensitiveOptions) > 0 {
+		seperator = ","
+	}
+
+	sensitiveOptionsStart := ""
+	sensitiveOptionsEnd := ""
+	if len(sensitiveOptions) > 0 {
+		sensitiveOptionsStart = strings.Repeat(sensitiveOptionsRemoved+",", len(sensitiveOptions)-1)
+		sensitiveOptionsEnd = sensitiveOptionsRemoved
+	}
+
+	return strings.Join(options, ",") +
+		seperator +
+		sensitiveOptionsStart +
+		sensitiveOptionsEnd
+}
Index: kubernetes-1.17.17/vendor/k8s.io/utils/mount/mount_helper_common.go
===================================================================
--- kubernetes-1.17.17.orig/vendor/k8s.io/utils/mount/mount_helper_common.go
+++ kubernetes-1.17.17/vendor/k8s.io/utils/mount/mount_helper_common.go
@@ -48,9 +48,9 @@ func CleanupMountPoint(mountPath string,
 // if corruptedMnt is true, it means that the mountPath is a corrupted mountpoint, and the mount point check
 // will be skipped
 func doCleanupMountPoint(mountPath string, mounter Interface, extensiveMountPointCheck bool, corruptedMnt bool) error {
+	var notMnt bool
+	var err error
 	if !corruptedMnt {
-		var notMnt bool
-		var err error
 		if extensiveMountPointCheck {
 			notMnt, err = IsNotMountPoint(mounter, mountPath)
 		} else {
@@ -73,9 +73,13 @@ func doCleanupMountPoint(mountPath strin
 		return err
 	}
 
-	notMnt, mntErr := mounter.IsLikelyNotMountPoint(mountPath)
-	if mntErr != nil {
-		return mntErr
+	if extensiveMountPointCheck {
+		notMnt, err = IsNotMountPoint(mounter, mountPath)
+	} else {
+		notMnt, err = mounter.IsLikelyNotMountPoint(mountPath)
+	}
+	if err != nil {
+		return err
 	}
 	if notMnt {
 		klog.V(4).Infof("%q is unmounted, deleting the directory", mountPath)
Index: kubernetes-1.17.17/vendor/k8s.io/utils/mount/mount_helper_unix.go
===================================================================
--- kubernetes-1.17.17.orig/vendor/k8s.io/utils/mount/mount_helper_unix.go
+++ kubernetes-1.17.17/vendor/k8s.io/utils/mount/mount_helper_unix.go
@@ -61,8 +61,12 @@ type MountInfo struct {
 	ID int
 	// The ID of the parent mount (or of self for the root of this mount namespace's mount tree).
 	ParentID int
-	// The value of `st_dev` for files on this filesystem.
-	MajorMinor string
+	// Major indicates one half of the device ID which identifies the device class
+	// (parsed from `st_dev` for files on this filesystem).
+	Major int
+	// Minor indicates one half of the device ID which identifies a specific
+	// instance of device (parsed from `st_dev` for files on this filesystem).
+	Minor int
 	// The pathname of the directory in the filesystem which forms the root of this mount.
 	Root string
 	// Mount source, filesystem-specific information. e.g. device, tmpfs name.
@@ -106,10 +110,24 @@ func ParseMountInfo(filename string) ([]
 		if err != nil {
 			return nil, err
 		}
+		mm := strings.Split(fields[2], ":")
+		if len(mm) != 2 {
+			return nil, fmt.Errorf("parsing '%s' failed: unexpected minor:major pair %s", line, mm)
+		}
+		major, err := strconv.Atoi(mm[0])
+		if err != nil {
+			return nil, fmt.Errorf("parsing '%s' failed: unable to parse major device id, err:%v", mm[0], err)
+		}
+		minor, err := strconv.Atoi(mm[1])
+		if err != nil {
+			return nil, fmt.Errorf("parsing '%s' failed: unable to parse minor device id, err:%v", mm[1], err)
+		}
+
 		info := MountInfo{
 			ID:           id,
 			ParentID:     parentID,
-			MajorMinor:   fields[2],
+			Major:        major,
+			Minor:        minor,
 			Root:         fields[3],
 			MountPoint:   fields[4],
 			MountOptions: strings.Split(fields[5], ","),
Index: kubernetes-1.17.17/vendor/k8s.io/utils/mount/mount_linux.go
===================================================================
--- kubernetes-1.17.17.orig/vendor/k8s.io/utils/mount/mount_linux.go
+++ kubernetes-1.17.17/vendor/k8s.io/utils/mount/mount_linux.go
@@ -19,7 +19,6 @@ limitations under the License.
 package mount
 
 import (
-	"errors"
 	"fmt"
 	"os"
 	"os/exec"
@@ -70,16 +69,25 @@ func New(mounterPath string) Interface {
 // currently come from mount(8), e.g. "ro", "remount", "bind", etc. If no more option is
 // required, call Mount with an empty string list or nil.
 func (mounter *Mounter) Mount(source string, target string, fstype string, options []string) error {
+	return mounter.MountSensitive(source, target, fstype, options, nil)
+}
+
+// MountSensitive is the same as Mount() but this method allows
+// sensitiveOptions to be passed in a separate parameter from the normal
+// mount options and ensures the sensitiveOptions are never logged. This
+// method should be used by callers that pass sensitive material (like
+// passwords) as mount options.
+func (mounter *Mounter) MountSensitive(source string, target string, fstype string, options []string, sensitiveOptions []string) error {
 	// Path to mounter binary if containerized mounter is needed. Otherwise, it is set to empty.
 	// All Linux distros are expected to be shipped with a mount utility that a support bind mounts.
 	mounterPath := ""
-	bind, bindOpts, bindRemountOpts := MakeBindOpts(options)
+	bind, bindOpts, bindRemountOpts, bindRemountOptsSensitive := MakeBindOptsSensitive(options, sensitiveOptions)
 	if bind {
-		err := mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindOpts)
+		err := mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindOpts, bindRemountOptsSensitive)
 		if err != nil {
 			return err
 		}
-		return mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindRemountOpts)
+		return mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindRemountOpts, bindRemountOptsSensitive)
 	}
 	// The list of filesystems that require containerized mounter on GCI image cluster
 	fsTypesNeedMounter := map[string]struct{}{
@@ -91,14 +99,16 @@ func (mounter *Mounter) Mount(source str
 	if _, ok := fsTypesNeedMounter[fstype]; ok {
 		mounterPath = mounter.mounterPath
 	}
-	return mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, options)
+	return mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, options, sensitiveOptions)
 }
 
 // doMount runs the mount command. mounterPath is the path to mounter binary if containerized mounter is used.
-func (mounter *Mounter) doMount(mounterPath string, mountCmd string, source string, target string, fstype string, options []string) error {
-	mountArgs := MakeMountArgs(source, target, fstype, options)
+// sensitiveOptions is an extention of options except they will not be logged (because they may contain sensitive material)
+func (mounter *Mounter) doMount(mounterPath string, mountCmd string, source string, target string, fstype string, options []string, sensitiveOptions []string) error {
+	mountArgs, mountArgsLogStr := MakeMountArgsSensitive(source, target, fstype, options, sensitiveOptions)
 	if len(mounterPath) > 0 {
 		mountArgs = append([]string{mountCmd}, mountArgs...)
+		mountArgsLogStr = mountCmd + " " + mountArgsLogStr
 		mountCmd = mounterPath
 	}
 
@@ -125,21 +135,21 @@ func (mounter *Mounter) doMount(mounterP
 		//
 		// systemd-mount is not used because it's too new for older distros
 		// (CentOS 7, Debian Jessie).
-		mountCmd, mountArgs = AddSystemdScope("systemd-run", target, mountCmd, mountArgs)
+		mountCmd, mountArgs, mountArgsLogStr = AddSystemdScopeSensitive("systemd-run", target, mountCmd, mountArgs, mountArgsLogStr)
 	} else {
 		// No systemd-run on the host (or we failed to check it), assume kubelet
 		// does not run as a systemd service.
 		// No code here, mountCmd and mountArgs are already populated.
 	}
 
-	klog.V(4).Infof("Mounting cmd (%s) with arguments (%s)", mountCmd, mountArgs)
+	// Logging with sensitive mount options removed.
+	klog.V(4).Infof("Mounting cmd (%s) with arguments (%s)", mountCmd, mountArgsLogStr)
 	command := exec.Command(mountCmd, mountArgs...)
 	output, err := command.CombinedOutput()
 	if err != nil {
-		args := strings.Join(mountArgs, " ")
-		klog.Errorf("Mount failed: %v\nMounting command: %s\nMounting arguments: %s\nOutput: %s\n", err, mountCmd, args, string(output))
+		klog.Errorf("Mount failed: %v\nMounting command: %s\nMounting arguments: %s\nOutput: %s\n", err, mountCmd, mountArgsLogStr, string(output))
 		return fmt.Errorf("mount failed: %v\nMounting command: %s\nMounting arguments: %s\nOutput: %s",
-			err, mountCmd, args, string(output))
+			err, mountCmd, mountArgsLogStr, string(output))
 	}
 	return err
 }
@@ -170,33 +180,59 @@ func detectSystemd() bool {
 }
 
 // MakeMountArgs makes the arguments to the mount(8) command.
-// Implementation is shared with NsEnterMounter
-func MakeMountArgs(source, target, fstype string, options []string) []string {
+// options MUST not contain sensitive material (like passwords).
+func MakeMountArgs(source, target, fstype string, options []string) (mountArgs []string) {
+	mountArgs, _ = MakeMountArgsSensitive(source, target, fstype, options, nil /* sensitiveOptions */)
+	return mountArgs
+}
+
+// MakeMountArgsSensitive makes the arguments to the mount(8) command.
+// sensitiveOptions is an extention of options except they will not be logged (because they may contain sensitive material)
+func MakeMountArgsSensitive(source, target, fstype string, options []string, sensitiveOptions []string) (mountArgs []string, mountArgsLogStr string) {
 	// Build mount command as follows:
 	//   mount [-t $fstype] [-o $options] [$source] $target
-	mountArgs := []string{}
+	mountArgs = []string{}
+	mountArgsLogStr = ""
 	if len(fstype) > 0 {
 		mountArgs = append(mountArgs, "-t", fstype)
+		mountArgsLogStr += strings.Join(mountArgs, " ")
 	}
-	if len(options) > 0 {
-		mountArgs = append(mountArgs, "-o", strings.Join(options, ","))
+	if len(options) > 0 || len(sensitiveOptions) > 0 {
+		combinedOptions := []string{}
+		combinedOptions = append(combinedOptions, options...)
+		combinedOptions = append(combinedOptions, sensitiveOptions...)
+		mountArgs = append(mountArgs, "-o", strings.Join(combinedOptions, ","))
+		// exclude sensitiveOptions from log string
+		mountArgsLogStr += " -o " + sanitizedOptionsForLogging(options, sensitiveOptions)
 	}
 	if len(source) > 0 {
 		mountArgs = append(mountArgs, source)
+		mountArgsLogStr += " " + source
 	}
 	mountArgs = append(mountArgs, target)
+	mountArgsLogStr += " " + target
 
-	return mountArgs
+	return mountArgs, mountArgsLogStr
 }
 
 // AddSystemdScope adds "system-run --scope" to given command line
-// implementation is shared with NsEnterMounter
+// If args contains sensitive material, use AddSystemdScopeSensitive to construct
+// a safe to log string.
 func AddSystemdScope(systemdRunPath, mountName, command string, args []string) (string, []string) {
 	descriptionArg := fmt.Sprintf("--description=Kubernetes transient mount for %s", mountName)
 	systemdRunArgs := []string{descriptionArg, "--scope", "--", command}
 	return systemdRunPath, append(systemdRunArgs, args...)
 }
 
+// AddSystemdScopeSensitive adds "system-run --scope" to given command line
+// It also accepts takes a sanitized string containing mount arguments, mountArgsLogStr,
+// and returns the string appended to the systemd command for logging.
+func AddSystemdScopeSensitive(systemdRunPath, mountName, command string, args []string, mountArgsLogStr string) (string, []string, string) {
+	descriptionArg := fmt.Sprintf("--description=Kubernetes transient mount for %s", mountName)
+	systemdRunArgs := []string{descriptionArg, "--scope", "--", command}
+	return systemdRunPath, append(systemdRunArgs, args...), strings.Join(systemdRunArgs, " ") + " " + mountArgsLogStr
+}
+
 // Unmount unmounts the target.
 func (mounter *Mounter) Unmount(target string) error {
 	klog.V(4).Infof("Unmounting %s", target)
@@ -257,8 +293,29 @@ func (mounter *Mounter) GetMountRefs(pat
 	return SearchMountPoints(realpath, procMountInfoPath)
 }
 
+// checkAndRepairFileSystem checks and repairs filesystems using command fsck.
+func (mounter *SafeFormatAndMount) checkAndRepairFilesystem(source string) error {
+	klog.V(4).Infof("Checking for issues with fsck on disk: %s", source)
+	args := []string{"-a", source}
+	out, err := mounter.Exec.Command("fsck", args...).CombinedOutput()
+	if err != nil {
+		ee, isExitError := err.(utilexec.ExitError)
+		switch {
+		case err == utilexec.ErrExecutableNotFound:
+			klog.Warningf("'fsck' not found on system; continuing mount without running 'fsck'.")
+		case isExitError && ee.ExitStatus() == fsckErrorsCorrected:
+			klog.Infof("Device %s has errors which were corrected by fsck.", source)
+		case isExitError && ee.ExitStatus() == fsckErrorsUncorrected:
+			return NewMountError(HasFilesystemErrors, "'fsck' found errors on device %s but could not correct them: %s", source, string(out))
+		case isExitError && ee.ExitStatus() > fsckErrorsUncorrected:
+			klog.Infof("`fsck` error %s", string(out))
+		}
+	}
+	return nil
+}
+
 // formatAndMount uses unix utils to format and mount the given disk
-func (mounter *SafeFormatAndMount) formatAndMount(source string, target string, fstype string, options []string) error {
+func (mounter *SafeFormatAndMount) formatAndMountSensitive(source string, target string, fstype string, options []string, sensitiveOptions []string) error {
 	readOnly := false
 	for _, option := range options {
 		if option == "ro" {
@@ -266,78 +323,80 @@ func (mounter *SafeFormatAndMount) forma
 			break
 		}
 	}
+	if !readOnly {
+		// Check sensitiveOptions for ro
+		for _, option := range sensitiveOptions {
+			if option == "ro" {
+				readOnly = true
+				break
+			}
+		}
+	}
 
 	options = append(options, "defaults")
+	mountErrorValue := UnknownMountError
 
-	if !readOnly {
-		// Run fsck on the disk to fix repairable issues, only do this for volumes requested as rw.
-		klog.V(4).Infof("Checking for issues with fsck on disk: %s", source)
-		args := []string{"-a", source}
-		out, err := mounter.Exec.Command("fsck", args...).CombinedOutput()
-		if err != nil {
-			ee, isExitError := err.(utilexec.ExitError)
-			switch {
-			case err == utilexec.ErrExecutableNotFound:
-				klog.Warningf("'fsck' not found on system; continuing mount without running 'fsck'.")
-			case isExitError && ee.ExitStatus() == fsckErrorsCorrected:
-				klog.Infof("Device %s has errors which were corrected by fsck.", source)
-			case isExitError && ee.ExitStatus() == fsckErrorsUncorrected:
-				return fmt.Errorf("'fsck' found errors on device %s but could not correct them: %s", source, string(out))
-			case isExitError && ee.ExitStatus() > fsckErrorsUncorrected:
-				klog.Infof("`fsck` error %s", string(out))
+	// Check if the disk is already formatted
+	existingFormat, err := mounter.GetDiskFormat(source)
+	if err != nil {
+		return NewMountError(GetDiskFormatFailed, "failed to get disk format of disk %s: %v", source, err)
+	}
+
+	// Use 'ext4' as the default
+	if len(fstype) == 0 {
+		fstype = "ext4"
+	}
+
+	if existingFormat == "" {
+		// Do not attempt to format the disk if mounting as readonly, return an error to reflect this.
+		if readOnly {
+			return NewMountError(UnformattedReadOnly, "cannot mount unformatted disk %s as we are manipulating it in read-only mode", source)
+		}
+
+		// Disk is unformatted so format it.
+		args := []string{source}
+		if fstype == "ext4" || fstype == "ext3" {
+			args = []string{
+				"-F",  // Force flag
+				"-m0", // Zero blocks reserved for super-user
+				source,
 			}
 		}
-	}
 
-	// Try to mount the disk
-	klog.V(4).Infof("Attempting to mount disk: %s %s %s", fstype, source, target)
-	mountErr := mounter.Interface.Mount(source, target, fstype, options)
-	if mountErr != nil {
-		// Mount failed. This indicates either that the disk is unformatted or
-		// it contains an unexpected filesystem.
-		existingFormat, err := mounter.GetDiskFormat(source)
+		klog.Infof("Disk %q appears to be unformatted, attempting to format as type: %q with options: %v", source, fstype, args)
+		output, err := mounter.Exec.Command("mkfs."+fstype, args...).CombinedOutput()
 		if err != nil {
-			return err
+			// Do not log sensitiveOptions only options
+			sensitiveOptionsLog := sanitizedOptionsForLogging(options, sensitiveOptions)
+			detailedErr := fmt.Sprintf("format of disk %q failed: type:(%q) target:(%q) options:(%q) errcode:(%v) output:(%v) ", source, fstype, target, sensitiveOptionsLog, err, string(output))
+			klog.Error(detailedErr)
+			return NewMountError(FormatFailed, detailedErr)
 		}
-		if existingFormat == "" {
-			if readOnly {
-				// Don't attempt to format if mounting as readonly, return an error to reflect this.
-				return errors.New("failed to mount unformatted volume as read only")
-			}
 
-			// Disk is unformatted so format it.
-			args := []string{source}
-			// Use 'ext4' as the default
-			if len(fstype) == 0 {
-				fstype = "ext4"
-			}
+		klog.Infof("Disk successfully formatted (mkfs): %s - %s %s", fstype, source, target)
+	} else {
+		if fstype != existingFormat {
+			// Verify that the disk is formatted with filesystem type we are expecting
+			mountErrorValue = FilesystemMismatch
+			klog.Warningf("Configured to mount disk %s as %s but current format is %s, things might break", source, existingFormat, fstype)
+		}
 
-			if fstype == "ext4" || fstype == "ext3" {
-				args = []string{
-					"-F",  // Force flag
-					"-m0", // Zero blocks reserved for super-user
-					source,
-				}
+		if !readOnly {
+			// Run check tools on the disk to fix repairable issues, only do this for formatted volumes requested as rw.
+			err := mounter.checkAndRepairFilesystem(source)
+			if err != nil {
+				return err
 			}
-			klog.Infof("Disk %q appears to be unformatted, attempting to format as type: %q with options: %v", source, fstype, args)
-			_, err := mounter.Exec.Command("mkfs."+fstype, args...).CombinedOutput()
-			if err == nil {
-				// the disk has been formatted successfully try to mount it again.
-				klog.Infof("Disk successfully formatted (mkfs): %s - %s %s", fstype, source, target)
-				return mounter.Interface.Mount(source, target, fstype, options)
-			}
-			klog.Errorf("format of disk %q failed: type:(%q) target:(%q) options:(%q)error:(%v)", source, fstype, target, options, err)
-			return err
 		}
-		// Disk is already formatted and failed to mount
-		if len(fstype) == 0 || fstype == existingFormat {
-			// This is mount error
-			return mountErr
-		}
-		// Block device is formatted with unexpected filesystem, let the user know
-		return fmt.Errorf("failed to mount the volume as %q, it already contains %s. Mount error: %v", fstype, existingFormat, mountErr)
 	}
-	return mountErr
+
+	// Mount the disk
+	klog.V(4).Infof("Attempting to mount disk %s in %s format at %s", source, fstype, target)
+	if err := mounter.MountSensitive(source, target, fstype, options, sensitiveOptions); err != nil {
+		return NewMountError(mountErrorValue, err.Error())
+	}
+
+	return nil
 }
 
 // GetDiskFormat uses 'blkid' to see if the given disk is unformatted
@@ -412,7 +471,8 @@ func parseProcMounts(content []byte) ([]
 		}
 		fields := strings.Fields(line)
 		if len(fields) != expectedNumFieldsPerLine {
-			return nil, fmt.Errorf("wrong number of fields (expected %d, got %d): %s", expectedNumFieldsPerLine, len(fields), line)
+			// Do not log line in case it contains sensitive Mount options
+			return nil, fmt.Errorf("wrong number of fields (expected %d, got %d)", expectedNumFieldsPerLine, len(fields))
 		}
 
 		mp := MountPoint{
@@ -455,7 +515,8 @@ func SearchMountPoints(hostSource, mount
 
 	mountID := 0
 	rootPath := ""
-	majorMinor := ""
+	major := -1
+	minor := -1
 
 	// Finding the underlying root path and major:minor if possible.
 	// We need search in backward order because it's possible for later mounts
@@ -465,12 +526,13 @@ func SearchMountPoints(hostSource, mount
 			// If it's a mount point or path under a mount point.
 			mountID = mis[i].ID
 			rootPath = filepath.Join(mis[i].Root, strings.TrimPrefix(hostSource, mis[i].MountPoint))
-			majorMinor = mis[i].MajorMinor
+			major = mis[i].Major
+			minor = mis[i].Minor
 			break
 		}
 	}
 
-	if rootPath == "" || majorMinor == "" {
+	if rootPath == "" || major == -1 || minor == -1 {
 		return nil, fmt.Errorf("failed to get root path and major:minor for %s", hostSource)
 	}
 
@@ -480,7 +542,7 @@ func SearchMountPoints(hostSource, mount
 			// Ignore mount entry for mount source itself.
 			continue
 		}
-		if mis[i].Root == rootPath && mis[i].MajorMinor == majorMinor {
+		if mis[i].Root == rootPath && mis[i].Major == major && mis[i].Minor == minor {
 			refs = append(refs, mis[i].MountPoint)
 		}
 	}
Index: kubernetes-1.17.17/vendor/k8s.io/utils/mount/mount_unsupported.go
===================================================================
--- kubernetes-1.17.17.orig/vendor/k8s.io/utils/mount/mount_unsupported.go
+++ kubernetes-1.17.17/vendor/k8s.io/utils/mount/mount_unsupported.go
@@ -43,6 +43,11 @@ func (mounter *Mounter) Mount(source str
 	return errUnsupported
 }
 
+// Mount always returns an error on unsupported platforms
+func (mounter *Mounter) MountSensitive(source string, target string, fstype string, options []string, sensitiveOptions []string) error {
+	return errUnsupported
+}
+
 // Unmount always returns an error on unsupported platforms
 func (mounter *Mounter) Unmount(target string) error {
 	return errUnsupported
@@ -63,7 +68,7 @@ func (mounter *Mounter) GetMountRefs(pat
 	return nil, errUnsupported
 }
 
-func (mounter *SafeFormatAndMount) formatAndMount(source string, target string, fstype string, options []string) error {
+func (mounter *SafeFormatAndMount) formatAndMountSensitive(source string, target string, fstype string, options []string, sensitiveOptions []string) error {
 	return mounter.Interface.Mount(source, target, fstype, options)
 }
 
Index: kubernetes-1.17.17/vendor/k8s.io/utils/mount/mount_windows.go
===================================================================
--- kubernetes-1.17.17.orig/vendor/k8s.io/utils/mount/mount_windows.go
+++ kubernetes-1.17.17/vendor/k8s.io/utils/mount/mount_windows.go
@@ -53,10 +53,20 @@ var getSMBMountMutex = keymutex.NewHashe
 // Mount : mounts source to target with given options.
 // currently only supports cifs(smb), bind mount(for disk)
 func (mounter *Mounter) Mount(source string, target string, fstype string, options []string) error {
+	return mounter.MountSensitive(source, target, fstype, options, nil /* sensitiveOptions */)
+}
+
+// MountSensitive is the same as Mount() but this method allows
+// sensitiveOptions to be passed in a separate parameter from the normal
+// mount options and ensures the sensitiveOptions are never logged. This
+// method should be used by callers that pass sensitive material (like
+// passwords) as mount options.
+func (mounter *Mounter) MountSensitive(source string, target string, fstype string, options []string, sensitiveOptions []string) error {
 	target = NormalizeWindowsPath(target)
+	sanitizedOptionsForLogging := sanitizedOptionsForLogging(options, sensitiveOptions)
 
 	if source == "tmpfs" {
-		klog.V(3).Infof("mounting source (%q), target (%q), with options (%q)", source, target, options)
+		klog.V(3).Infof("mounting source (%q), target (%q), with options (%q)", source, target, sanitizedOptionsForLogging)
 		return os.MkdirAll(target, 0755)
 	}
 
@@ -66,36 +76,37 @@ func (mounter *Mounter) Mount(source str
 	}
 
 	klog.V(4).Infof("mount options(%q) source:%q, target:%q, fstype:%q, begin to mount",
-		options, source, target, fstype)
+		sanitizedOptionsForLogging, source, target, fstype)
 	bindSource := source
 
-	// tell it's going to mount azure disk or azure file according to options
-	if bind, _, _ := MakeBindOpts(options); bind {
-		// mount azure disk
+	if bind, _, _, _ := MakeBindOptsSensitive(options, sensitiveOptions); bind {
 		bindSource = NormalizeWindowsPath(source)
 	} else {
-		if len(options) < 2 {
+		allOptions := []string{}
+		allOptions = append(allOptions, options...)
+		allOptions = append(allOptions, sensitiveOptions...)
+		if len(allOptions) < 2 {
 			klog.Warningf("mount options(%q) command number(%d) less than 2, source:%q, target:%q, skip mounting",
-				options, len(options), source, target)
+				sanitizedOptionsForLogging, len(allOptions), source, target)
 			return nil
 		}
 
 		// currently only cifs mount is supported
 		if strings.ToLower(fstype) != "cifs" {
-			return fmt.Errorf("only cifs mount is supported now, fstype: %q, mounting source (%q), target (%q), with options (%q)", fstype, source, target, options)
+			return fmt.Errorf("only cifs mount is supported now, fstype: %q, mounting source (%q), target (%q), with options (%q)", fstype, source, target, sanitizedOptionsForLogging)
 		}
 
 		// lock smb mount for the same source
 		getSMBMountMutex.LockKey(source)
 		defer getSMBMountMutex.UnlockKey(source)
 
-		if output, err := newSMBMapping(options[0], options[1], source); err != nil {
+		if output, err := newSMBMapping(allOptions[0], allOptions[1], source); err != nil {
 			if isSMBMappingExist(source) {
 				klog.V(2).Infof("SMB Mapping(%s) already exists, now begin to remove and remount", source)
 				if output, err := removeSMBMapping(source); err != nil {
 					return fmt.Errorf("Remove-SmbGlobalMapping failed: %v, output: %q", err, output)
 				}
-				if output, err := newSMBMapping(options[0], options[1], source); err != nil {
+				if output, err := newSMBMapping(allOptions[0], allOptions[1], source); err != nil {
 					return fmt.Errorf("New-SmbGlobalMapping remount failed: %v, output: %q", err, output)
 				}
 			} else {
@@ -116,7 +127,7 @@ func (mounter *Mounter) Mount(source str
 // return (output, error)
 func newSMBMapping(username, password, remotepath string) (string, error) {
 	if username == "" || password == "" || remotepath == "" {
-		return "", fmt.Errorf("invalid parameter(username: %s, password: %s, remoteapth: %s)", username, password, remotepath)
+		return "", fmt.Errorf("invalid parameter(username: %s, password: %s, remoteapth: %s)", username, sensitiveOptionsRemoved, remotepath)
 	}
 
 	// use PowerShell Environment Variables to store user input string to prevent command line injection
@@ -203,7 +214,7 @@ func (mounter *Mounter) GetMountRefs(pat
 	return []string{pathname}, nil
 }
 
-func (mounter *SafeFormatAndMount) formatAndMount(source string, target string, fstype string, options []string) error {
+func (mounter *SafeFormatAndMount) formatAndMountSensitive(source string, target string, fstype string, options []string, sensitiveOptions []string) error {
 	// Try to mount the disk
 	klog.V(4).Infof("Attempting to formatAndMount disk: %s %s %s", fstype, source, target)
 
