chroot_linux.go 1.2 KB

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