1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283 |
- //go:build !windows
- // +build !windows
- package chrootarchive // import "github.com/docker/docker/pkg/chrootarchive"
- import (
- "io"
- "net"
- "os/user"
- "path/filepath"
- "strings"
- "github.com/docker/docker/pkg/archive"
- "github.com/pkg/errors"
- )
- func init() {
- // initialize nss libraries in Glibc so that the dynamic libraries are loaded in the host
- // environment not in the chroot from untrusted files.
- _, _ = user.Lookup("docker")
- _, _ = net.LookupHost("localhost")
- }
- func invokeUnpack(decompressedArchive io.Reader, dest string, options *archive.TarOptions, root string) error {
- relDest, err := resolvePathInChroot(root, dest)
- if err != nil {
- return err
- }
- done := make(chan error)
- err = goInChroot(root, func() { done <- archive.Unpack(decompressedArchive, relDest, options) })
- if err != nil {
- return err
- }
- return <-done
- }
- func invokePack(srcPath string, options *archive.TarOptions, root string) (io.ReadCloser, error) {
- relSrc, err := resolvePathInChroot(root, srcPath)
- if err != nil {
- return nil, err
- }
- // make sure we didn't trim a trailing slash with the call to `resolvePathInChroot`
- if strings.HasSuffix(srcPath, "/") && !strings.HasSuffix(relSrc, "/") {
- relSrc += "/"
- }
- tb, err := archive.NewTarballer(relSrc, options)
- if err != nil {
- return nil, errors.Wrap(err, "error processing tar file")
- }
- err = goInChroot(root, tb.Do)
- if err != nil {
- return nil, errors.Wrap(err, "could not chroot")
- }
- return tb.Reader(), nil
- }
- // resolvePathInChroot returns the equivalent to path inside a chroot rooted at root.
- // The returned path always begins with '/'.
- //
- // - resolvePathInChroot("/a/b", "/a/b/c/d") -> "/c/d"
- // - resolvePathInChroot("/a/b", "/a/b") -> "/"
- //
- // The implementation is buggy, and some bugs may be load-bearing.
- // Here be dragons.
- func resolvePathInChroot(root, path string) (string, error) {
- if root == "" {
- return "", errors.New("root path must not be empty")
- }
- rel, err := filepath.Rel(root, path)
- if err != nil {
- return "", err
- }
- if rel == "." {
- rel = "/"
- }
- if rel[0] != '/' {
- rel = "/" + rel
- }
- return rel, nil
- }
|