Fix SELinux mismatch metrics

DesiredStateOfWorld must remember both
- the effective SELinux label to apply as a mount option (non-empty for
  RWOP volumes, empty otherwise)
- and the label that _would_ be used if the mount option would be used by
  all access modes.

Mismatch warning metrics must be generated from the second label.
This commit is contained in:
Jan Safranek 2023-03-09 14:15:58 +01:00
parent 771c9be291
commit 48ea6a3f3a

View File

@ -206,12 +206,23 @@ type volumeToMount struct {
// Usually this value reflects size recorded in pv.Spec.Capacity
persistentVolumeSize *resource.Quantity
// seLinuxFileLabel is desired SELinux label on files on the volume. If empty, then
// effectiveSELinuxMountFileLabel is the SELinux label that will be applied to the volume using mount options.
// If empty, then:
// - either the context+label is unknown (assigned randomly by the container runtime)
// - or the volume plugin responsible for this volume does not support mounting with -o context
// - or the volume is not ReadWriteOncePod
// - or the OS does not support SELinux
// In all cases, the SELinux context does not matter when mounting the volume.
effectiveSELinuxMountFileLabel string
// originalSELinuxLabel is the SELinux label that would be used if SELinux mount was supported for all access modes.
// For RWOP volumes it's the same as effectiveSELinuxMountFileLabel.
// It is used only to report potential SELinux mismatch metrics.
// If empty, then:
// - either the context+label is unknown (assigned randomly by the container runtime)
// - or the volume plugin responsible for this volume does not support mounting with -o context
// - or the OS does not support SELinux
// In all cases, the SELinux context does not matter when mounting the volume.
seLinuxFileLabel string
originalSELinuxLabel string
}
// The pod object represents a pod that references the underlying volume and
@ -307,23 +318,25 @@ func (dsw *desiredStateOfWorld) AddPodToVolume(
}
}
}
effectiveSELinuxMountLabel := seLinuxFileLabel
if !util.VolumeSupportsSELinuxMount(volumeSpec) {
// Clear SELinux label for the volume with unsupported access modes.
klog.V(4).InfoS("volume does not support SELinux context mount, clearing the expected label", "volume", volumeSpec.Name())
seLinuxFileLabel = ""
effectiveSELinuxMountLabel = ""
}
if seLinuxFileLabel != "" {
seLinuxVolumesAdmitted.Add(1.0)
}
vmt := volumeToMount{
volumeName: volumeName,
podsToMount: make(map[types.UniquePodName]podToMount),
pluginIsAttachable: attachable,
pluginIsDeviceMountable: deviceMountable,
volumeGidValue: volumeGidValue,
reportedInUse: false,
desiredSizeLimit: sizeLimit,
seLinuxFileLabel: seLinuxFileLabel,
volumeName: volumeName,
podsToMount: make(map[types.UniquePodName]podToMount),
pluginIsAttachable: attachable,
pluginIsDeviceMountable: deviceMountable,
volumeGidValue: volumeGidValue,
reportedInUse: false,
desiredSizeLimit: sizeLimit,
effectiveSELinuxMountFileLabel: effectiveSELinuxMountLabel,
originalSELinuxLabel: seLinuxFileLabel,
}
// record desired size of the volume
if volumeSpec.PersistentVolume != nil {
@ -337,9 +350,9 @@ func (dsw *desiredStateOfWorld) AddPodToVolume(
} else {
// volume exists
if pluginSupportsSELinuxContextMount {
if seLinuxFileLabel != vol.seLinuxFileLabel {
if seLinuxFileLabel != vol.originalSELinuxLabel {
// TODO: update the error message after tests, e.g. add at least the conflicting pod names.
fullErr := fmt.Errorf("conflicting SELinux labels of volume %s: %q and %q", volumeSpec.Name(), vol.seLinuxFileLabel, seLinuxFileLabel)
fullErr := fmt.Errorf("conflicting SELinux labels of volume %s: %q and %q", volumeSpec.Name(), vol.originalSELinuxLabel, seLinuxFileLabel)
supported := util.VolumeSupportsSELinuxMount(volumeSpec)
if err := handleSELinuxMetricError(fullErr, supported, seLinuxVolumeContextMismatchWarnings, seLinuxVolumeContextMismatchErrors); err != nil {
return "", err
@ -499,7 +512,7 @@ func (dsw *desiredStateOfWorld) VolumeExists(
// and mounted with new SELinux mount options for pod B.
// Without SELinux, kubelet can (and often does) reuse device mounted
// for A.
return vol.seLinuxFileLabel == seLinuxMountContext
return vol.effectiveSELinuxMountFileLabel == seLinuxMountContext
}
return true
}
@ -515,7 +528,7 @@ func (dsw *desiredStateOfWorld) PodExistsInVolume(
}
if feature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
if volumeObj.seLinuxFileLabel != seLinuxMountOption {
if volumeObj.effectiveSELinuxMountFileLabel != seLinuxMountOption {
// The volume is in DSW, but with a different SELinux mount option.
// Report it as unused, so the volume is unmounted and mounted back
// with the right SELinux option.
@ -573,7 +586,7 @@ func (dsw *desiredStateOfWorld) GetVolumesToMount() []VolumeToMount {
ReportedInUse: volumeObj.reportedInUse,
MountRequestTime: podObj.mountRequestTime,
DesiredSizeLimit: volumeObj.desiredSizeLimit,
SELinuxLabel: volumeObj.seLinuxFileLabel,
SELinuxLabel: volumeObj.effectiveSELinuxMountFileLabel,
},
}
if volumeObj.persistentVolumeSize != nil {