Skip to content

Commit 4dcd484

Browse files
author
Ma Shimiao
committed
validate: add mounts whether nested check
Signed-off-by: Ma Shimiao <[email protected]>
1 parent 6bcd3b4 commit 4dcd484

File tree

1 file changed

+92
-7
lines changed

1 file changed

+92
-7
lines changed

validate/validate.go

Lines changed: 92 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"os"
1010
"path/filepath"
1111
"reflect"
12+
"regexp"
1213
"runtime"
1314
"strings"
1415
"unicode"
@@ -401,15 +402,40 @@ func (v *Validator) CheckMounts() (msgs []string) {
401402
return
402403
}
403404

404-
for _, mount := range v.spec.Mounts {
405-
if supportedTypes != nil {
406-
if !supportedTypes[mount.Type] {
407-
msgs = append(msgs, fmt.Sprintf("Unsupported mount type %q", mount.Type))
405+
for i, mountA := range v.spec.Mounts {
406+
if supportedTypes != nil && !supportedTypes[mountA.Type] {
407+
msgs = append(msgs, fmt.Sprintf("Unsupported mount type %q", mountA.Type))
408+
}
409+
if v.platform == "windows" {
410+
if err := pathValid(v.platform, mountA.Destination); err != nil {
411+
msgs = append(msgs, err.Error())
412+
}
413+
if err := pathValid(v.platform, mountA.Source); err != nil {
414+
msgs = append(msgs, err.Error())
415+
}
416+
} else {
417+
if err := pathValid(v.platform, mountA.Destination); err != nil {
418+
msgs = append(msgs, err.Error())
408419
}
409420
}
410-
411-
if !filepath.IsAbs(mount.Destination) {
412-
msgs = append(msgs, fmt.Sprintf("destination %v is not an absolute path", mount.Destination))
421+
for j, mountB := range v.spec.Mounts {
422+
if i == j {
423+
continue
424+
}
425+
// whether B.Desination is nested within A.Destination
426+
nested, err := nestedValid(v.platform, mountA.Destination, mountB.Destination)
427+
if err != nil {
428+
msgs = append(msgs, err.Error())
429+
continue
430+
}
431+
if nested {
432+
if v.platform == "windows" && i < j {
433+
msgs = append(msgs, fmt.Sprintf("On Windows, %v nested within %v is forbidden", mountB.Destination, mountA.Destination))
434+
}
435+
if i > j {
436+
logrus.Warnf("%v will be covered by %v", mountB.Destination, mountA.Destination)
437+
}
438+
}
413439
}
414440
}
415441

@@ -708,6 +734,65 @@ func namespaceValid(ns rspec.LinuxNamespace) bool {
708734
return true
709735
}
710736

737+
func pathValid(os, path string) error {
738+
if os == "windows" {
739+
matched, err := regexp.MatchString("^[a-zA-Z]:(\\\\[^\\\\/<>|:*?\"]+)+$", path)
740+
if err != nil {
741+
return err
742+
}
743+
if !matched {
744+
return fmt.Errorf("invalid windows path %v", path)
745+
}
746+
return nil
747+
}
748+
if !filepath.IsAbs(path) {
749+
return fmt.Errorf("%v is not an absolute path", path)
750+
}
751+
return nil
752+
}
753+
754+
// Check whether pathB is nested whithin pathA
755+
func nestedValid(os, pathA, pathB string) (bool, error) {
756+
if pathA == pathB {
757+
return false, nil
758+
}
759+
if pathA == "/" && pathB != "" {
760+
return true, nil
761+
}
762+
763+
var sep string
764+
if os == "windows" {
765+
sep = "\\"
766+
} else {
767+
sep = "/"
768+
}
769+
770+
splitedPathA := strings.Split(filepath.Clean(pathA), sep)
771+
splitedPathB := strings.Split(filepath.Clean(pathB), sep)
772+
lenA := len(splitedPathA)
773+
lenB := len(splitedPathB)
774+
775+
if lenA > lenB {
776+
if (lenA - lenB) == 1 {
777+
// if pathA is longer but not end with separator
778+
if splitedPathA[lenA-1] != "" {
779+
return false, nil
780+
}
781+
splitedPathA = splitedPathA[:lenA-1]
782+
} else {
783+
return false, nil
784+
}
785+
}
786+
787+
for i, partA := range splitedPathA {
788+
if partA != splitedPathB[i] {
789+
return false, nil
790+
}
791+
}
792+
793+
return true, nil
794+
}
795+
711796
func deviceValid(d rspec.LinuxDevice) bool {
712797
switch d.Type {
713798
case "b", "c", "u":

0 commit comments

Comments
 (0)