Explorar el Código

Merge pull request #5954 from vieux/fix_cp_error

Ignore lchown error on docker cp
unclejack hace 11 años
padre
commit
a94a87778c
Se han modificado 6 ficheros con 51 adiciones y 10 borrados
  1. 2 0
      Dockerfile
  2. 1 1
      api/client/commands.go
  3. 4 4
      archive/archive.go
  4. 3 2
      archive/archive_test.go
  5. 4 3
      archive/diff.go
  6. 37 0
      integration-cli/docker_cli_cp_test.go

+ 2 - 0
Dockerfile

@@ -91,6 +91,8 @@ RUN	git config --global user.email 'docker-dummy@example.com'
 
 # Add an unprivileged user to be used for tests which need it
 RUN adduser unprivilegeduser
+RUN groupadd docker
+RUN gpasswd -a unprivilegeduser docker
 
 VOLUME	/var/lib/docker
 WORKDIR	/go/src/github.com/dotcloud/docker

+ 1 - 1
api/client/commands.go

@@ -2058,7 +2058,7 @@ func (cli *DockerCli) CmdCp(args ...string) error {
 	}
 
 	if statusCode == 200 {
-		if err := archive.Untar(stream, copyData.Get("HostPath"), nil); err != nil {
+		if err := archive.Untar(stream, copyData.Get("HostPath"), &archive.TarOptions{NoLchown: true}); err != nil {
 			return err
 		}
 	}

+ 4 - 4
archive/archive.go

@@ -28,6 +28,7 @@ type (
 	TarOptions    struct {
 		Includes    []string
 		Compression Compression
+		NoLchown    bool
 	}
 )
 
@@ -179,7 +180,7 @@ func addTarFile(path, name string, tw *tar.Writer) error {
 	return nil
 }
 
-func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader) error {
+func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, Lchown bool) error {
 	// 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,
 	// so use hdrInfo.Mode() (they differ for e.g. setuid bits)
@@ -240,7 +241,7 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader) e
 		return fmt.Errorf("Unhandled tar header type %d\n", hdr.Typeflag)
 	}
 
-	if err := os.Lchown(path, hdr.Uid, hdr.Gid); err != nil {
+	if err := os.Lchown(path, hdr.Uid, hdr.Gid); err != nil && Lchown {
 		return err
 	}
 
@@ -415,8 +416,7 @@ func Untar(archive io.Reader, dest string, options *TarOptions) error {
 				}
 			}
 		}
-
-		if err := createTarFile(path, dest, hdr, tr); err != nil {
+		if err := createTarFile(path, dest, hdr, tr, options == nil || !options.NoLchown); err != nil {
 			return err
 		}
 

+ 3 - 2
archive/archive_test.go

@@ -3,7 +3,6 @@ package archive
 import (
 	"bytes"
 	"fmt"
-	"github.com/dotcloud/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
 	"io"
 	"io/ioutil"
 	"os"
@@ -11,6 +10,8 @@ import (
 	"path"
 	"testing"
 	"time"
+
+	"github.com/dotcloud/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
 )
 
 func TestCmdStreamLargeStderr(t *testing.T) {
@@ -132,7 +133,7 @@ func TestTarUntar(t *testing.T) {
 // Failing prevents the archives from being uncompressed during ADD
 func TestTypeXGlobalHeaderDoesNotFail(t *testing.T) {
 	hdr := tar.Header{Typeflag: tar.TypeXGlobalHeader}
-	err := createTarFile("pax_global_header", "some_dir", &hdr, nil)
+	err := createTarFile("pax_global_header", "some_dir", &hdr, nil, true)
 	if err != nil {
 		t.Fatal(err)
 	}

+ 4 - 3
archive/diff.go

@@ -2,13 +2,14 @@ package archive
 
 import (
 	"fmt"
-	"github.com/dotcloud/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
 	"io"
 	"io/ioutil"
 	"os"
 	"path/filepath"
 	"strings"
 	"syscall"
+
+	"github.com/dotcloud/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
 )
 
 // Linux device nodes are a bit weird due to backwards compat with 16 bit device nodes.
@@ -79,7 +80,7 @@ func ApplyLayer(dest string, layer ArchiveReader) error {
 					}
 					defer os.RemoveAll(aufsTempdir)
 				}
-				if err := createTarFile(filepath.Join(aufsTempdir, basename), dest, hdr, tr); err != nil {
+				if err := createTarFile(filepath.Join(aufsTempdir, basename), dest, hdr, tr, true); err != nil {
 					return err
 				}
 			}
@@ -126,7 +127,7 @@ func ApplyLayer(dest string, layer ArchiveReader) error {
 				srcData = tmpFile
 			}
 
-			if err := createTarFile(path, dest, srcHdr, srcData); err != nil {
+			if err := createTarFile(path, dest, srcHdr, srcData, true); err != nil {
 				return err
 			}
 

+ 37 - 0
integration-cli/docker_cli_cp_test.go

@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"io/ioutil"
 	"os"
+	"os/exec"
 	"path/filepath"
 	"testing"
 )
@@ -206,3 +207,39 @@ func TestCpAbsolutePath(t *testing.T) {
 
 	logDone("cp - absolute paths relative to container's rootfs")
 }
+
+// Check that cp with unprivileged user doesn't return any error
+func TestCpUnprivilegedUser(t *testing.T) {
+	out, exitCode, err := cmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "touch "+cpTestName)
+	if err != nil || exitCode != 0 {
+		t.Fatal("failed to create a container", out, err)
+	}
+
+	cleanedContainerID := stripTrailingCharacters(out)
+	defer deleteContainer(cleanedContainerID)
+
+	out, _, err = cmd(t, "wait", cleanedContainerID)
+	if err != nil || stripTrailingCharacters(out) != "0" {
+		t.Fatal("failed to set up container", out, err)
+	}
+
+	tmpdir, err := ioutil.TempDir("", "docker-integration")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	defer os.RemoveAll(tmpdir)
+
+	if err = os.Chmod(tmpdir, 0777); err != nil {
+		t.Fatal(err)
+	}
+
+	path := cpTestName
+
+	_, _, err = runCommandWithOutput(exec.Command("su", "unprivilegeduser", "-c", dockerBinary+" cp "+cleanedContainerID+":"+path+" "+tmpdir))
+	if err != nil {
+		t.Fatalf("couldn't copy with unprivileged user: %s:%s %s", cleanedContainerID, path, err)
+	}
+
+	logDone("cp - unprivileged user")
+}