Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docker cp archive/tar error with filenames greater than 100 characters #484

Closed
2 of 3 tasks
mkozell opened this issue Nov 13, 2018 · 6 comments
Closed
2 of 3 tasks
Labels

Comments

@mkozell
Copy link

mkozell commented Nov 13, 2018

  • This is a bug report
  • This is a feature request
  • I searched existing issues before opening this one

Expected behavior

Using docker cp should copy files and directories from container to host with filenames greater than 100 characters for Docker version 18.06.1-ce and higher.

Actual behavior

Using docker cp container_name:/etc/resolv.conf a_very_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_long_filename_that_is_101_characters in 18.03.1-ce works but results in the error below on 18.06.1-ce and higher.

archive/tar: cannot encode header: Format specifies USTAR; and USTAR cannot encode Name="a_very_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_long_filename_that_is_101_characters"

Steps to reproduce the behavior

Output of docker version:

Server:
 Engine:
  Version:          18.06.1-ce
  API version:      1.38 (minimum version 1.12)
  Go version:       go1.10.3
  
Server:
 Engine:
  Version:      18.03.1-ce
  API version:  1.37 (minimum version 1.12)
  Go version:   go1.9.5

Additional environment details (AWS, VirtualBox, physical, etc.)

I was able to reproduce the issue in Docker 18.06.1-ce and 18.09.0-ce but not in Docker 18.03.1-ce. The commands below can reproduce the issue. I reproduced the issue using CentOS 7.5 and Amazon Linux 2 hosts. I then used Vagrant to confirm the issue locally.

docker pull centos:7
docker run -d -i --name docker_test centos:7
docker cp docker_test:/etc/resolv.conf a_very_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_long_filename_that_is_100_characters
docker cp docker_test:/etc/resolv.conf a_very_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_long_filename_that_is_101_characters

It appears a change to Golang v1.10 may have changed the default archive/tar format to USTAR which has a 100 character Linkname limit.

https://golang.org/doc/go1.10#archive/tar
https://golang.org/pkg/archive/tar/#Format

@thaJeztah
Copy link
Member

ping @kolyshkin

@travisreed-wf
Copy link

I am running into this issue in 18.06.1-ce as well. I will downgrade to 18.03.1-ce but wanted to chime in that it is impacting us too.

@kolyshkin
Copy link

kolyshkin commented Jan 25, 2019

The problem is, docker daemon writes tar in PAX format, but since the reading side has to guess the format, and it mis-guesses it as USTAR. This issue is probably caused in archive/tar changes in Go 1.10 (docker 18.03 uses go-1.9.5, while 18.06 switched to go 1.10, which has many changes to archive/tar).

I have a fix in progress...

kolyshkin added a commit to kolyshkin/moby that referenced this issue Jan 25, 2019
As reported in docker/for-linux/issues/484, since Docker 18.06
docker cp with a destination file name fails with the following error:

> archive/tar: cannot encode header: Format specifies USTAR; and USTAR cannot encode Name="a_very_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_long_filename_that_is_101_characters"

The problem is caused by changes in Go 1.10 archive/tar, which
mis-guesses the tar stream format as USTAR (rather than PAX),
which, in turn, leads to inability to specify file names
longer than 100 characters.

This tar stream is sent by TarWithOptions() (which, since we switched to
Go 1.10, explicitly sets format=PAX for every file, see FileInfoHeader(),
and before Go 1.10 it was PAX by default). Unfortunately, the receiving
side, RebaseArchiveEntries(), which calls tar.Next(), mistakenly guesses
header format as USTAR, which leads to the above error.

The fix is easy: set the format to PAX in RebaseArchiveEntries()
where we read the tar stream and change the file name.

A unit test is added to prevent future regressions.

NOTE this code is not used by dockerd, but rather but docker cli
(also possibly other clients), so this needs to be re-vendored
to cli in order to take effect.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
@kolyshkin
Copy link

Proposed fix: moby/moby#38634 (note it needs to be merged to moby/moby first and then vendored to docker/cli in order to take effect).

docker-jenkins pushed a commit to docker-archive/docker-ce that referenced this issue Jan 31, 2019
As reported in docker/for-linux/issues/484, since Docker 18.06
docker cp with a destination file name fails with the following error:

> archive/tar: cannot encode header: Format specifies USTAR; and USTAR cannot encode Name="a_very_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_long_filename_that_is_101_characters"

The problem is caused by changes in Go 1.10 archive/tar, which
mis-guesses the tar stream format as USTAR (rather than PAX),
which, in turn, leads to inability to specify file names
longer than 100 characters.

This tar stream is sent by TarWithOptions() (which, since we switched to
Go 1.10, explicitly sets format=PAX for every file, see FileInfoHeader(),
and before Go 1.10 it was PAX by default). Unfortunately, the receiving
side, RebaseArchiveEntries(), which calls tar.Next(), mistakenly guesses
header format as USTAR, which leads to the above error.

The fix is easy: set the format to PAX in RebaseArchiveEntries()
where we read the tar stream and change the file name.

A unit test is added to prevent future regressions.

NOTE this code is not used by dockerd, but rather but docker cli
(also possibly other clients), so this needs to be re-vendored
to cli in order to take effect.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Upstream-commit: f55a4176febbd0dffd6e5eb65beb70bc32912d0b
Component: engine
thaJeztah pushed a commit to thaJeztah/docker that referenced this issue Mar 2, 2019
As reported in docker/for-linux/issues/484, since Docker 18.06
docker cp with a destination file name fails with the following error:

