summaryrefslogtreecommitdiff
path: root/tests/sources
diff options
context:
space:
mode:
authorTristan Maat <tristan.maat@codethink.co.uk>2019-06-24 17:35:23 +0100
committerTristan Maat <tristan.maat@codethink.co.uk>2019-07-02 15:20:46 +0100
commit86a76c29c09d92e58280c5a9fc1736f5efe1e88f (patch)
treeea7d64ec5ec39b8391e8bdb316ee952566516111 /tests/sources
parent7893f514404c6f18e40b94961f89b756f5041000 (diff)
downloadbuildstream-86a76c29c09d92e58280c5a9fc1736f5efe1e88f.tar.gz
tar.py: Make link target renaming work between base-dirs
Fixes #1052
Diffstat (limited to 'tests/sources')
-rw-r--r--tests/sources/tar.py83
-rw-r--r--tests/sources/tar/out-of-basedir-hardlinks/contents/elsewhere/a1
-rw-r--r--tests/sources/tar/out-of-basedir-hardlinks/contents/elsewhere/malicious0
-rw-r--r--tests/sources/tar/out-of-basedir-hardlinks/contents/to_extract/a1
-rw-r--r--tests/sources/tar/out-of-basedir-hardlinks/malicious_target.bst5
-rw-r--r--tests/sources/tar/out-of-basedir-hardlinks/target.bst6
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