From 5ba24629610c27f08b54ff4c1f000ad6d787c156 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Tue, 18 Feb 2014 09:53:30 +0100 Subject: [PATCH] archive: Fix the storing of setuid bits, etc In commit 3dfc910d7774d57c533b067fbe59d6b24dd803cd we changed from syscall.Chmod() to os.Chmod(), but these take a different form of the Mode argument. The sycall one takes the raw linux form, wheras os.Chmod takes the os.FileMode form, and they differ for the higher bits (setuid, setgid, etc). The raw tar header uses a form which is compatible with the syscalls, but not the go calls. We fix this by using hdr.FileInfo() which properly converts the mode to what go expects. Docker-DCO-1.1-Signed-off-by: Alexander Larsson (github: alexlarsson) --- archive/archive.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/archive/archive.go b/archive/archive.go index c0551d9fa3..16c01993b7 100644 --- a/archive/archive.go +++ b/archive/archive.go @@ -187,19 +187,24 @@ func addTarFile(path, name string, tw *tar.Writer) error { } func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader) 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) + hdrInfo := hdr.FileInfo() + switch hdr.Typeflag { case tar.TypeDir: // Create directory unless it exists as a directory already. // In that case we just want to merge the two if fi, err := os.Lstat(path); !(err == nil && fi.IsDir()) { - if err := os.Mkdir(path, os.FileMode(hdr.Mode)); err != nil { + if err := os.Mkdir(path, hdrInfo.Mode()); err != nil { return err } } case tar.TypeReg, tar.TypeRegA: // Source is regular file - file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, os.FileMode(hdr.Mode)) + file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, hdrInfo.Mode()) if err != nil { return err } @@ -249,7 +254,7 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader) e // There is no LChmod, so ignore mode for symlink. Also, this // must happen after chown, as that can modify the file mode if hdr.Typeflag != tar.TypeSymlink { - if err := os.Chmod(path, os.FileMode(hdr.Mode&07777)); err != nil { + if err := os.Chmod(path, hdrInfo.Mode()); err != nil { return err } }