diff options
author | Richard Maw <richard.maw@codethink.co.uk> | 2013-08-28 17:01:50 +0000 |
---|---|---|
committer | Richard Maw <richard.maw@codethink.co.uk> | 2013-08-28 17:01:50 +0000 |
commit | 05f49ba6c19778a8c2a427d4eee2fb71a01fe375 (patch) | |
tree | b93cc7493eadcc0e054d279bf16db434e6d5bedc /morphlib | |
parent | f3293ecbda184248ea370aa8a419968cb005ba03 (diff) | |
download | morph-05f49ba6c19778a8c2a427d4eee2fb71a01fe375.tar.gz |
rootfs-protection: Fix building with tempdir=/tmp
The issue is that the tempdir is added at the end of the list of
directories to keep writable, and entries earlier in the list are
subdirectories of tempdir.
The check encountered the subdirs first, so decided it must recurse and
make everything else read-only.
It never got as far as noticing that /tmp was requested writable.
Now, every path is checked for being equal, then checked for being
a subdirectory.
This changed style to use any and generator expressions, as it was more
concise than having an explicit loop for checking equality, then an
explicit loop for checking subdirectory.
Diffstat (limited to 'morphlib')
-rw-r--r-- | morphlib/fsutils.py | 34 | ||||
-rw-r--r-- | morphlib/fsutils_tests.py | 25 |
2 files changed, 44 insertions, 15 deletions
diff --git a/morphlib/fsutils.py b/morphlib/fsutils.py index 84884be8..0212b987 100644 --- a/morphlib/fsutils.py +++ b/morphlib/fsutils.py @@ -103,29 +103,33 @@ def invert_paths(tree_walker, paths): dn_copy = list(dirnames) for subdir in dn_copy: subdirpath = os.path.join(dirpath, subdir) - for p in paths: - # Subdir is an exact match for a given path + + if any(p == subdirpath for p in paths): + # Subdir is an exact match for a path # Don't recurse into it, so remove from list - # Also don't yield it as we're inverting - if subdirpath == p: - dirnames.remove(subdir) - break + # Don't yield it, since we don't return listed paths + dirnames.remove(subdir) + elif any(is_subpath(subdirpath, p) for p in paths): # This directory is a parent directory of one - # of our paths, recurse into it, but don't yield it - elif is_subpath(subdirpath, p): - break + # of our paths + # Recurse into it, so don't remove it from the list + # Don't yield it, since we don't return listed paths + pass else: + # This directory is neither one marked for writing, + # nor a parent of a file marked for writing + # Don't recurse, so remove it from the list + # Yield it, since we return listed paths dirnames.remove(subdir) yield subdirpath for filename in filenames: fullpath = os.path.join(dirpath, filename) - for p in paths: + if any(is_subpath(p, fullpath) for p in paths): # The file path is a child of one of the paths - # or is equal. Don't yield because either it is - # one of the specified paths, or is a file in a - # directory specified by a path - if is_subpath(p, fullpath): - break + # or is equal. + # Don't yield because either it is one of the specified + # paths, or is a file in a directory specified by a path + pass else: yield fullpath diff --git a/morphlib/fsutils_tests.py b/morphlib/fsutils_tests.py index f49e6f89..7b159665 100644 --- a/morphlib/fsutils_tests.py +++ b/morphlib/fsutils_tests.py @@ -72,3 +72,28 @@ class InvertPathsTests(unittest.TestCase): found = frozenset(morphlib.fsutils.invert_paths(walker, ["./foo"])) unexpected = ("./foo", "./foo/bar", "./foo/baz") self.assertTrue(all(path not in found for path in unexpected)) + + def test_lower_mount_precludes(self): + walker = dummy_top_down_walker('.', { + "tmp": { + "morph": { + "staging": { + "build": None, + "inst": None, + }, + }, + "ccache": { + "0": None + }, + }, + "bin": { + }, + }) + found = frozenset(morphlib.fsutils.invert_paths( + walker, [ + "./tmp/morph/staging/build", + "./tmp/morph/staging/inst", + "./tmp", + ])) + expected = ("./bin",) + self.assertEqual(sorted(found), sorted(expected)) |