> archive/tar: cannot encode header: Format specifies USTAR; and USTAR cannot encode Name="a_very_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_long_filename_that_is_101_characters"

The problem is caused by changes in Go 1.10 archive/tar, which
mis-guesses the tar stream format as USTAR (rather than PAX),
which, in turn, leads to inability to specify file names
longer than 100 characters.

This tar stream is sent by TarWithOptions() (which, since we switched to
Go 1.10, explicitly sets format=PAX for every file, see FileInfoHeader(),
and before Go 1.10 it was PAX by default). Unfortunately, the receiving
side, RebaseArchiveEntries(), which calls tar.Next(), mistakenly guesses
header format as USTAR, which leads to the above error.

The fix is easy: set the format to PAX in RebaseArchiveEntries()
where we read the tar stream and change the file name.

A unit test is added to prevent future regressions.

NOTE this code is not used by dockerd, but rather but docker cli
(also possibly other clients), so this needs to be re-vendored
to cli in order to take effect.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit f55a417)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
docker-jenkins pushed a commit to docker-archive/docker-ce that referenced this issue Mar 6, 2019
As reported in docker/for-linux/issues/484, since Docker 18.06
docker cp with a destination file name fails with the following error:

> archive/tar: cannot encode header: Format specifies USTAR; and USTAR cannot encode Name="a_very_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_long_filename_that_is_101_characters"

The problem is caused by changes in Go 1.10 archive/tar, which
mis-guesses the tar stream format as USTAR (rather than PAX),
which, in turn, leads to inability to specify file names
longer than 100 characters.

This tar stream is sent by TarWithOptions() (which, since we switched to
Go 1.10, explicitly sets format=PAX for every file, see FileInfoHeader(),
and before Go 1.10 it was PAX by default). Unfortunately, the receiving
side, RebaseArchiveEntries(), which calls tar.Next(), mistakenly guesses
header format as USTAR, which leads to the above error.

The fix is easy: set the format to PAX in RebaseArchiveEntries()
where we read the tar stream and change the file name.

A unit test is added to prevent future regressions.

NOTE this code is not used by dockerd, but rather but docker cli
(also possibly other clients), so this needs to be re-vendored
to cli in order to take effect.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit f55a4176febbd0dffd6e5eb65beb70bc32912d0b)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: 989e7f5d3a3f40ebb936376245b770f766ea42e9
Component: engine
thaJeztah added a commit to thaJeztah/cli that referenced this issue Mar 27, 2019
relevant changes;

- moby/moby#38006 / docker-archive/engine#114 client: use io.LimitedReader for reading HTTP error
- moby/moby#38634 / docker-archive/engine#167 pkg/archive:CopyTo(): fix for long dest filename
  - fixes docker/for-linux#484 for 18.09
- moby/moby#38944 / docker-archive/engine#183 gitutils: add validation for ref
- moby/moby#37780 / docker-archive/engine#55 pkg/progress: work around closing closed channel panic
  - addresses moby/moby#/37735 pkg/progress: panic due to race on shutdown

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
docker-jenkins pushed a commit to docker-archive/docker-ce that referenced this issue Mar 27, 2019
relevant changes;

- moby/moby#38006 / docker-archive/engine#114 client: use io.LimitedReader for reading HTTP error
- moby/moby#38634 / docker-archive/engine#167 pkg/archive:CopyTo(): fix for long dest filename
  - fixes docker/for-linux#484 for 18.09
- moby/moby#38944 / docker-archive/engine#183 gitutils: add validation for ref
- moby/moby#37780 / docker-archive/engine#55 pkg/progress: work around closing closed channel panic
  - addresses moby/moby#/37735 pkg/progress: panic due to race on shutdown

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: 010c234a0d5a03d450ebec60be37dd9f279feeca
Component: cli
adhulipa pushed a commit to adhulipa/docker that referenced this issue Apr 11, 2019
As reported in docker/for-linux/issues/484, since Docker 18.06
docker cp with a destination file name fails with the following error:

> archive/tar: cannot encode header: Format specifies USTAR; and USTAR cannot encode Name="a_very_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_long_filename_that_is_101_characters"

The problem is caused by changes in Go 1.10 archive/tar, which
mis-guesses the tar stream format as USTAR (rather than PAX),
which, in turn, leads to inability to specify file names
longer than 100 characters.

This tar stream is sent by TarWithOptions() (which, since we switched to
Go 1.10, explicitly sets format=PAX for every file, see FileInfoHeader(),
and before Go 1.10 it was PAX by default). Unfortunately, the receiving
side, RebaseArchiveEntries(), which calls tar.Next(), mistakenly guesses
header format as USTAR, which leads to the above error.

The fix is easy: set the format to PAX in RebaseArchiveEntries()
where we read the tar stream and change the file name.

A unit test is added to prevent future regressions.

NOTE this code is not used by dockerd, but rather but docker cli
(also possibly other clients), so this needs to be re-vendored
to cli in order to take effect.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
@interactwithankush
Copy link

Assuming this issue is fixed in later docker version, could someone please share the version which solves this issue.

@thaJeztah
Copy link
Member

Yes this is fixed;

$ docker run -d -i  --name docker_test alpine
$ docker cp docker_test:/etc/resolv.conf a_very_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_long_filename_that_is_100_characters
$ docker cp docker_test:/etc/resolv.conf a_very_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_long_filename_that_is_101_characters
$ ls a_very_*
a_very_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_long_filename_that_is_100_characters
a_very_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_long_filename_that_is_101_characters

could someone please share the version which solves this issue.

It's included in Docker 18.09.4 and up; docker-archive/engine#167 / docker/cli#1778

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants