@@ -982,54 +982,33 @@ func mknodDevice(dest string, node *devices.Device) error {
982
982
return os .Chown (dest , int (node .Uid ), int (node .Gid ))
983
983
}
984
984
985
- // Get the parent mount point of directory passed in as argument. Also return
986
- // optional fields.
987
- func getParentMount (rootfs string ) (string , string , error ) {
988
- mi , err := mountinfo .GetMounts (mountinfo .ParentsFilter (rootfs ))
989
- if err != nil {
990
- return "" , "" , err
991
- }
992
- if len (mi ) < 1 {
993
- return "" , "" , fmt .Errorf ("could not find parent mount of %s" , rootfs )
994
- }
995
-
996
- // find the longest mount point
997
- var idx , maxlen int
998
- for i := range mi {
999
- if len (mi [i ].Mountpoint ) > maxlen {
1000
- maxlen = len (mi [i ].Mountpoint )
1001
- idx = i
985
+ // rootfsParentMountPrivate ensures rootfs parent mount is private.
986
+ // This is needed for two reasons:
987
+ // - pivot_root() will fail if parent mount is shared;
988
+ // - when we bind mount rootfs, if its parent is not private, the new mount
989
+ // will propagate (leak!) to parent namespace and we don't want that.
990
+ func rootfsParentMountPrivate (path string ) error {
991
+ var err error
992
+ // Assuming path is absolute and clean (this is checked in
993
+ // libcontainer/validate). Any error other than EINVAL means we failed,
994
+ // and EINVAL means this is not a mount point, so traverse up until we
995
+ // find one.
996
+ for {
997
+ err = unix .Mount ("" , path , "" , unix .MS_PRIVATE , "" )
998
+ if err == nil {
999
+ return nil
1002
1000
}
1003
- }
1004
- return mi [idx ].Mountpoint , mi [idx ].Optional , nil
1005
- }
1006
-
1007
- // Make parent mount private if it was shared
1008
- func rootfsParentMountPrivate (rootfs string ) error {
1009
- sharedMount := false
1010
-
1011
- parentMount , optionalOpts , err := getParentMount (rootfs )
1012
- if err != nil {
1013
- return err
1014
- }
1015
-
1016
- optsSplit := strings .Split (optionalOpts , " " )
1017
- for _ , opt := range optsSplit {
1018
- if strings .HasPrefix (opt , "shared:" ) {
1019
- sharedMount = true
1001
+ if err != unix .EINVAL || path == "/" { //nolint:errorlint // unix errors are bare
1020
1002
break
1021
1003
}
1004
+ path = filepath .Dir (path )
1022
1005
}
1023
-
1024
- // Make parent mount PRIVATE if it was shared. It is needed for two
1025
- // reasons. First of all pivot_root() will fail if parent mount is
1026
- // shared. Secondly when we bind mount rootfs it will propagate to
1027
- // parent namespace and we don't want that to happen.
1028
- if sharedMount {
1029
- return mount ("" , parentMount , "" , unix .MS_PRIVATE , "" )
1006
+ return & mountError {
1007
+ op : "remount-private" ,
1008
+ target : path ,
1009
+ flags : unix .MS_PRIVATE ,
1010
+ err : err ,
1030
1011
}
1031
-
1032
- return nil
1033
1012
}
1034
1013
1035
1014
func prepareRoot (config * configs.Config ) error {
@@ -1041,9 +1020,6 @@ func prepareRoot(config *configs.Config) error {
1041
1020
return err
1042
1021
}
1043
1022
1044
- // Make parent mount private to make sure following bind mount does
1045
- // not propagate in other namespaces. Also it will help with kernel
1046
- // check pass in pivot_root. (IS_SHARED(new_mnt->mnt_parent))
1047
1023
if err := rootfsParentMountPrivate (config .Rootfs ); err != nil {
1048
1024
return err
1049
1025
}
0 commit comments