1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Don't create devices if in a user namespace

If we are running in a user namespace, don't try to mknod as
it won't be allowed.  libcontainer will bind-mount the host's
devices over files in the container anyway, so it's not needed.

The chrootarchive package does a chroot (without mounting /proc) before
its work, so we cannot check /proc/self/uid_map when we need to.  So
compute it in advance and pass it along with the tar options.

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
This commit is contained in:
Serge Hallyn 2016-02-12 16:05:50 -08:00 committed by Phil Estes
parent 838db8852c
commit 617c352e92
6 changed files with 36 additions and 6 deletions

View file

@ -11,6 +11,7 @@ import (
"github.com/docker/docker/pkg/pools" "github.com/docker/docker/pkg/pools"
"github.com/docker/docker/pkg/system" "github.com/docker/docker/pkg/system"
rsystem "github.com/opencontainers/runc/libcontainer/system"
) )
type copyFlags int type copyFlags int
@ -105,6 +106,10 @@ func copyDir(srcDir, dstDir string, flags copyFlags) error {
case os.ModeNamedPipe: case os.ModeNamedPipe:
fallthrough fallthrough
case os.ModeSocket: case os.ModeSocket:
if rsystem.RunningInUserNS() {
// cannot create a device if running in user namespace
return nil
}
if err := syscall.Mkfifo(dstPath, stat.Mode); err != nil { if err := syscall.Mkfifo(dstPath, stat.Mode); err != nil {
return err return err
} }

View file

@ -59,6 +59,7 @@ type (
// For each include when creating an archive, the included name will be // For each include when creating an archive, the included name will be
// replaced with the matching name from this map. // replaced with the matching name from this map.
RebaseNames map[string]string RebaseNames map[string]string
InUserNS bool
} }
// Archiver allows the reuse of most utility functions of this package // Archiver allows the reuse of most utility functions of this package
@ -381,7 +382,7 @@ func (ta *tarAppender) addTarFile(path, name string) error {
return nil return nil
} }
func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, Lchown bool, chownOpts *TarChownOptions) error { func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, Lchown bool, chownOpts *TarChownOptions, inUserns bool) error {
// hdr.Mode is in linux format, which we can use for sycalls, // hdr.Mode is in linux format, which we can use for sycalls,
// but for os.Foo() calls we need the mode converted to os.FileMode, // but for os.Foo() calls we need the mode converted to os.FileMode,
// so use hdrInfo.Mode() (they differ for e.g. setuid bits) // so use hdrInfo.Mode() (they differ for e.g. setuid bits)
@ -409,7 +410,16 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, L
} }
file.Close() file.Close()
case tar.TypeBlock, tar.TypeChar, tar.TypeFifo: case tar.TypeBlock, tar.TypeChar:
if inUserns { // cannot create devices in a userns
return nil
}
// Handle this is an OS-specific way
if err := handleTarTypeBlockCharFifo(hdr, path); err != nil {
return err
}
case tar.TypeFifo:
// Handle this is an OS-specific way // Handle this is an OS-specific way
if err := handleTarTypeBlockCharFifo(hdr, path); err != nil { if err := handleTarTypeBlockCharFifo(hdr, path); err != nil {
return err return err
@ -817,7 +827,7 @@ loop:
} }
} }
if err := createTarFile(path, dest, hdr, trBuf, !options.NoLchown, options.ChownOpts); err != nil { if err := createTarFile(path, dest, hdr, trBuf, !options.NoLchown, options.ChownOpts, options.InUserNS); err != nil {
return err return err
} }

View file

@ -802,7 +802,7 @@ func TestTypeXGlobalHeaderDoesNotFail(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
err = createTarFile(filepath.Join(tmpDir, "pax_global_header"), tmpDir, &hdr, nil, true, nil) err = createTarFile(filepath.Join(tmpDir, "pax_global_header"), tmpDir, &hdr, nil, true, nil, false)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -10,6 +10,7 @@ import (
"syscall" "syscall"
"github.com/docker/docker/pkg/system" "github.com/docker/docker/pkg/system"
rsystem "github.com/opencontainers/runc/libcontainer/system"
) )
// fixVolumePathPrefix does platform specific processing to ensure that if // fixVolumePathPrefix does platform specific processing to ensure that if
@ -80,6 +81,11 @@ func minor(device uint64) uint64 {
// handleTarTypeBlockCharFifo is an OS-specific helper function used by // handleTarTypeBlockCharFifo is an OS-specific helper function used by
// createTarFile to handle the following types of header: Block; Char; Fifo // createTarFile to handle the following types of header: Block; Char; Fifo
func handleTarTypeBlockCharFifo(hdr *tar.Header, path string) error { func handleTarTypeBlockCharFifo(hdr *tar.Header, path string) error {
if rsystem.RunningInUserNS() {
// cannot create a device if running in user namespace
return nil
}
mode := uint32(hdr.Mode & 07777) mode := uint32(hdr.Mode & 07777)
switch hdr.Typeflag { switch hdr.Typeflag {
case tar.TypeBlock: case tar.TypeBlock:

View file

@ -111,7 +111,7 @@ func UnpackLayer(dest string, layer Reader, options *TarOptions) (size int64, er
} }
defer os.RemoveAll(aufsTempdir) defer os.RemoveAll(aufsTempdir)
} }
if err := createTarFile(filepath.Join(aufsTempdir, basename), dest, hdr, tr, true, nil); err != nil { if err := createTarFile(filepath.Join(aufsTempdir, basename), dest, hdr, tr, true, nil, options.InUserNS); err != nil {
return 0, err return 0, err
} }
} }
@ -219,7 +219,7 @@ func UnpackLayer(dest string, layer Reader, options *TarOptions) (size int64, er
} }
srcHdr.Gid = xGID srcHdr.Gid = xGID
} }
if err := createTarFile(path, dest, srcHdr, srcData, true, nil); err != nil { if err := createTarFile(path, dest, srcHdr, srcData, true, nil, options.InUserNS); err != nil {
return 0, err return 0, err
} }

View file

@ -15,6 +15,7 @@ import (
"github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/reexec" "github.com/docker/docker/pkg/reexec"
"github.com/docker/docker/pkg/system" "github.com/docker/docker/pkg/system"
rsystem "github.com/opencontainers/runc/libcontainer/system"
) )
type applyLayerResponse struct { type applyLayerResponse struct {
@ -34,6 +35,7 @@ func applyLayer() {
runtime.LockOSThread() runtime.LockOSThread()
flag.Parse() flag.Parse()
inUserns := rsystem.RunningInUserNS()
if err := chroot(flag.Arg(0)); err != nil { if err := chroot(flag.Arg(0)); err != nil {
fatal(err) fatal(err)
} }
@ -49,6 +51,10 @@ func applyLayer() {
fatal(err) fatal(err)
} }
if inUserns {
options.InUserNS = true
}
if tmpDir, err = ioutil.TempDir("/", "temp-docker-extract"); err != nil { if tmpDir, err = ioutil.TempDir("/", "temp-docker-extract"); err != nil {
fatal(err) fatal(err)
} }
@ -88,6 +94,9 @@ func applyLayerHandler(dest string, layer archive.Reader, options *archive.TarOp
} }
if options == nil { if options == nil {
options = &archive.TarOptions{} options = &archive.TarOptions{}
if rsystem.RunningInUserNS() {
options.InUserNS = true
}
} }
if options.ExcludePatterns == nil { if options.ExcludePatterns == nil {
options.ExcludePatterns = []string{} options.ExcludePatterns = []string{}