@@ -577,17 +577,17 @@ func validateGIDMappings(spec *rspec.Spec) error {
577577 return validateIDMappings (spec .Linux .GIDMappings , "/proc/self/gid_map" , "linux.gidMappings" )
578578}
579579
580- func mountMatch (specMount rspec.Mount , sysMount rspec.Mount ) error {
581- if filepath .Clean (specMount .Destination ) != sysMount .Destination {
582- return fmt .Errorf ("mount destination expected: %v, actual: %v" , specMount .Destination , sysMount .Destination )
580+ func mountMatch (configMount rspec.Mount , sysMount rspec.Mount ) error {
581+ if filepath .Clean (configMount .Destination ) != sysMount .Destination {
582+ return fmt .Errorf ("mount destination expected: %v, actual: %v" , configMount .Destination , sysMount .Destination )
583583 }
584584
585- if specMount .Type != sysMount .Type {
586- return fmt .Errorf ("mount %v type expected: %v, actual: %v" , specMount .Destination , specMount .Type , sysMount .Type )
585+ if configMount .Type != sysMount .Type {
586+ return fmt .Errorf ("mount %v type expected: %v, actual: %v" , configMount .Destination , configMount .Type , sysMount .Type )
587587 }
588588
589- if filepath .Clean (specMount .Source ) != sysMount .Source {
590- return fmt .Errorf ("mount %v source expected: %v, actual: %v" , specMount .Destination , specMount .Source , sysMount .Source )
589+ if filepath .Clean (configMount .Source ) != sysMount .Source {
590+ return fmt .Errorf ("mount %v source expected: %v, actual: %v" , configMount .Destination , configMount .Source , sysMount .Source )
591591 }
592592
593593 return nil
@@ -609,21 +609,77 @@ func validateMountsExist(spec *rspec.Spec) error {
609609 mountsMap [mountInfo .Mountpoint ] = append (mountsMap [mountInfo .Mountpoint ], m )
610610 }
611611
612- for _ , specMount := range spec .Mounts {
613- if specMount .Type == "bind" || specMount .Type == "rbind" {
612+ for _ , configMount := range spec .Mounts {
613+ if configMount .Type == "bind" || configMount .Type == "rbind" {
614614 // TODO: add bind or rbind check.
615615 continue
616616 }
617617
618618 found := false
619- for _ , sysMount := range mountsMap [filepath .Clean (specMount .Destination )] {
620- if err := mountMatch (specMount , sysMount ); err == nil {
619+ for _ , sysMount := range mountsMap [filepath .Clean (configMount .Destination )] {
620+ if err := mountMatch (configMount , sysMount ); err == nil {
621621 found = true
622622 break
623623 }
624624 }
625625 if ! found {
626- return fmt .Errorf ("Expected mount %v does not exist" , specMount )
626+ return fmt .Errorf ("Expected mount %v does not exist" , configMount )
627+ }
628+ }
629+
630+ return nil
631+ }
632+
633+ func validateMountsOrder (spec * rspec.Spec ) error {
634+ if runtime .GOOS == "windows" {
635+ logrus .Warnf ("mounts order validation not yet implemented for OS %q" , runtime .GOOS )
636+ return nil
637+ }
638+
639+ mountInfos , err := mount .GetMounts ()
640+ if err != nil {
641+ return err
642+ }
643+
644+ type mountOrder struct {
645+ Order int
646+ Root string
647+ Dest string
648+ Source string
649+ }
650+ mountsMap := make (map [string ][]mountOrder )
651+ for i , mountInfo := range mountInfos {
652+ m := mountOrder {
653+ Order : i ,
654+ Root : mountInfo .Root ,
655+ Dest : mountInfo .Mountpoint ,
656+ Source : mountInfo .Source ,
657+ }
658+ mountsMap [mountInfo .Mountpoint ] = append (mountsMap [mountInfo .Mountpoint ], m )
659+ }
660+ current := - 1
661+ for i , configMount := range spec .Mounts {
662+ mounts := mountsMap [configMount .Destination ]
663+ if len (mounts ) == 0 {
664+ return fmt .Errorf ("Mounts[%d] %s is not mounted in order" , i , configMount .Destination )
665+ }
666+ for j , mount := range mounts {
667+ source := mount .Source
668+ for _ , option := range configMount .Options {
669+ if option == "bind" || option == "rbind" {
670+ source = mount .Root
671+ break
672+ }
673+ }
674+ if source == configMount .Source {
675+ if current > mount .Order {
676+ return fmt .Errorf ("Mounts[%d] %s is not mounted in order" , i , configMount .Destination )
677+ }
678+ current = mount .Order
679+ // in order to deal with dup mount elements
680+ mountsMap [configMount .Destination ] = append (mountsMap [configMount .Destination ][:j ], mountsMap [configMount .Destination ][j + 1 :]... )
681+ break
682+ }
627683 }
628684 }
629685
@@ -659,6 +715,10 @@ func run(context *cli.Context) error {
659715 test : validateMountsExist ,
660716 description : "mounts" ,
661717 },
718+ {
719+ test : validateMountsOrder ,
720+ description : "mounts order" ,
721+ },
662722 }
663723
664724 linuxValidations := []validation {
0 commit comments