Repository: kubernetes/kubernetes (language: go)

Issue:
NFS PV mountOptions does not work when Volume SubPath option is set
### What happened?

Setting the Volume subpath option at deployment with an NFS PV with a mount option (e.g. nosuid) does not mount accordingly. If no SubPath is set and the NFS PV is set to the /nfs_share/directory the mount works with the nosuid.

### What did you expect to happen?

should be mounted with correct mountoptions

### How can we reproduce it (as minimally and precisely as possible)?

- create KIND cluster and install nfs client packages
- create a PV and PVC with below options: 


```
spec:
  accessModes:
    - ReadWriteOnce
    - ReadOnlyMany
    - ReadWriteMany
  capacity:
    storage: 10Gi
  claimRef:
    apiVersion: v1
    kind: PersistentVolumeClaim
    name: pvc01
    namespace: default
    resourceVersion: '53505'
    uid: 0b3736ac-bbb6-4539-95c1-854ddcb36114
  mountOptions:
    - nfsvers=4.2
    - sec=sys
    - nosuid
  nfs:
    path: /nfs
    server: 172.31.40.82
  persistentVolumeReclaimPolicy: Retain
  volumeMode: Filesystem  
```
-  Update the deployment with the volume and mount information: 

```
          volumeMounts:
            - mountPath: /data
              name: vol-oirnd
              subPath: share01

      volumes:
        - name: vol-oirnd
          persistentVolumeClaim:
            claimName: pvc01
          __newPvc:
            type: persistentvolumeclaim
            metadata:
              namespace: default
            spec:
              storageClassName: ''
              volumeName: ''
              resources:
                requests: {} 
```

### Anything else we need to know?

```
**Not using SubPath**

root@kind-2-control-plane:/# mount | grep nfs
192.168.100.217:/nfs on /var/lib/kubelet/pods/c29b33d8-3709-4082-892c-def5efbba86f/volumes/kubernetes.io~nfs/pv type nfs4 (rw,nosuid,relatime,vers=4.2,rsize=524288,wsize=524288,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=172.18.0.2,local_lock=none,addr=192.168.100.217)

**When not using SubPath**


192.168.100.217:/nfs/hello/world on /var/lib/kubelet/pods/c29b33d8-3709-4082-892c-def5efbba86f/volume-subpaths/pv/httpd/0 type nfs4 (rw,relatime,vers=4.2,rsize=524288,wsize=524288,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=172.18.0.2,local_lock=none,addr=192.168.100.217)
root@kind-2-control-plane:/# 

root@kind-2-control-plane:/# kubectl get nodes
NAME                   STATUS   ROLES           AGE   VERSION
kind-2-control-plane   Ready    control-plane   49m   v1.29.2
root@kind-2-control-plane:/# 
```

### Kubernetes version

<details>

```console
$ kubectl version
 v1.29.2
```

</details>


### Cloud provider

<details>

</details>


### OS version

<details>

```console
# On Linux:
$ cat /etc/os-release
# paste output here
$ uname -a
Ubuntu

# On Windows:
C:\> wmic os get Caption, Version, BuildNumber, OSArchitecture
# paste output here
```

</details>


### Install tools

<details>

</details>


### Container runtime (CRI) and version (if applicable)

<details>

</details>


### Related plugins (CNI, CSI, ...) and versions (if applicable)

<details>

</details>



Discussion / hints:
/sig storage
/triage accepted
Hi. I've researched this problem and here's how it works:
1) The nfs Plugin mounts nfs-share in volumes/kubernetes.io~nfs/\<pv-name>
2) subpather mounts volumes/kubernetes.io~nfs/\<pv-name>/\<subpath> to volume-subpaths/\<pv-name>/\<ctr-name>/\<mount-index>

In fact, subpather runs the mount -o bind command...
That's how it looks in the code:
https://github.com/kubernetes/kubernetes/blob/1608dc2b0928fc69a9923716a305612746dbec55/pkg/volume/util/subpath/subpath_linux.go#L228-L233

When using the --bind option to mount one directory to another, the original mounting options are not automatically transferred to the new mounting point. 
That is, when using mount --bind, the mount options, including the NFS-specific nosuid, will not be saved automatically on the new mount.
However, these options continue to work "in the background", as they are active for the original mounting point.
So it turns out that there is a problem only with displaying all the options, of course if we consider this a problem? 
It seems to me that this can be easily fixed by simply reading the parameters from the first mount and adding them to the second.
I can do a pr
/assign
In my cluster (created by `hack/local-up-cluster.sh`), I can see both the main mount + subpath mount retain `nosuid` in their /proc/mounts entries:

```
192.168.122.1:/home/jsafrane/tmp on /var/lib/kubelet/pods/559a34f5-226a-48ae-8dbe-a93458404b68/volumes/kubernetes.io~nfs/nfs-pv type nfs4 (rw,nosuid,relatime,vers=4.2,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=192.168.122.75,local_lock=none,addr=192.168.122.1)
192.168.122.1:/home/jsafrane/tmp/subdir on /var/lib/kubelet/pods/559a34f5-226a-48ae-8dbe-a93458404b68/volume-subpaths/nfs-pv/busybox/0 type nfs4 (rw,nosuid,relatime,vers=4.2,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=192.168.122.75,local_lock=none,addr=192.168.122.1)
```

Kubernetes 1.31 beta (but I don't think it matters), Fedora 39, Kernel 6.8.10-200.fc39.x86_64
It could be caused either by the kernel or KIND.

`mount` man page says:

> Note that the filesystem mount options maintained by the kernel will remain the same as those on the original mount point. The userspace mount options (e.g., _netdev) will not be copied by mount and it’s necessary to explicitly specify the options on the mount command line.
...
> It’s also possible to change nosuid, nodev, noexec, noatime, nodiratime, relatime and nosymfollow VFS entry flags via ...


I interpret it as `nosuid` should be copied by default, but can be explicitly changed in a bind mount.
@jsafrane Hi
It appears that you are correct. However, I conducted additional testing and can confirm that I have:
1. cluster "KIND" using an image created from the master branch.
```
Kubernetes version: v1.32.0-alpha.0.18
Containerd version: v1.7.15
OS in a KIND:
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm

OS on my host:
NAME="Fedora Linux"
VERSION="40 (Workstation Edition)"
ID=fedora
VERSION_ID=40
VERSION_CODENAME=""
PLATFORM_ID="platform:f40"
PRETTY_NAME="Fedora Linux 40 (Workstation Edition)"

KERNEL: 6.9.11-200.fc40.x86_64
```

RESULT:
```
172.18.0.3:/var/nfs/pvc1 on /var/lib/kubelet/pods/1ff6e863-124d-498e-83db-e79fe668426b/volumes/kubernetes.io~nfs/nfs-pv-1 type nfs (rw,nosuid,relatime,vers=3,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=172.18.0.3,mountvers=3,mountport=39415,mountproto=udp,local_lock=none,addr=172.18.0.3)
172.18.0.3:/var/nfs/pvc1/share01 on /var/lib/kubelet/pods/1ff6e863-124d-498e-83db-e79fe668426b/volume-subpaths/nfs-pv-1/busybox/0 type nfs (rw,relatime,vers=3,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=172.18.0.3,mountvers=3,mountport=39415,mountproto=udp,local_lock=none,addr=172.18.0.3)
```


2. Working cluster on bare metal

```
Kubernetes version: v1.26.15 (I understand that this version is old, but now I don't have another one at hand, later I will be able to repeat this on a more recent one.)
Containerd version: v1.7.13
OS:
PRETTY_NAME="Ubuntu 22.04.4 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.4 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy

KERNEL: 5.15.0-75-generic
```

RESULT:
```
172.18.18.80:/var/nfs/pvc1 on /var/lib/kubelet/pods/3d389a14-f2b9-44ba-af6c-0e5154285527/volumes/kubernetes.io~nfs/nfs-pv-1 type nfs4 (rw,nosuid,relatime,vers=4.2,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=172.18.18.81,local_lock=none,addr=172.18.18.80)
172.18.18.80:/var/nfs/pvc1/share01 on /var/lib/kubelet/pods/3d389a14-f2b9-44ba-af6c-0e5154285527/volume-subpaths/nfs-pv-1/busybox/0 type nfs4 (rw,relatime,vers=4.2,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=172.18.18.81,local_lock=none,addr=172.18.18.80)

```
I continued my research and found that the "Mounter" with the bind option always performs a remount
https://github.com/kubernetes/kubernetes/blob/60c4c2b2521fb454ce69dee737e3eb91a25e0535/staging/src/k8s.io/mount-utils/mount_linux.go#L145-L149
This is why mount parameters that were not passed directly are missing.

But there is a fix that added some mount options, if kubelet is running in a user namespace, that's why I think you didn't encounter this problem in your testing.
https://github.com/kubernetes/kubernetes/blob/60c4c2b2521fb454ce69dee737e3eb91a25e0535/staging/src/k8s.io/mount-utils/mount_linux.go#L150-L162

Nice! So... should we jest remove `if libcontaineruserns.RunningInUserNS()` check?
I think so. In the near future, I will be able to check this and make a new PR or change the old one.

Fix patch:
diff --git a/staging/src/k8s.io/mount-utils/go.mod b/staging/src/k8s.io/mount-utils/go.mod
index 6e032e7c0aeb7..4b3d51c303110 100644
--- a/staging/src/k8s.io/mount-utils/go.mod
+++ b/staging/src/k8s.io/mount-utils/go.mod
@@ -8,7 +8,6 @@ godebug default=go1.23
 
 require (
 	github.com/moby/sys/mountinfo v0.7.1
-	github.com/opencontainers/runc v1.1.14
 	github.com/stretchr/testify v1.9.0
 	golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
 	golang.org/x/sys v0.23.0
@@ -17,15 +16,11 @@ require (
 )
 
 require (
-	github.com/coreos/go-systemd/v22 v22.5.0 // indirect
 	github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
 	github.com/go-logr/logr v1.4.2 // indirect
-	github.com/godbus/dbus/v5 v5.1.0 // indirect
 	github.com/kr/pretty v0.3.1 // indirect
-	github.com/opencontainers/runtime-spec v1.2.0 // indirect
 	github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
 	github.com/rogpeppe/go-internal v1.12.0 // indirect
-	github.com/sirupsen/logrus v1.9.3 // indirect
 	gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 )
diff --git a/staging/src/k8s.io/mount-utils/go.sum b/staging/src/k8s.io/mount-utils/go.sum
index 8fb0419910050..ab0b8883cbfea 100644
--- a/staging/src/k8s.io/mount-utils/go.sum
+++ b/staging/src/k8s.io/mount-utils/go.sum
@@ -1,21 +1,8 @@
-github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
-github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
-github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
-github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
-github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
-github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
-github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
-github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
 github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
 github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
-github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
-github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
-github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
 github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
@@ -26,48 +13,26 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g=
 github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
-github.com/mrunalp/fileutils v0.5.1/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
-github.com/opencontainers/runc v1.1.14 h1:rgSuzbmgz5DUJjeSnw337TxDbRuqjs6iqQck/2weR6w=
-github.com/opencontainers/runc v1.1.14/go.mod h1:E4C2z+7BxR7GHXp0hAY53mek+x49X1LjPNeMTfRGvOA=
-github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=
-github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
-github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
 github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
-github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
 github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
 github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
-github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
-github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
-github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
-github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
-github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
 github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
-github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
-github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
-github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
-github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
 golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
-golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
 golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
 golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
-google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
diff --git a/staging/src/k8s.io/mount-utils/mount_linux.go b/staging/src/k8s.io/mount-utils/mount_linux.go
index 843b84a463440..5901114f049ce 100644
--- a/staging/src/k8s.io/mount-utils/mount_linux.go
+++ b/staging/src/k8s.io/mount-utils/mount_linux.go
@@ -35,7 +35,6 @@ import (
 	"github.com/moby/sys/mountinfo"
 	"golang.org/x/sys/unix"
 
-	libcontaineruserns "github.com/opencontainers/runc/libcontainer/userns"
 	"k8s.io/klog/v2"
 	utilexec "k8s.io/utils/exec"
 )
@@ -114,7 +113,7 @@ func (mounter *Mounter) hasSystemd() bool {
 
 // Map unix.Statfs mount flags ro, nodev, noexec, nosuid, noatime, relatime,
 // nodiratime to mount option flag strings.
-func getUserNSBindMountOptions(path string, statfs func(path string, buf *unix.Statfs_t) (err error)) ([]string, error) {
+func getBindMountOptions(path string, statfs func(path string, buf *unix.Statfs_t) (err error)) ([]string, error) {
 	var s unix.Statfs_t
 	var mountOpts []string
 	if err := statfs(path, &s); err != nil {
@@ -137,32 +136,23 @@ func getUserNSBindMountOptions(path string, statfs func(path string, buf *unix.S
 	return mountOpts, nil
 }
 
-// Do a bind mount including the needed remount for applying the bind opts.
-// If the remount fails and we are running in a user namespace
-// figure out if the source filesystem has the ro, nodev, noexec, nosuid,
-// noatime, relatime or nodiratime flag set and try another remount with the found flags.
+// Performs a bind mount with the specified options, and then remounts
+// the mount point with the same `nodev`, `nosuid`, `noexec`, `nosuid`, `noatime`,
+// `relatime`, `nodiratime` options as the original mount point.
 func (mounter *Mounter) bindMountSensitive(mounterPath string, mountCmd string, source string, target string, fstype string, bindOpts []string, bindRemountOpts []string, bindRemountOptsSensitive []string, mountFlags []string, systemdMountRequired bool) error {
-	err := mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindOpts, bindRemountOptsSensitive, mountFlags, systemdMountRequired)
+	err := mounter.doMount(mounterPath, mountCmd, source, target, fstype, bindOpts, bindRemountOptsSensitive, mountFlags, systemdMountRequired)
 	if err != nil {
 		return err
 	}
-	err = mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindRemountOpts, bindRemountOptsSensitive, mountFlags, systemdMountRequired)
-	if libcontaineruserns.RunningInUserNS() {
-		if err == nil {
-			return nil
-		}
-		// Check if the source has ro, nodev, noexec, nosuid, noatime, relatime,
-		// nodiratime flag...
-		fixMountOpts, err := getUserNSBindMountOptions(source, unix.Statfs)
-		if err != nil {
-			return &os.PathError{Op: "statfs", Path: source, Err: err}
-		}
-		// ... and retry the mount with flags found above.
-		bindRemountOpts = append(bindRemountOpts, fixMountOpts...)
-		return mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindRemountOpts, bindRemountOptsSensitive, mountFlags, systemdMountRequired)
-	} else {
-		return err
+	// Check if the source has ro, nodev, noexec, nosuid, noatime, relatime,
+	// nodiratime flag...
+	fixMountOpts, err := getBindMountOptions(source, unix.Statfs)
+	if err != nil {
+		return &os.PathError{Op: "statfs", Path: source, Err: err}
 	}
+	// ... and retry the mount with flags found above.
+	bindRemountOpts = append(bindRemountOpts, fixMountOpts...)
+	return mounter.doMount(mounterPath, mountCmd, source, target, fstype, bindRemountOpts, bindRemountOptsSensitive, mountFlags, systemdMountRequired)
 }
 
 // Mount mounts source to target as fstype with given options. 'source' and 'fstype' must


Test patch:
diff --git a/staging/src/k8s.io/mount-utils/mount_linux_test.go b/staging/src/k8s.io/mount-utils/mount_linux_test.go
index 3c0842b20b35c..e8c765b5c52e4 100644
--- a/staging/src/k8s.io/mount-utils/mount_linux_test.go
+++ b/staging/src/k8s.io/mount-utils/mount_linux_test.go
@@ -821,7 +821,7 @@ func mkStatfsFlags[T1 constraints.Integer, T2 constraints.Integer](orig T1, add
 	return orig | T1(add)
 }
 
-func TestGetUserNSBindMountOptions(t *testing.T) {
+func TestGetBindMountOptions(t *testing.T) {
 	var testCases = map[string]struct {
 		flags        int32 // smallest size used by any platform we care about
 		mountoptions string
@@ -843,9 +843,9 @@ func TestGetUserNSBindMountOptions(t *testing.T) {
 		return nil
 	}
 
-	testGetUserNSBindMountOptionsSingleCase := func(t *testing.T) {
+	testGetBindMountOptionsSingleCase := func(t *testing.T) {
 		path := strings.Split(t.Name(), "/")[1]
-		options, _ := getUserNSBindMountOptions(path, statfsMock)
+		options, _ := getBindMountOptions(path, statfsMock)
 		sort.Strings(options)
 		optionString := strings.Join(options, ",")
 		mountOptions := testCases[path].mountoptions
@@ -855,7 +855,7 @@ func TestGetUserNSBindMountOptions(t *testing.T) {
 	}
 
 	for k := range testCases {
-		t.Run(k, testGetUserNSBindMountOptionsSingleCase)
+		t.Run(k, testGetBindMountOptionsSingleCase)
 	}
 }
 
diff --git a/test/e2e/storage/drivers/in_tree.go b/test/e2e/storage/drivers/in_tree.go
index 58ec455c67b30..402ad397858b8 100644
--- a/test/e2e/storage/drivers/in_tree.go
+++ b/test/e2e/storage/drivers/in_tree.go
@@ -43,6 +43,7 @@ import (
 	"time"
 
 	"github.com/onsi/ginkgo/v2"
+
 	v1 "k8s.io/api/core/v1"
 	rbacv1 "k8s.io/api/rbac/v1"
 	storagev1 "k8s.io/api/storage/v1"
@@ -1223,7 +1224,12 @@ func (l *localDriver) PrepareTest(ctx context.Context, f *framework.Framework) *
 	framework.ExpectNoError(err)
 
 	l.hostExec = utils.NewHostExec(f)
-	l.ltrMgr = utils.NewLocalResourceManager("local-driver", l.hostExec, "/tmp")
+	// It is recommended to mount /tmp with options noexec, nodev, nosuid.
+	// tmpfs on /tmp type tmpfs (rw,nosuid,nodev,noexec,relatime,seclabel,inode64)
+	// This prevents scripts and binaries from being executed from the /tmp directory.
+	// This can cause errors like "Permission denied" when executing files from `/tmp`.
+	// To pass the test that verifies the execution of files on a volume, we use `/var/tmp` instead of `/tmp`.
+	l.ltrMgr = utils.NewLocalResourceManager("local-driver", l.hostExec, "/var/tmp")
 
 	// This can't be done in SkipUnsupportedTest because the test framework is not initialized yet
 	if l.volumeType == utils.LocalVolumeGCELocalSSD {
diff --git a/test/e2e/storage/utils/local.go b/test/e2e/storage/utils/local.go
index df96eac124e3b..1dccee34625da 100644
--- a/test/e2e/storage/utils/local.go
+++ b/test/e2e/storage/utils/local.go
@@ -27,6 +27,7 @@ import (
 	"strings"
 
 	"github.com/onsi/ginkgo/v2"
+
 	v1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/util/uuid"
 	"k8s.io/kubernetes/test/e2e/framework"
@@ -215,7 +216,7 @@ func (l *ltrMgr) cleanupLocalVolumeDirectory(ctx context.Context, ltr *LocalTest
 func (l *ltrMgr) setupLocalVolumeDirectoryLink(ctx context.Context, node *v1.Node, parameters map[string]string) *LocalTestResource {
 	hostDir := l.getTestDir()
 	hostDirBackend := hostDir + "-backend"
-	cmd := fmt.Sprintf("mkdir %s && ln -s %s %s", hostDirBackend, hostDirBackend, hostDir)
+	cmd := fmt.Sprintf("mkdir -p %s && ln -s %s %s", hostDirBackend, hostDirBackend, hostDir)
 	err := l.hostExec.IssueCommand(ctx, cmd, node)
 	framework.ExpectNoError(err)
 	return &LocalTestResource{
@@ -235,7 +236,7 @@ func (l *ltrMgr) cleanupLocalVolumeDirectoryLink(ctx context.Context, ltr *Local
 
 func (l *ltrMgr) setupLocalVolumeDirectoryBindMounted(ctx context.Context, node *v1.Node, parameters map[string]string) *LocalTestResource {
 	hostDir := l.getTestDir()
-	cmd := fmt.Sprintf("mkdir %s && mount --bind %s %s", hostDir, hostDir, hostDir)
+	cmd := fmt.Sprintf("mkdir -p %s && mount --bind %s %s", hostDir, hostDir, hostDir)
 	err := l.hostExec.IssueCommand(ctx, cmd, node)
 	framework.ExpectNoError(err)
 	return &LocalTestResource{
@@ -255,7 +256,7 @@ func (l *ltrMgr) cleanupLocalVolumeDirectoryBindMounted(ctx context.Context, ltr
 func (l *ltrMgr) setupLocalVolumeDirectoryLinkBindMounted(ctx context.Context, node *v1.Node, parameters map[string]string) *LocalTestResource {
 	hostDir := l.getTestDir()
 	hostDirBackend := hostDir + "-backend"
-	cmd := fmt.Sprintf("mkdir %s && mount --bind %s %s && ln -s %s %s", hostDirBackend, hostDirBackend, hostDirBackend, hostDirBackend, hostDir)
+	cmd := fmt.Sprintf("mkdir -p %s && mount --bind %s %s && ln -s %s %s", hostDirBackend, hostDirBackend, hostDirBackend, hostDirBackend, hostDir)
 	err := l.hostExec.IssueCommand(ctx, cmd, node)
 	framework.ExpectNoError(err)
 	return &LocalTestResource{