mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-21 19:01:49 +00:00
Merge pull request #47236 from dixudx/not_allow_backsteps_in_local_volume
Automatic merge from submit-queue (batch tested with PRs 34515, 47236, 46694, 47819, 47792) not allow backsteps in local volume plugin **Which issue this PR fixes** : fixes #47207 **Special notes for your reviewer**: cc @msau42 @ddysher Just follow @liggitt [commented](https://github.com/kubernetes/kubernetes/issues/47107#issuecomment-306831175). **Release note**: ```release-note NONE ```
This commit is contained in:
commit
1184ce869a
@ -1133,7 +1133,10 @@ func validateLocalVolumeSource(ls *api.LocalVolumeSource, fldPath *field.Path) f
|
|||||||
allErrs := field.ErrorList{}
|
allErrs := field.ErrorList{}
|
||||||
if ls.Path == "" {
|
if ls.Path == "" {
|
||||||
allErrs = append(allErrs, field.Required(fldPath.Child("path"), ""))
|
allErrs = append(allErrs, field.Required(fldPath.Child("path"), ""))
|
||||||
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allErrs = append(allErrs, validatePathNoBacksteps(ls.Path, fldPath.Child("path"))...)
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,6 +281,21 @@ func TestValidatePersistentVolumes(t *testing.T) {
|
|||||||
StorageClassName: "backstep-hostpath",
|
StorageClassName: "backstep-hostpath",
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
"bad-local-volume-backsteps": {
|
||||||
|
isExpectedFailure: true,
|
||||||
|
volume: testVolume("foo", "", api.PersistentVolumeSpec{
|
||||||
|
Capacity: api.ResourceList{
|
||||||
|
api.ResourceName(api.ResourceStorage): resource.MustParse("10G"),
|
||||||
|
},
|
||||||
|
AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce},
|
||||||
|
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||||
|
Local: &api.LocalVolumeSource{
|
||||||
|
Path: "/foo/..",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
StorageClassName: "backstep-local",
|
||||||
|
}),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, scenario := range scenarios {
|
for name, scenario := range scenarios {
|
||||||
|
@ -21,6 +21,7 @@ go_library(
|
|||||||
"//pkg/util/strings:go_default_library",
|
"//pkg/util/strings:go_default_library",
|
||||||
"//pkg/volume:go_default_library",
|
"//pkg/volume:go_default_library",
|
||||||
"//pkg/volume/util:go_default_library",
|
"//pkg/volume/util:go_default_library",
|
||||||
|
"//pkg/volume/validation:go_default_library",
|
||||||
"//vendor/github.com/golang/glog:go_default_library",
|
"//vendor/github.com/golang/glog:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||||
|
@ -29,6 +29,7 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/util/strings"
|
"k8s.io/kubernetes/pkg/util/strings"
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
"k8s.io/kubernetes/pkg/volume/util"
|
"k8s.io/kubernetes/pkg/volume/util"
|
||||||
|
"k8s.io/kubernetes/pkg/volume/validation"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is the primary entrypoint for volume plugins.
|
// This is the primary entrypoint for volume plugins.
|
||||||
@ -192,6 +193,11 @@ func (m *localVolumeMounter) SetUpAt(dir string, fsGroup *types.UnixGroupID) err
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err := validation.ValidatePathNoBacksteps(m.globalPath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid path: %s %v", m.globalPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
notMnt, err := m.mounter.IsLikelyNotMountPoint(dir)
|
notMnt, err := m.mounter.IsLikelyNotMountPoint(dir)
|
||||||
glog.V(4).Infof("LocalVolume mount setup: PodDir(%s) VolDir(%s) Mounted(%t) Error(%v), ReadOnly(%t)", dir, m.globalPath, !notMnt, err, m.readOnly)
|
glog.V(4).Infof("LocalVolume mount setup: PodDir(%s) VolDir(%s) Mounted(%t) Error(%v), ReadOnly(%t)", dir, m.globalPath, !notMnt, err, m.readOnly)
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
|
@ -75,7 +75,7 @@ func getPersistentPlugin(t *testing.T) (string, volume.PersistentVolumePlugin) {
|
|||||||
return tmpDir, plug
|
return tmpDir, plug
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTestVolume(readOnly bool) *volume.Spec {
|
func getTestVolume(readOnly bool, path string) *volume.Spec {
|
||||||
pv := &v1.PersistentVolume{
|
pv := &v1.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: testPVName,
|
Name: testPVName,
|
||||||
@ -83,7 +83,7 @@ func getTestVolume(readOnly bool) *volume.Spec {
|
|||||||
Spec: v1.PersistentVolumeSpec{
|
Spec: v1.PersistentVolumeSpec{
|
||||||
PersistentVolumeSource: v1.PersistentVolumeSource{
|
PersistentVolumeSource: v1.PersistentVolumeSource{
|
||||||
Local: &v1.LocalVolumeSource{
|
Local: &v1.LocalVolumeSource{
|
||||||
Path: "/test-vol",
|
Path: path,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -104,7 +104,7 @@ func TestCanSupport(t *testing.T) {
|
|||||||
tmpDir, plug := getPlugin(t)
|
tmpDir, plug := getPlugin(t)
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
if !plug.CanSupport(getTestVolume(false)) {
|
if !plug.CanSupport(getTestVolume(false, "/test-vol")) {
|
||||||
t.Errorf("Expected true")
|
t.Errorf("Expected true")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,7 +130,7 @@ func TestGetVolumeName(t *testing.T) {
|
|||||||
tmpDir, plug := getPersistentPlugin(t)
|
tmpDir, plug := getPersistentPlugin(t)
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
volName, err := plug.GetVolumeName(getTestVolume(false))
|
volName, err := plug.GetVolumeName(getTestVolume(false, "/test-vol"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to get volume name: %v", err)
|
t.Errorf("Failed to get volume name: %v", err)
|
||||||
}
|
}
|
||||||
@ -139,12 +139,29 @@ func TestGetVolumeName(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInvalidLocalPath(t *testing.T) {
|
||||||
|
tmpDir, plug := getPlugin(t)
|
||||||
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
|
pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: types.UID("poduid")}}
|
||||||
|
mounter, err := plug.NewMounter(getTestVolume(false, "/no/backsteps/allowed/.."), pod, volume.VolumeOptions{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = mounter.SetUp(nil)
|
||||||
|
expectedMsg := "invalid path: /no/backsteps/allowed/.. must not contain '..'"
|
||||||
|
if err.Error() != expectedMsg {
|
||||||
|
t.Fatalf("expected error `%s` but got `%s`", expectedMsg, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestMountUnmount(t *testing.T) {
|
func TestMountUnmount(t *testing.T) {
|
||||||
tmpDir, plug := getPlugin(t)
|
tmpDir, plug := getPlugin(t)
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: types.UID("poduid")}}
|
pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: types.UID("poduid")}}
|
||||||
mounter, err := plug.NewMounter(getTestVolume(false), pod, volume.VolumeOptions{})
|
mounter, err := plug.NewMounter(getTestVolume(false, "/test-vol"), pod, volume.VolumeOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to make a new Mounter: %v", err)
|
t.Errorf("Failed to make a new Mounter: %v", err)
|
||||||
}
|
}
|
||||||
@ -226,7 +243,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) {
|
|||||||
|
|
||||||
// Read only == true
|
// Read only == true
|
||||||
pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: types.UID("poduid")}}
|
pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: types.UID("poduid")}}
|
||||||
mounter, err := plug.NewMounter(getTestVolume(true), pod, volume.VolumeOptions{})
|
mounter, err := plug.NewMounter(getTestVolume(true, "/test-vol"), pod, volume.VolumeOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to make a new Mounter: %v", err)
|
t.Errorf("Failed to make a new Mounter: %v", err)
|
||||||
}
|
}
|
||||||
@ -238,7 +255,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read only == false
|
// Read only == false
|
||||||
mounter, err = plug.NewMounter(getTestVolume(false), pod, volume.VolumeOptions{})
|
mounter, err = plug.NewMounter(getTestVolume(false, "/test-vol"), pod, volume.VolumeOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to make a new Mounter: %v", err)
|
t.Errorf("Failed to make a new Mounter: %v", err)
|
||||||
}
|
}
|
||||||
@ -259,7 +276,7 @@ func TestUnsupportedPlugins(t *testing.T) {
|
|||||||
|
|
||||||
plugMgr := volume.VolumePluginMgr{}
|
plugMgr := volume.VolumePluginMgr{}
|
||||||
plugMgr.InitPlugins(ProbeVolumePlugins(), volumetest.NewFakeVolumeHost(tmpDir, nil, nil))
|
plugMgr.InitPlugins(ProbeVolumePlugins(), volumetest.NewFakeVolumeHost(tmpDir, nil, nil))
|
||||||
spec := getTestVolume(false)
|
spec := getTestVolume(false, "/test-vol")
|
||||||
|
|
||||||
recyclePlug, err := plugMgr.FindRecyclablePluginBySpec(spec)
|
recyclePlug, err := plugMgr.FindRecyclablePluginBySpec(spec)
|
||||||
if err == nil && recyclePlug != nil {
|
if err == nil && recyclePlug != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user