diff options
author | Tristan Maat <tristan.maat@codethink.co.uk> | 2019-06-24 17:35:23 +0100 |
---|---|---|
committer | Tristan Maat <tristan.maat@codethink.co.uk> | 2019-07-02 15:20:46 +0100 |
commit | 86a76c29c09d92e58280c5a9fc1736f5efe1e88f (patch) | |
tree | ea7d64ec5ec39b8391e8bdb316ee952566516111 /tests/sources | |
parent | 7893f514404c6f18e40b94961f89b756f5041000 (diff) | |
download | buildstream-86a76c29c09d92e58280c5a9fc1736f5efe1e88f.tar.gz |
tar.py: Make link target renaming work between base-dirs
Fixes #1052
Diffstat (limited to 'tests/sources')
6 files changed, 96 insertions, 0 deletions
diff --git a/tests/sources/tar.py b/tests/sources/tar.py index a6c1a4d9f..07108ccbb 100644 --- a/tests/sources/tar.py +++ b/tests/sources/tar.py @@ -407,3 +407,86 @@ def test_homeless_environment(cli, tmpdir, datafiles): # Use a track, make sure the plugin tries to find a ~/.netrc result = cli.run(project=project, args=['source', 'track', 'target.bst'], env={'HOME': None}) result.assert_success() + + +@pytest.mark.datafiles(os.path.join(DATA_DIR, 'out-of-basedir-hardlinks')) +def test_out_of_basedir_hardlinks(cli, tmpdir, datafiles): + def ensure_link(member): + # By default, python will simply duplicate files - we want + # hardlinks! + if member.path == "contents/to_extract/a": + member.type = tarfile.LNKTYPE + member.linkname = "contents/elsewhere/a" + return member + + project = str(datafiles) + generate_project(project, tmpdir) + checkoutdir = os.path.join(str(tmpdir), "checkout") + + # Create a tarball with an odd hardlink + src_tar = os.path.join(str(tmpdir), "contents.tar.gz") + old_dir = os.getcwd() + os.chdir(str(tmpdir)) + with tarfile.open(src_tar, "w:gz") as tar: + tar.add("contents", filter=ensure_link) + os.chdir(old_dir) + + # Make sure our tarfile is actually created with the desired + # attributes set + with tarfile.open(src_tar, "r:gz") as tar: + assert any(member.islnk() and + member.path == "contents/to_extract/a" and + member.linkname == "contents/elsewhere/a" + for member in tar.getmembers()) + + # Assert that we will actually create a singular copy of the file + result = cli.run(project=project, args=['source', 'track', 'target.bst']) + result.assert_success() + result = cli.run(project=project, args=['source', 'fetch', 'target.bst']) + result.assert_success() + result = cli.run(project=project, args=['build', 'target.bst']) + result.assert_success() + result = cli.run(project=project, args=['artifact', 'checkout', 'target.bst', '--directory', checkoutdir]) + result.assert_success() + + original_dir = os.path.join(str(datafiles), 'contents', 'to_extract') + original_contents = list_dir_contents(original_dir) + checkout_contents = list_dir_contents(checkoutdir) + assert checkout_contents == original_contents + + +@pytest.mark.datafiles(os.path.join(DATA_DIR, 'out-of-basedir-hardlinks')) +def test_malicious_out_of_basedir_hardlinks(cli, tmpdir, datafiles): + project = str(datafiles) + generate_project(project, tmpdir) + + # Create a maliciously-hardlinked tarball + def ensure_link(member): + # By default, python will simply duplicate files - we want + # hardlinks! + if member.path == "contents/elsewhere/malicious": + member.type = tarfile.LNKTYPE + # This should not be allowed + member.linkname = "../../../malicious_target.bst" + return member + + src_tar = os.path.join(str(tmpdir), "contents.tar.gz") + old_dir = os.getcwd() + os.chdir(str(tmpdir)) + with tarfile.open(src_tar, "w:gz") as tar: + tar.add("contents", filter=ensure_link) + os.chdir(old_dir) + + # Make sure our tarfile is actually created with the desired + # attributes set + with tarfile.open(src_tar, "r:gz") as tar: + assert any(member.islnk() and + member.path == "contents/elsewhere/malicious" and + member.linkname == "../../../malicious_target.bst" + for member in tar.getmembers()) + + # Try to execute the exploit + result = cli.run(project=project, args=['source', 'track', 'malicious_target.bst']) + result.assert_success() + result = cli.run(project=project, args=['source', 'fetch', 'malicious_target.bst']) + result.assert_main_error(ErrorDomain.STREAM, None) diff --git a/tests/sources/tar/out-of-basedir-hardlinks/contents/elsewhere/a b/tests/sources/tar/out-of-basedir-hardlinks/contents/elsewhere/a new file mode 100644 index 000000000..ce0136250 --- /dev/null +++ b/tests/sources/tar/out-of-basedir-hardlinks/contents/elsewhere/a @@ -0,0 +1 @@ +hello diff --git a/tests/sources/tar/out-of-basedir-hardlinks/contents/elsewhere/malicious b/tests/sources/tar/out-of-basedir-hardlinks/contents/elsewhere/malicious new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/sources/tar/out-of-basedir-hardlinks/contents/elsewhere/malicious diff --git a/tests/sources/tar/out-of-basedir-hardlinks/contents/to_extract/a b/tests/sources/tar/out-of-basedir-hardlinks/contents/to_extract/a new file mode 100644 index 000000000..ce0136250 --- /dev/null +++ b/tests/sources/tar/out-of-basedir-hardlinks/contents/to_extract/a @@ -0,0 +1 @@ +hello diff --git a/tests/sources/tar/out-of-basedir-hardlinks/malicious_target.bst b/tests/sources/tar/out-of-basedir-hardlinks/malicious_target.bst new file mode 100644 index 000000000..b9debe961 --- /dev/null +++ b/tests/sources/tar/out-of-basedir-hardlinks/malicious_target.bst @@ -0,0 +1,5 @@ +kind: import +description: The kind of this element is irrelevant. +sources: +- kind: tar + url: tmpdir:/contents.tar.gz diff --git a/tests/sources/tar/out-of-basedir-hardlinks/target.bst b/tests/sources/tar/out-of-basedir-hardlinks/target.bst new file mode 100644 index 000000000..4f07e2e4c --- /dev/null +++ b/tests/sources/tar/out-of-basedir-hardlinks/target.bst @@ -0,0 +1,6 @@ +kind: import +description: The kind of this element is irrelevant. +sources: +- kind: tar + url: tmpdir:/contents.tar.gz + base-dir: contents/to_extract |