f49c88f1c4
Disables user.Lookup() and net.LookupHost() in the init() function on Windows. Any package that simply imports pkg/chrootarchive will panic on Windows Nano Server, due to missing netapi32.dll. While docker itself is not meant to run on Nano Server, binaries that may import this package and run on Nano server, will fail even if they don't really use any of the functionality in this package while running on Nano. Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
96 lines
3.2 KiB
Go
96 lines
3.2 KiB
Go
package chrootarchive // import "github.com/docker/docker/pkg/chrootarchive"
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/docker/docker/pkg/archive"
|
|
"github.com/docker/docker/pkg/idtools"
|
|
)
|
|
|
|
// NewArchiver returns a new Archiver which uses chrootarchive.Untar
|
|
func NewArchiver(idMapping idtools.IdentityMapping) *archive.Archiver {
|
|
return &archive.Archiver{
|
|
Untar: Untar,
|
|
IDMapping: idMapping,
|
|
}
|
|
}
|
|
|
|
// Untar reads a stream of bytes from `archive`, parses it as a tar archive,
|
|
// and unpacks it into the directory at `dest`.
|
|
// The archive may be compressed with one of the following algorithms:
|
|
// identity (uncompressed), gzip, bzip2, xz.
|
|
func Untar(tarArchive io.Reader, dest string, options *archive.TarOptions) error {
|
|
return untarHandler(tarArchive, dest, options, true, dest)
|
|
}
|
|
|
|
// UntarWithRoot is the same as `Untar`, but allows you to pass in a root directory
|
|
// The root directory is the directory that will be chrooted to.
|
|
// `dest` must be a path within `root`, if it is not an error will be returned.
|
|
//
|
|
// `root` should set to a directory which is not controlled by any potentially
|
|
// malicious process.
|
|
//
|
|
// This should be used to prevent a potential attacker from manipulating `dest`
|
|
// such that it would provide access to files outside of `dest` through things
|
|
// like symlinks. Normally `ResolveSymlinksInScope` would handle this, however
|
|
// sanitizing symlinks in this manner is inherrently racey:
|
|
// ref: CVE-2018-15664
|
|
func UntarWithRoot(tarArchive io.Reader, dest string, options *archive.TarOptions, root string) error {
|
|
return untarHandler(tarArchive, dest, options, true, root)
|
|
}
|
|
|
|
// UntarUncompressed reads a stream of bytes from `archive`, parses it as a tar archive,
|
|
// and unpacks it into the directory at `dest`.
|
|
// The archive must be an uncompressed stream.
|
|
func UntarUncompressed(tarArchive io.Reader, dest string, options *archive.TarOptions) error {
|
|
return untarHandler(tarArchive, dest, options, false, dest)
|
|
}
|
|
|
|
// Handler for teasing out the automatic decompression
|
|
func untarHandler(tarArchive io.Reader, dest string, options *archive.TarOptions, decompress bool, root string) error {
|
|
if tarArchive == nil {
|
|
return fmt.Errorf("Empty archive")
|
|
}
|
|
if options == nil {
|
|
options = &archive.TarOptions{}
|
|
}
|
|
if options.ExcludePatterns == nil {
|
|
options.ExcludePatterns = []string{}
|
|
}
|
|
|
|
// If dest is inside a root then directory is created within chroot by extractor.
|
|
// This case is only currently used by cp.
|
|
if dest == root {
|
|
rootIDs := options.IDMap.RootPair()
|
|
|
|
dest = filepath.Clean(dest)
|
|
if _, err := os.Stat(dest); os.IsNotExist(err) {
|
|
if err := idtools.MkdirAllAndChownNew(dest, 0755, rootIDs); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
r := io.NopCloser(tarArchive)
|
|
if decompress {
|
|
decompressedArchive, err := archive.DecompressStream(tarArchive)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer decompressedArchive.Close()
|
|
r = decompressedArchive
|
|
}
|
|
|
|
return invokeUnpack(r, dest, options, root)
|
|
}
|
|
|
|
// Tar tars the requested path while chrooted to the specified root.
|
|
func Tar(srcPath string, options *archive.TarOptions, root string) (io.ReadCloser, error) {
|
|
if options == nil {
|
|
options = &archive.TarOptions{}
|
|
}
|
|
return invokePack(srcPath, options, root)
|
|
}
|