2021-08-23 13:14:53 +00:00
|
|
|
//go:build !windows
|
2015-05-14 22:08:00 +00:00
|
|
|
|
2018-02-05 21:05:59 +00:00
|
|
|
package chrootarchive // import "github.com/docker/docker/pkg/chrootarchive"
|
2015-05-14 22:08:00 +00:00
|
|
|
|
|
|
|
import (
|
2015-06-01 23:42:27 +00:00
|
|
|
"io"
|
2023-01-18 13:59:46 +00:00
|
|
|
"net"
|
|
|
|
"os/user"
|
2019-05-30 18:15:09 +00:00
|
|
|
"path/filepath"
|
2019-05-30 21:55:52 +00:00
|
|
|
"strings"
|
2015-06-01 23:42:27 +00:00
|
|
|
|
|
|
|
"github.com/docker/docker/pkg/archive"
|
2019-05-30 21:55:52 +00:00
|
|
|
"github.com/pkg/errors"
|
2015-05-14 22:08:00 +00:00
|
|
|
)
|
|
|
|
|
2023-01-18 13:59:46 +00:00
|
|
|
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")
|
|
|
|
}
|
|
|
|
|
2019-05-30 18:15:09 +00:00
|
|
|
func invokeUnpack(decompressedArchive io.Reader, dest string, options *archive.TarOptions, root string) error {
|
2022-09-27 22:39:26 +00:00
|
|
|
relDest, err := resolvePathInChroot(root, dest)
|
2015-06-01 23:42:27 +00:00
|
|
|
if err != nil {
|
2022-09-27 22:39:26 +00:00
|
|
|
return err
|
2019-05-30 18:15:09 +00:00
|
|
|
}
|
|
|
|
|
2023-07-13 01:17:02 +00:00
|
|
|
return doUnpack(decompressedArchive, relDest, root, options)
|
2019-05-30 21:55:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func invokePack(srcPath string, options *archive.TarOptions, root string) (io.ReadCloser, error) {
|
2022-09-27 22:39:26 +00:00
|
|
|
relSrc, err := resolvePathInChroot(root, srcPath)
|
2019-05-30 21:55:52 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2022-09-27 22:39:26 +00:00
|
|
|
// make sure we didn't trim a trailing slash with the call to `resolvePathInChroot`
|
2019-05-30 21:55:52 +00:00
|
|
|
if strings.HasSuffix(srcPath, "/") && !strings.HasSuffix(relSrc, "/") {
|
|
|
|
relSrc += "/"
|
|
|
|
}
|
|
|
|
|
2023-07-13 01:17:02 +00:00
|
|
|
return doPack(relSrc, root, options)
|
2022-09-27 22:39:26 +00:00
|
|
|
}
|
2019-05-30 21:55:52 +00:00
|
|
|
|
2022-09-27 22:39:26 +00:00
|
|
|
// 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")
|
2019-05-30 21:55:52 +00:00
|
|
|
}
|
2022-09-27 22:39:26 +00:00
|
|
|
rel, err := filepath.Rel(root, path)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
if rel == "." {
|
|
|
|
rel = "/"
|
|
|
|
}
|
|
|
|
if rel[0] != '/' {
|
|
|
|
rel = "/" + rel
|
|
|
|
}
|
|
|
|
return rel, nil
|
2019-05-30 21:55:52 +00:00
|
|
|
}
|