@@ -20,8 +20,8 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
@@ -627,7 +627,10 @@ func validateHostPathVolumeSource(hostPath *api.HostPathVolumeSource, fldPath *f
|
||||
allErrs := field.ErrorList{}
|
||||
if len(hostPath.Path) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("path"), ""))
|
||||
return allErrs
|
||||
}
|
||||
|
||||
allErrs = append(allErrs, validatePathNoBacksteps(hostPath.Path, fldPath.Child("path"))...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
@@ -958,8 +961,18 @@ func validateLocalDescendingPath(targetPath string, fldPath *field.Path) field.E
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, targetPath, "must be a relative path"))
|
||||
}
|
||||
|
||||
// TODO: this assumes the OS of apiserver & nodes are the same
|
||||
parts := strings.Split(targetPath, string(os.PathSeparator))
|
||||
allErrs = append(allErrs, validatePathNoBacksteps(targetPath, fldPath)...)
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// validatePathNoBacksteps makes sure the targetPath does not have any `..` path elements when split
|
||||
//
|
||||
// This assumes the OS of the apiserver and the nodes are the same. The same check should be done
|
||||
// on the node to ensure there are no backsteps.
|
||||
func validatePathNoBacksteps(targetPath string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
parts := strings.Split(filepath.ToSlash(targetPath), "/")
|
||||
for _, item := range parts {
|
||||
if item == ".." {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, targetPath, "must not contain '..'"))
|
||||
|
||||
@@ -268,6 +268,19 @@ func TestValidatePersistentVolumes(t *testing.T) {
|
||||
StorageClassName: "test-storage-class",
|
||||
}),
|
||||
},
|
||||
"bad-hostpath-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{
|
||||
HostPath: &api.HostPathVolumeSource{Path: "/foo/.."},
|
||||
},
|
||||
StorageClassName: "backstep-hostpath",
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
||||
for name, scenario := range scenarios {
|
||||
@@ -1102,6 +1115,20 @@ func TestValidateVolumes(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid HostPath backsteps",
|
||||
vol: api.Volume{
|
||||
Name: "hostpath",
|
||||
VolumeSource: api.VolumeSource{
|
||||
HostPath: &api.HostPathVolumeSource{
|
||||
Path: "/mnt/path/..",
|
||||
},
|
||||
},
|
||||
},
|
||||
errtype: field.ErrorTypeInvalid,
|
||||
errfield: "path",
|
||||
errdetail: "must not contain '..'",
|
||||
},
|
||||
// GcePersistentDisk
|
||||
{
|
||||
name: "valid GcePersistentDisk",
|
||||
|
||||
Reference in New Issue
Block a user