Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions pkg/apis/core/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -2187,6 +2187,10 @@ type VolumeMount struct {
// SubPathExpr and SubPath are mutually exclusive.
// +optional
SubPathExpr string
// mountOptions is a list of mount options (noexec, nodev, nosuid) to apply
// when mounting this volume into the container.
// +optional
MountOptions []string
}

// MountPropagationMode describes mount propagation.
Expand Down
2 changes: 2 additions & 0 deletions pkg/apis/core/v1/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions pkg/apis/core/validation/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -3146,6 +3146,19 @@ func ValidateVolumeMounts(mounts []core.VolumeMount, voldevices map[string]strin
allErrs = append(allErrs, validateMountPropagation(mnt.MountPropagation, container, fldPath.Child("mountPropagation"))...)
}
allErrs = append(allErrs, validateMountRecursiveReadOnly(mnt, fldPath.Child("recursiveReadOnly"))...)

if len(mnt.MountOptions) > 0 {
if !utilfeature.DefaultFeatureGate.Enabled(features.VolumeMountOptions) {
allErrs = append(allErrs, field.Forbidden(idxPath.Child("mountOptions"), "mount options require the VolumeMountOptions feature gate to be enabled"))
} else {
allowedOptions := sets.New("noexec", "nodev", "nosuid")
for j, opt := range mnt.MountOptions {
if !allowedOptions.Has(opt) {
allErrs = append(allErrs, field.NotSupported(idxPath.Child("mountOptions").Index(j), opt, sets.List(allowedOptions)))
}
}
}
Comment on lines +3150 to +3160

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== References to VolumeMountOptions feature gate =="
rg -n -C3 'VolumeMountOptions|MountOptions' pkg staging/src/k8s.io 2>/dev/null || true

echo
echo "== Pod strategy/drop-disabled handling =="
rg -n -C4 'dropDisabled|DropDisabled|VolumeMountOptions|mountOptions' pkg/registry/core 2>/dev/null || true

echo
echo "== Pod validation options plumbing for create/update =="
rg -n -C4 'PodValidationOptions|ValidationOptionsForPod|ValidatePod(Create|Update|TemplateSpec)' pkg/apis/core 2>/dev/null || true

Repository: openshift/kubernetes

Length of output: 50377


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Locate ValidateVolumeMounts call sites =="
rg -n "ValidateVolumeMounts" pkg/apis/core/validation/validation.go pkg/apis/core/validation -S || true

echo
echo "== Feature gate check usage (VolumeMountOptions) =="
rg -n "VolumeMountOptions" pkg/apis/core/validation/validation.go pkg/apis/core/validation -S || true

echo
echo "== Pod validation entrypoints (create/update/template) =="
rg -n "ValidatePod(Create|Update|TemplateSpec)" pkg/apis/core/validation -S || true
rg -n "type PodValidationOptions|PodValidationOptions" pkg/apis/core/validation -S || true

echo
echo "== Any pod field-dropping / dropDisabled logic touching mountOptions =="
rg -n "(dropDisabled|DropDisabled)" pkg/registry/core -S || true
rg -n "mountOptions" pkg/registry/core -S | head -n 80 || true

Repository: openshift/kubernetes

Length of output: 37115


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Search for mountOptions in pod disabled field dropping =="
rg -n "mountOptions|VolumeMountOptions" pkg/registry/core/pod pkg/registry/core/podtemplate pkg/registry/core/replicationcontroller pkg/registry/core -S || true

echo
echo "== Locate podutil.DropDisabledPodFields implementation =="
rg -n "func DropDisabledPodFields" -S pkg | head -n 50

echo
# Search for the helper that might drop mountOptions inside podutil or related utils
rg -n "DropDisabledPodFields" -S pkg | head -n 50

echo
echo "== Search for VolumeMountOptions feature gate in registry pod util code =="
rg -n "VolumeMountOptions" -S pkg/registry pkg/util pkg/apis | head -n 200

Repository: openshift/kubernetes

Length of output: 1823


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show DropDisabledPodFields logic around where spec fields might be dropped
nl -ba pkg/api/pod/util.go | sed -n '650,780p'

echo
echo "== Search for mountOptions/VolumeMountOptions inside util.go =="
rg -n "mountOptions|VolumeMountOptions" pkg/api/pod/util.go -S || true

Repository: openshift/kubernetes

Length of output: 107


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== DropDisabledPodFields implementation (pkg/api/pod/util.go) =="
cat -n pkg/api/pod/util.go | sed -n '660,780p'

echo
echo "== Search for mountOptions/VolumeMountOptions inside util.go =="
rg -n "mountOptions|VolumeMountOptions" pkg/api/pod/util.go -S || true

Repository: openshift/kubernetes

Length of output: 5813


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Does podutil/dropDisabled handle mountOptions? =="
rg -n "mountOptions" pkg/api/pod -S || true
rg -n "VolumeMountOptions" pkg/api/pod -S || true

echo
echo "== Remaining part of dropDisabledFields (look for any mountOptions-related helpers) =="
rg -n "dropDisabledFields|dropDisabled.*mount|mountOptions" pkg/api/pod/util.go -S || true

echo
echo "== PodValidationOptions fields mentioning mountOptions / gate =="
rg -n "type PodValidationOptions" -n pkg/apis/core/validation/validation.go
sed -n '4450,4555p' pkg/apis/core/validation/validation.go

echo
echo "== Any other uses of VolumeMountOptions beyond ValidateVolumeMounts =="
rg -n "VolumeMountOptions" pkg/apis/core/validation -S || true

echo
echo "== Any other gate-drop / field-drop logic for mountOptions elsewhere =="
rg -n "mountOptions.*featuregate|featuregate.*mountOptions|VolumeMountOptions.*drop" -S pkg | head -n 200 || true

Repository: openshift/kubernetes

Length of output: 6360


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Search for VolumeMountOptions in pod util (pkg/api/pod/util.go) =="
rg -n "VolumeMountOptions" pkg/api/pod/util.go pkg/api/pod -S || true

echo
echo "== Inspect GetValidationOptionsFromPodSpecAndMeta in pkg/api/pod/util.go =="
rg -n "func GetValidationOptionsFromPodSpecAndMeta" pkg/api/pod/util.go -S
# print a window around the function
start=$(rg -n "func GetValidationOptionsFromPodSpecAndMeta" pkg/api/pod/util.go -n | head -n1 | cut -d: -f1)
end=$((start+260))
sed -n "${start},${end}p" pkg/api/pod/util.go

echo
echo "== Inspect pod strategy PrepareForUpdate/PrepareForCreate calling DropDisabledPodFields =="
rg -n "PrepareForUpdate|PrepareForCreate|DropDisabledPodFields" pkg/registry/core/pod/strategy.go -S
cat -n pkg/registry/core/pod/strategy.go | sed -n '60,180p'

echo
echo "== Inspect ValidateVolumeMounts call site in ValidateVolumeMounts flow (validateContainerCommon) =="
cat -n pkg/apis/core/validation/validation.go | sed -n '3870,3960p'

Repository: openshift/kubernetes

Length of output: 22390


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Search for mountOptions / VolumeMountOptions in pod drop-disabled code =="
rg -n "mountOptions|VolumeMountOptions|MountOptions" pkg/api/pod -S || true

echo
echo "== Search for DropDisabledTemplateFields call sites (pods embedded in controllers) =="
rg -n "DropDisabledTemplateFields" pkg/registry/core -S

echo
echo "== Search for PodTemplate validation update flow and whether it uses old spec for gating =="
rg -n "ValidatePodTemplateUpdate" pkg/apis/core/validation/validation.go
# show the function body window
start=$(rg -n "func ValidatePodTemplateUpdate" pkg/apis/core/validation/validation.go | head -n1 | cut -d: -f1)
end=$((start+220))
sed -n "${start},${end}p" pkg/apis/core/validation/validation.go

Repository: openshift/kubernetes

Length of output: 11216


Fix/update compatibility when disabling the VolumeMountOptions feature gate

ValidateVolumeMounts hard-forbids volumeMount.mountOptions whenever features.VolumeMountOptions is disabled. Pod/controller create/update flows call podutil.DropDisabledPodFields/DropDisabledTemplateFields, but those drop helpers have no mountOptions/VolumeMountOptions handling, and GetValidationOptionsFromPodSpecAndMeta has no update-mode allowance for previously-set mountOptions.
So disabling the gate can make API updates to existing pods/templates that still contain mountOptions fail.

}
}
return allErrs
}
Expand Down
5 changes: 5 additions & 0 deletions pkg/apis/core/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions pkg/features/kube_features.go
Original file line number Diff line number Diff line change
Expand Up @@ -1081,6 +1081,13 @@ const (
// co-ordinate better with cluster-autoscaler for storage limits.
VolumeLimitScaling featuregate.Feature = "VolumeLimitScaling"

// owner: @nispriha
// kep: https://kep.k8s.io/5855
//
// Enables mount options (noexec, nodev, nosuid) on volumeMounts, passed
// through CRI to the container runtime.
VolumeMountOptions featuregate.Feature = "VolumeMountOptions"

// owner: @ksubrmnn
//
// Allows kube-proxy to create DSR loadbalancers for Windows
Expand Down Expand Up @@ -1907,6 +1914,10 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate
{Version: version.MustParse("1.35"), Default: false, PreRelease: featuregate.Alpha},
},

