archive_unix.go 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. //go:build !windows
  2. package chrootarchive // import "github.com/docker/docker/pkg/chrootarchive"
  3. import (
  4. "io"
  5. "net"
  6. "os/user"
  7. "path/filepath"
  8. "strings"
  9. "github.com/docker/docker/pkg/archive"
  10. "github.com/pkg/errors"
  11. )
  12. func init() {
  13. // initialize nss libraries in Glibc so that the dynamic libraries are loaded in the host
  14. // environment not in the chroot from untrusted files.
  15. _, _ = user.Lookup("docker")
  16. _, _ = net.LookupHost("localhost")
  17. }
  18. func invokeUnpack(decompressedArchive io.Reader, dest string, options *archive.TarOptions, root string) error {
  19. relDest, err := resolvePathInChroot(root, dest)
  20. if err != nil {
  21. return err
  22. }
  23. return doUnpack(decompressedArchive, relDest, root, options)
  24. }
  25. func invokePack(srcPath string, options *archive.TarOptions, root string) (io.ReadCloser, error) {
  26. relSrc, err := resolvePathInChroot(root, srcPath)
  27. if err != nil {
  28. return nil, err
  29. }
  30. // make sure we didn't trim a trailing slash with the call to `resolvePathInChroot`
  31. if strings.HasSuffix(srcPath, "/") && !strings.HasSuffix(relSrc, "/") {
  32. relSrc += "/"
  33. }
  34. return doPack(relSrc, root, options)
  35. }
  36. // resolvePathInChroot returns the equivalent to path inside a chroot rooted at root.
  37. // The returned path always begins with '/'.
  38. //
  39. // - resolvePathInChroot("/a/b", "/a/b/c/d") -> "/c/d"
  40. // - resolvePathInChroot("/a/b", "/a/b") -> "/"
  41. //
  42. // The implementation is buggy, and some bugs may be load-bearing.
  43. // Here be dragons.
  44. func resolvePathInChroot(root, path string) (string, error) {
  45. if root == "" {
  46. return "", errors.New("root path must not be empty")
  47. }
  48. rel, err := filepath.Rel(root, path)
  49. if err != nil {
  50. return "", err
  51. }
  52. if rel == "." {
  53. rel = "/"
  54. }
  55. if rel[0] != '/' {
  56. rel = "/" + rel
  57. }
  58. return rel, nil
  59. }