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

Fix relative symlink support in TarFile #77338

Merged

Conversation

am11
Copy link
Member

@am11 am11 commented Oct 22, 2022

@ghost ghost added the community-contribution Indicates that the PR has been added by a community member label Oct 22, 2022
@ghost
Copy link

ghost commented Oct 22, 2022

Tagging subscribers to this area: @dotnet/area-system-io
See info in area-owners.md if you want to be subscribed.

Issue Details

Fixes #77303

Depends on dotnet/runtime-assets#280

Author: am11
Assignees: -
Labels:

area-System.IO

Milestone: -

@am11 am11 force-pushed the feature/libs/System.Formats.Tar/podman-image-tar branch 3 times, most recently from c2c500d to 533c109 Compare October 22, 2022 13:39
@am11
Copy link
Member Author

am11 commented Oct 22, 2022

@tmds, this gets us closer to tar utilities.

File attributes: I noticed with GNU and BSD tar(1), the file layer.tar in extraction dir has these permissions: rwxrwxrwx and date is of unix epoch's (Jan 1 1970), while we assign rwxr-xr-x and current date.

@tmds
Copy link
Member

tmds commented Oct 23, 2022

If we're changing this code, I think it would be good to make a decision about #74140.
I think the behavior is restrictive without a good reason.

@tmds
Copy link
Member

tmds commented Oct 23, 2022

File attributes: I noticed with GNU and BSD tar(1), the file layer.tar in extraction dir has these permissions: rwxrwxrwx and date is of unix epoch's (Jan 1 1970), while we assign rwxr-xr-x and current date.

Can you create an issue about this?

@am11
Copy link
Member Author

am11 commented Oct 23, 2022

I think the behavior is restrictive without a good reason.

There are two things which throw different IOExceptions:

  • file being extracted has destination outside the extraction directory. Throws: IOException(TarExtractingResultsFileOutside)
  • symlink is pointing to something outside the extraction directory (e.g. /usr/bin/foo). Throws: IOException(TarExtractingResultsLinkOutside)

the security concerns mentioned in #74140 apply to the first one, but the second one seems harmless given the target of symlink are normally not validated upon symlink creation (it can point to a non-existing path).

@tmds
Copy link
Member

tmds commented Oct 23, 2022

the security concerns mentioned in #74140 apply to the first one, but the second one seems harmless given the target of symlink are normally not validated upon symlink creation (it can point to a non-existing path).

Yes, #74140 is about the behavior being too restrictive in the second case.

@jozkee @carlossanlop @jeffhandley @adamsitnik can you make a decision about the desired behavior?

@am11 am11 force-pushed the feature/libs/System.Formats.Tar/podman-image-tar branch from 533c109 to bb34445 Compare November 3, 2022 09:55
@am11 am11 marked this pull request as ready for review November 3, 2022 09:56
@am11
Copy link
Member Author

am11 commented Nov 3, 2022

@adamsitnik, currently, System.Formats.Tar allows symlink target to be inside the archive and disallows if the target is pointing to path outside the archive. So far, this PR hasn't changed the behavior. The bug appears when the symlink target is pointing to the path inside the archive with relative paths, the symlink validation (TarExtractingResultsLinkOutside) fails. In addition to fixing the bug, this PR is also restoring the original symlink path post-validation, so we don't turn a relative target into absolute one in symlink's target after extracting the archive (matches GNU and BSD tar utilities).

Allowing the target of symlink to path outside the archive is a separate discussion (#74140, awaiting decision) and it can be fixed in a separate PR.

@tmds
Copy link
Member

tmds commented Nov 3, 2022

Allowing the target of symlink to path outside the archive is a separate discussion (#74140, awaiting decision) and it can be fixed in a separate PR.

Rather than changing this code once more, review it once more, and maybe backport it once more too, why don't we make a decision?

@am11
Copy link
Member Author

am11 commented Nov 3, 2022

Hmm, because they are separate issues: #77303 (comment)..

@tmds
Copy link
Member

tmds commented Nov 3, 2022

Yes, and still very related. #77303 is a bug in the code written for #74140.

@am11
Copy link
Member Author

am11 commented Nov 3, 2022

Right, and this is a bug fix with accompanying tests. If decision to allow link target outside the extraction directory will take longer (#74140 is awaiting decision for some time now), we should fix this bug regardless. The code change for 74140 is straightforward, so I am fine to fix it here as well. Lets see what the area owners think about next steps.

@am11
Copy link
Member Author

am11 commented Nov 4, 2022

FWIW, it will take this change to allow target of symlinks (and hardlinks) outside the archive: am11@fae7cd2 (remove validation of link target, update two existing tests and add two additional tests for non-existing paths).

@am11 am11 requested a review from adamsitnik November 5, 2022 08:28
@tmds
Copy link
Member

tmds commented Nov 5, 2022

FWIW, it will take this change to allow target of symlinks (and hardlinks) outside the archive: am11@fae7cd2 (remove validation of link target, update two existing tests and add two additional tests for non-existing paths).

You must also add the symlink check (see #74140) to prevent 'using' a symlink to place files outside the output directory.

@am11
Copy link
Member Author

am11 commented Nov 5, 2022

You must also add the symlink check (see #74140) to prevent 'using' a symlink to place files outside the output directory.

I am not sure how to produce that tar file. Do you have a test case handy which isn't failing with my change, while it should?

@tmds
Copy link
Member

tmds commented Nov 5, 2022

This is about introducing a new check that prevents an 'evil' tar file to write files outside the output directory. You should be able to create the tar file using the .NET API.

For example:

link: SymbolicLink to /tmp
link/file: RegularFile

Extracting this without the check, would lead to writing to /tmp/file independent of the output directory.

@am11
Copy link
Member Author

am11 commented Nov 5, 2022

You should be able to create the tar file using the .NET API.

How exactly?

@tmds
Copy link
Member

tmds commented Nov 8, 2022

You can use the TarWriter API. Take a look at the tests for some inspiration.

@am11
Copy link
Member Author

am11 commented Nov 8, 2022

Have you actually found that kind of tar file before? I am not sure how do you think it is possible to construct that tar file using the .NET API (or any other producer for that matter). That's why I asked for the test repro (or the tar file) you are talking about.

@tmds
Copy link
Member

tmds commented Nov 8, 2022

This is a specially crafted file meant to trigger a security problem. You can't create it from file system. The TarWriter API allows you to create it because it will write whatever entries you ask it to.

@am11
Copy link
Member Author

am11 commented Nov 8, 2022

Ok. Since you have ideas what needs to be done for #74140, I am not pursuing it. As it stands, this PR is only fixing the bug reported in #77303.

@jozkee, can you take a look?

@jozkee
Copy link
Member

jozkee commented Nov 9, 2022

Rather than changing this code once more, review it once more, and maybe backport it once more too, why don't we make a decision?

Between #77303 and #74140, is one of the issues worth backporting while the other is not?

Without the answer I think keeping them as separate PRs would allow us to nicely cherry-pick in case we choose to backport just one.

@am11
Copy link
Member Author

am11 commented Nov 9, 2022

is one of the issues worth backporting while the other is not?

IMO, this one is worth backporting since we currently allow symlinks within the extraction directory. The validation logic is wrong when the symlink is created with relative path; the bug this PR is fixing. It is not uncommon, e.g. in https://github.com/libunwind/libunwind/archive/refs/tags/v1.6.2.tar.gz, README is a relative symlink to README.md.

I think keeping them as separate PRs would allow us to nicely cherry-pick

I agree. Keeping bugfixes separate from changing the (intentional) behavior is pretty normal; if not recommended.

@am11 am11 force-pushed the feature/libs/System.Formats.Tar/podman-image-tar branch from 0350b9e to 3753c0a Compare November 9, 2022 20:17
@am11 am11 force-pushed the feature/libs/System.Formats.Tar/podman-image-tar branch from 118fc69 to 5b99de4 Compare November 10, 2022 23:39
…romDirectory.File.Roundtrip.cs

Co-authored-by: David Cantú <[email protected]>
@jozkee
Copy link
Member

jozkee commented Nov 11, 2022

Thanks.

@am11
Copy link
Member Author

am11 commented Nov 11, 2022

Thanks for the reviews @tmds and @jozkee.

@jozkee
Copy link
Member

jozkee commented Nov 16, 2022

/backport to release/7.0

@github-actions
Copy link
Contributor

Started backporting to release/7.0: https://github.com/dotnet/runtime/actions/runs/3480654764

@ghost ghost locked as resolved and limited conversation to collaborators Dec 22, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Formats.Tar community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

TarFile fails to extract even when symbolic link references into the output directory
4 participants