Fix docker cp when container source path is /#39357
Conversation
33c5db2 to
cac6afc
Compare
CID=$(docker create alpine) docker cp $CID:/ out Signed-off-by: Brian Goff <[email protected]> Signed-off-by: Tibor Vass <[email protected]>
Codecov Report
@@ Coverage Diff @@
## master #39357 +/- ##
=========================================
Coverage ? 36.97%
=========================================
Files ? 612
Lines ? 45645
Branches ? 0
=========================================
Hits ? 16877
Misses ? 26480
Partials ? 2288 |
|
087d4c3 to
d718ac0
Compare
Signed-off-by: Tibor Vass <[email protected]>
Before 7a7357d, archive.TarResourceRebase was being used to copy files and folders from the container. That function splits the source path into a dirname + basename pair to support copying a file: if you wanted to tar `dir/file` it would tar from `dir` the file `file` (as part of the IncludedFiles option). However, that path splitting logic was kept for folders as well, which resulted in weird inputs to archive.TarWithOptions: if you wanted to tar `dir1/dir2` it would tar from `dir1` the directory `dir2` (as part of IncludedFiles option). Although it was weird, it worked fine until we started chrooting into the container rootfs when doing a `docker cp` with container source set to `/` (cf 3029e76). The fix is to only do the path splitting logic if the source is a file. Unfortunately, 7a7357d added support for LCOW by duplicating some of this subtle logic. Ideally we would need to do more refactoring of the archive codebase to properly encapsulate these behaviors behind well- documented APIs. This fix does not do that. Instead, it fixes the issue inline. Signed-off-by: Tibor Vass <[email protected]>
| sourceDir := resolvedPath | ||
| sourceBase := "." | ||
|
|
||
| if stat.Mode&os.ModeDir == 0 { // not dir |
There was a problem hiding this comment.
I think this should be
if symlink {
opts = rebase
}
and always archivePath(resolvedPath).
Would be more understandable what is actually happening and wouldn't need the hack for removing the slash in the walker. But functionally they seem equivalent.
There was a problem hiding this comment.
Agreed. Can be done in a follow up.
|
@thaJeztah @kolyshkin updated with small requested change. |
Previously, getWalkRoot("/", "foo") would return "//foo"
Now it returns "/foo"
Signed-off-by: Tibor Vass <[email protected]>
|
Failure is TestAPISwarmLeaderElection which is unrelated |
|
Looks like s390x passed, but is hanging on the cleanup; https://jenkins.dockerproject.org/job/Docker-PRs-s390x/14591/console |
…directory traversal. moby/moby#39357
Another attempt at fixing #39348
Fixes #39348
Previous attempt at #39351
Before 7a7357d, archive.TarResourceRebase was being used to copy files
and folders from the container. That function splits the source path
into a dirname + basename pair to support copying a file:
if you wanted to tar
dir/fileit would tar fromdirthe filefile(as part of the IncludedFiles option).
However, that path splitting logic was kept for folders as well, which
resulted in weird inputs to archive.TarWithOptions:
if you wanted to tar
dir1/dir2it would tar fromdir1the directorydir2(as part of IncludedFiles option).Although it was weird, it worked fine until we started chrooting into
the container rootfs when doing a
docker cpwith container source setto
/(cf 3029e76 (#39292)).The fix is to only do the path splitting logic if the source is a file.
Unfortunately, 7a7357d added support for LCOW by duplicating some of
this subtle logic. Ideally we would need to do more refactoring of the
archive codebase to properly encapsulate these behaviors behind well-
documented APIs.
This fix does not do that. Instead, it fixes the issue inline.
Signed-off-by: Tibor Vass [email protected]
I added a couple of more tests than the actual issue needs, just to make sure there are no other regressions compared to before the cve fix (3029e76).
Huge thanks to @cpuguy83 ❤️who worked tirelessly with me to understand the code and make this PR.