github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/pkg/chrootarchive/chroot_linux.go (about)

     1  package chrootarchive // import "github.com/docker/docker/pkg/chrootarchive"
     2  
     3  import (
     4  	"github.com/docker/docker/internal/mounttree"
     5  	"github.com/docker/docker/internal/unshare"
     6  	"github.com/moby/sys/mount"
     7  	"golang.org/x/sys/unix"
     8  )
     9  
    10  // goInChroot starts fn in a goroutine where the root directory, current working
    11  // directory and umask are unshared from other goroutines and the root directory
    12  // has been changed to path. These changes are only visible to the goroutine in
    13  // which fn is executed. Any other goroutines, including ones started from fn,
    14  // will see the same root directory and file system attributes as the rest of
    15  // the process.
    16  func goInChroot(path string, fn func()) error {
    17  	return unshare.Go(
    18  		unix.CLONE_FS|unix.CLONE_NEWNS,
    19  		func() error {
    20  			// Make everything in new ns slave.
    21  			// Don't use `private` here as this could race where the mountns gets a
    22  			//   reference to a mount and an unmount from the host does not propagate,
    23  			//   which could potentially cause transient errors for other operations,
    24  			//   even though this should be relatively small window here `slave` should
    25  			//   not cause any problems.
    26  			if err := mount.MakeRSlave("/"); err != nil {
    27  				return err
    28  			}
    29  
    30  			return mounttree.SwitchRoot(path)
    31  		},
    32  		fn,
    33  	)
    34  }