Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
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