Merge pull request #11099 from iavael/bugfix/tar-symlinks

Fixed handling hardlinks to symlinks in tar stream
This commit is contained in:
Vincent Batts 2015-04-01 18:34:00 -04:00
commit 88b8fc10e3
2 changed files with 42 additions and 2 deletions

View file

@ -350,7 +350,13 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, L
// 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 hdr.Typeflag == tar.TypeLink {
if fi, err := os.Lstat(hdr.Linkname); err == nil && (fi.Mode()&os.ModeSymlink == 0) {
if err := os.Chmod(path, hdrInfo.Mode()); err != nil {
return err
}
}
} else if hdr.Typeflag != tar.TypeSymlink {
if err := os.Chmod(path, hdrInfo.Mode()); err != nil {
return err
}
@ -358,7 +364,13 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, L
ts := []syscall.Timespec{timeToTimespec(hdr.AccessTime), timeToTimespec(hdr.ModTime)}
// syscall.UtimesNano doesn't support a NOFOLLOW flag atm, and
if hdr.Typeflag != tar.TypeSymlink {
if hdr.Typeflag == tar.TypeLink {
if fi, err := os.Lstat(hdr.Linkname); err == nil && (fi.Mode()&os.ModeSymlink == 0) {
if err := system.UtimesNano(path, ts); err != nil && err != system.ErrNotSupportedPlatform {
return err
}
}
} else if hdr.Typeflag != tar.TypeSymlink {
if err := system.UtimesNano(path, ts); err != nil && err != system.ErrNotSupportedPlatform {
return err
}

View file

@ -435,6 +435,34 @@ func TestUntarInvalidFilenames(t *testing.T) {
}
}
func TestUntarHardlinkToSymlink(t *testing.T) {
for i, headers := range [][]*tar.Header{
{
{
Name: "symlink1",
Typeflag: tar.TypeSymlink,
Linkname: "regfile",
Mode: 0644,
},
{
Name: "symlink2",
Typeflag: tar.TypeLink,
Linkname: "symlink1",
Mode: 0644,
},
{
Name: "regfile",
Typeflag: tar.TypeReg,
Mode: 0644,
},
},
} {
if err := testBreakout("untar", "docker-TestUntarHardlinkToSymlink", headers); err != nil {
t.Fatalf("i=%d. %v", i, err)
}
}
}
func TestUntarInvalidHardlink(t *testing.T) {
for i, headers := range [][]*tar.Header{
{ // try reading victim/hello (../)