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