@@ -801,54 +801,33 @@ func mknodDevice(dest string, node *devices.Device) error {
801
801
return os .Chown (dest , int (node .Uid ), int (node .Gid ))
802
802
}
803
803
804
- // Get the parent mount point of directory passed in as argument. Also return
805
- // optional fields.
806
- func getParentMount (rootfs string ) (string , string , error ) {
807
- mi , err := mountinfo .GetMounts (mountinfo .ParentsFilter (rootfs ))
808
- if err != nil {
809
- return "" , "" , err
810
- }
811
- if len (mi ) < 1 {
812
- return "" , "" , fmt .Errorf ("could not find parent mount of %s" , rootfs )
813
- }
814
-
815
- // find the longest mount point
816
- var idx , maxlen int
817
- for i := range mi {
818
- if len (mi [i ].Mountpoint ) > maxlen {
819
- maxlen = len (mi [i ].Mountpoint )
820
- idx = i
804
+ // rootfsParentMountPrivate ensures rootfs parent mount is private.
805
+ // This is needed for two reasons:
806
+ // - pivot_root() will fail if parent mount is shared;
807
+ // - when we bind mount rootfs, if its parent is not private, the new mount
808
+ // will propagate (leak!) to parent namespace and we don't want that.
809
+ func rootfsParentMountPrivate (path string ) error {
810
+ var err error
811
+ // Assuming path is absolute and clean (this is checked in
812
+ // libcontainer/validate). Any error other than EINVAL means we failed,
813
+ // and EINVAL means this is not a mount point, so traverse up until we
814
+ // find one.
815
+ for {
816
+ err = unix .Mount ("" , path , "" , unix .MS_PRIVATE , "" )
817
+ if err == nil {
818
+ return nil
821
819
}
822
- }
823
- return mi [idx ].Mountpoint , mi [idx ].Optional , nil
824
- }
825
-
826
- // Make parent mount private if it was shared
827
- func rootfsParentMountPrivate (rootfs string ) error {
828
- sharedMount := false
829
-
830
- parentMount , optionalOpts , err := getParentMount (rootfs )
831
- if err != nil {
832
- return err
833
- }
834
-
835
- optsSplit := strings .Split (optionalOpts , " " )
836
- for _ , opt := range optsSplit {
837
- if strings .HasPrefix (opt , "shared:" ) {
838
- sharedMount = true
820
+ if err != unix .EINVAL || path == "/" { //nolint:errorlint // unix errors are bare
839
821
break
840
822
}
823
+ path = filepath .Dir (path )
841
824
}
842
-
843
- // Make parent mount PRIVATE if it was shared. It is needed for two
844
- // reasons. First of all pivot_root() will fail if parent mount is
845
- // shared. Secondly when we bind mount rootfs it will propagate to
846
- // parent namespace and we don't want that to happen.
847
- if sharedMount {
848
- return mount ("" , parentMount , "" , "" , unix .MS_PRIVATE , "" )
825
+ return & mountError {
826
+ op : "remount-private" ,
827
+ target : path ,
828
+ flags : unix .MS_PRIVATE ,
829
+ err : err ,
849
830
}
850
-
851
- return nil
852
831
}
853
832
854
833
func prepareRoot (config * configs.Config ) error {
@@ -860,9 +839,6 @@ func prepareRoot(config *configs.Config) error {
860
839
return err
861
840
}
862
841
863
- // Make parent mount private to make sure following bind mount does
864
- // not propagate in other namespaces. Also it will help with kernel
865
- // check pass in pivot_root. (IS_SHARED(new_mnt->mnt_parent))
866
842
if err := rootfsParentMountPrivate (config .Rootfs ); err != nil {
867
843
return err
868
844
}
0 commit comments