VolumeMountOptions: {
{Version: version.MustParse("1.37"), Default: false, PreRelease: featuregate.Alpha},
},

WinDSR: {
{Version: version.MustParse("1.14"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.33"), Default: true, PreRelease: featuregate.Beta},
Expand Down Expand Up @@ -2480,6 +2491,8 @@ var defaultKubernetesFeatureGateDependencies = map[featuregate.Feature][]feature

VolumeLimitScaling: {},

VolumeMountOptions: {},

WinDSR: {},

WinOverlay: {},
Expand Down
20 changes: 20 additions & 0 deletions pkg/generated/openapi/zz_generated.openapi.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions pkg/kubelet/container/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,9 @@ type Mount struct {
// ImageSubPath is set if an image volume sub path should get mounted. This
// field is only required if the above Image is set.
ImageSubPath string
// MountOptions specifies additional mount options (noexec, nodev, nosuid)
// to pass through CRI to the container runtime.
MountOptions []string
}

// ImageVolumes is a map of image specs by volume name.
Expand Down
1 change: 1 addition & 0 deletions pkg/kubelet/kubelet_pods.go
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,7 @@ func makeMounts(pod *v1.Pod, podDir string, container *v1.Container, hostName, h
RecursiveReadOnly: rro,
SELinuxRelabel: relabelVolume,
Propagation: propagation,
MountOptions: mount.MountOptions,
})
}
if mountEtcHostsFile {
Expand Down
2 changes: 2 additions & 0 deletions pkg/kubelet/kuberuntime/kuberuntime_container.go
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,7 @@ func (m *kubeGenericRuntimeManager) makeMounts(opts *kubecontainer.RunContainerO
RecursiveReadOnly: v.RecursiveReadOnly,
Image: v.Image,
ImageSubPath: v.ImageSubPath,
MountOptions: v.MountOptions,
}

volumeMounts = append(volumeMounts, mount)
Expand Down Expand Up @@ -759,6 +760,7 @@ func (m *kubeGenericRuntimeManager) toKubeContainerStatus(ctx context.Context, p
Propagation: mount.Propagation,
Image: mount.Image,
ImageSubPath: mount.ImageSubPath,
MountOptions: mount.MountOptions,
})
}
return cStatus
Expand Down
48 changes: 48 additions & 0 deletions staging/src/k8s.io/api/core/v1/generated.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions staging/src/k8s.io/api/core/v1/generated.proto

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions staging/src/k8s.io/api/core/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -2413,6 +2413,16 @@ type VolumeMount struct {
// SubPathExpr and SubPath are mutually exclusive.
// +optional
SubPathExpr string `json:"subPathExpr,omitempty" protobuf:"bytes,6,opt,name=subPathExpr"`
// mountOptions is a list of mount options (noexec, nodev, nosuid) to apply
// when mounting this volume into the container. These options are passed
// through CRI to the container runtime and enforced at the OS level.
// Only VFS-level bind mount flags are permitted; filesystem-specific
// options are not allowed.
// This is an alpha field and requires the VolumeMountOptions feature gate.
// +featureGate=VolumeMountOptions
// +optional
// +listType=atomic
MountOptions []string `json:"mountOptions,omitempty" protobuf:"bytes,8,rep,name=mountOptions"`
}

// MountPropagationMode describes mount propagation.
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions staging/src/k8s.io/api/core/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 12 additions & 3 deletions staging/src/k8s.io/api/testdata/HEAD/apps.v1.DaemonSet.json
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,10 @@
"mountPath": "mountPathValue",
"subPath": "subPathValue",
"mountPropagation": "mountPropagationValue",
"subPathExpr": "subPathExprValue"
"subPathExpr": "subPathExprValue",
"mountOptions": [
"mountOptionsValue"
]
}
],
"volumeDevices": [
Expand Down Expand Up @@ -929,7 +932,10 @@
"mountPath": "mountPathValue",
"subPath": "subPathValue",
"mountPropagation": "mountPropagationValue",
"subPathExpr": "subPathExprValue"
"subPathExpr": "subPathExprValue",
"mountOptions": [
"mountOptionsValue"
]
}
],
"volumeDevices": [
Expand Down Expand Up @@ -1243,7 +1249,10 @@
"mountPath": "mountPathValue",
"subPath": "subPathValue",
"mountPropagation": "mountPropagationValue",
"subPathExpr": "subPathExprValue"
"subPathExpr": "subPathExprValue",
"mountOptions": [
"mountOptionsValue"
]
}
],
"volumeDevices": [
Expand Down
12 changes: 9 additions & 3 deletions staging/src/k8s.io/api/testdata/HEAD/apps.v1.DaemonSet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,9 @@ spec:
- devicePath: devicePathValue
name: nameValue
volumeMounts:
- mountPath: mountPathValue
- mountOptions:
- mountOptionsValue
mountPath: mountPathValue
mountPropagation: mountPropagationValue
name: nameValue
readOnly: true
Expand Down Expand Up @@ -647,7 +649,9 @@ spec:
- devicePath: devicePathValue
name: nameValue
volumeMounts:
- mountPath: mountPathValue
- mountOptions:
- mountOptionsValue
mountPath: mountPathValue
mountPropagation: mountPropagationValue
name: nameValue
readOnly: true
Expand Down Expand Up @@ -877,7 +881,9 @@ spec:
- devicePath: devicePathValue
name: nameValue
volumeMounts:
- mountPath: mountPathValue
- mountOptions:
- mountOptionsValue
mountPath: mountPathValue
mountPropagation: mountPropagationValue
name: nameValue
readOnly: true
Expand Down
15 changes: 12 additions & 3 deletions staging/src/k8s.io/api/testdata/HEAD/apps.v1.Deployment.json
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,10 @@
"mountPath": "mountPathValue",
"subPath": "subPathValue",
"mountPropagation": "mountPropagationValue",
"subPathExpr": "subPathExprValue"
"subPathExpr": "subPathExprValue",
"mountOptions": [
"mountOptionsValue"
]
}
],
"volumeDevices": [
Expand Down Expand Up @@ -930,7 +933,10 @@
"mountPath": "mountPathValue",
"subPath": "subPathValue",
"mountPropagation": "mountPropagationValue",
"subPathExpr": "subPathExprValue"
"subPathExpr": "subPathExprValue",
"mountOptions": [
"mountOptionsValue"
]
}
],
"volumeDevices": [
Expand Down Expand Up @@ -1244,7 +1250,10 @@
"mountPath": "mountPathValue",
"subPath": "subPathValue",
"mountPropagation": "mountPropagationValue",
"subPathExpr": "subPathExprValue"
"subPathExpr": "subPathExprValue",
"mountOptions": [
"mountOptionsValue"
]
}
],
"volumeDevices": [
Expand Down
Loading