Change:
On a busy system, kubelet failed to tell the container runtime that a pod's CSI volume supports SELinux and should be relabeled with pod's SELinux label. The pod then can't access the volume. Kubelet correctly detects that the CSI volume supports SELinux and tells the container runtime to relabel it. Unknown. Get a busy system and try hard? CSI volume plugin tried to detect that the volume supports SELinux during SetupAt. This check failed: Current CSI volume plugin code silently consumes the error and assumes that the volume does not support SELinux at all: Therefore, the volume is marked as mounted and given to the container runtime without the right SELinux options and the runtime does not relabel volume. <details22.0 </details<detailsNone </details<details</details<details</details<detailsCRI-O, but I think it's not really relevant. </details<details</details
/sig storage /triage accepted
We've updated kubelet in our clusters to v1.20.13 (which contains the cherry picked fix), but still observe the issue

Discussion:
c.supportsSELinux, err = c.kubeVolHost.GetHostUtil().GetSELinuxSupport(dir) if err != nil { <del> klog.V(2).Info(log("error checking for SELinux support: %s", err)) </del> <ins> // The volume is mounted. Return UncertainProgressError, so kubelet will unmount it when user deletes the pod. return volumetypes.NewUncertainProgressError(fmt.Sprintf("error checking for SELinux support: %s", err)) </ins> } if !driverSupportsCSIVolumeMountGroup && c.supportsFSGroup(fsType, mounterArgs.FsGroup, c.fsGroupPolicy) {

// GetSELinuxSupport tests if pathname is on a mount that supports SELinux. // Not implemented for testing func (hu *FakeHostUtil) GetSELinuxSupport(pathname string) (bool, error) { <del> return false, errors.New("GetSELinuxSupport not implemented") </del> <ins> return false, nil </ins> } // GetMode returns permissions of pathname.

"golang.org/x/sys/unix" "k8s.io/klog/v2" <ins> "k8s.io/kubernetes/pkg/util/selinux" </ins> "k8s.io/mount-utils" utilpath "k8s.io/utils/path" )

return nil } <ins> // selinux.SELinuxEnabled implementation for unit tests type seLinuxEnabledFunc func() bool </ins> // GetSELinux is common implementation of GetSELinuxSupport on Linux. <del> func GetSELinux(path string, mountInfoFilename string) (bool, error) { </del> <ins> func GetSELinux(path string, mountInfoFilename string, selinuxEnabled seLinuxEnabledFunc) (bool, error) { // Skip /proc/mounts parsing if SELinux is disabled. if !selinuxEnabled() { return false, nil } </ins> info, err := findMountInfo(path, mountInfoFilename) if err != nil { return false, err

// GetSELinuxSupport returns true if given path is on a mount that supports // SELinux. func (hu *HostUtil) GetSELinuxSupport(pathname string) (bool, error) { <del> return GetSELinux(pathname, procMountInfoPath) </del> <ins> return GetSELinux(pathname, procMountInfoPath, selinux.SELinuxEnabled) </ins> } // GetOwner returns the integer ID for the user and group of the given path

tests := []struct { name           string mountPoint     string <ins> selinuxEnabled bool </ins> expectedResult bool }{ { <ins> "ext4 on / with disabled SELinux", "/", false, false, }, { </ins> "ext4 on /", "/", true, <ins> true, </ins> }, { "tmpfs on /var/lib/bar", "/var/lib/bar", <ins> true, </ins> false, }, { "nfsv4", "/media/nfs_vol", <ins> true, </ins> false, }, } for _, test := range tests { <del> out, err := GetSELinux(test.mountPoint, filename) </del> <ins> out, err := GetSELinux(test.mountPoint, filename, func() bool { return test.selinuxEnabled }) </ins> if err != nil { t.Errorf("Test %s failed with error: %s", test.name, err) }