From accc38032663f8f3253685f01547513f594d43c6 Mon Sep 17 00:00:00 2001 From: Christian Boltz Date: Mon, 22 Feb 2021 22:22:25 +0100 Subject: [PATCH] Add in_preamble parameter to profile loading/parsing functions in_preamble keeps track of the current parsing position. It's True while parsing the preamble of a profile file, and when loading an include file that is included in the preamble (typically tunables/*). While inside a profile or parsing abstractions/*, it is False. This commit only hands the information around and keeps in_preamble updated, but it doesn't really get used yet. Also adjust the tests to hand over the additional parameter to parse_profile_data(). --- utils/apparmor/aa.py | 21 ++++++++++++--------- utils/test/test-aa.py | 16 ++++++++-------- utils/test/test-parser-simple-tests.py | 4 ++-- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/utils/apparmor/aa.py b/utils/apparmor/aa.py index 6b974978b..e02b7411c 100644 --- a/utils/apparmor/aa.py +++ b/utils/apparmor/aa.py @@ -1727,7 +1727,7 @@ def read_profile(file, active_profile): debug_logger.debug("read_profile: can't read %s - skipping" % file) return None - profile_data = parse_profile_data(data, file, 0) + profile_data = parse_profile_data(data, file, 0, True) if profile_data and active_profile: attach_profile_data(aa, profile_data) @@ -1825,7 +1825,7 @@ def parse_profile_start_to_storage(line, file, lineno, profile, hat): return (profile, hat, prof_storage) -def parse_profile_data(data, file, do_include): +def parse_profile_data(data, file, do_include, in_preamble): profile_data = hasher() profile = None hat = None @@ -1863,6 +1863,8 @@ def parse_profile_data(data, file, do_include): else: in_contained_hat = False + in_preamble = False + (profile, hat, prof_storage) = parse_profile_start_to_storage(line, file, lineno, profile, hat) if profile_data[profile].get(hat, False): @@ -1888,6 +1890,7 @@ def parse_profile_data(data, file, do_include): else: parsed_profiles.append(profile) profile = None + in_preamble = True initial_comment = '' @@ -1938,7 +1941,7 @@ def parse_profile_data(data, file, do_include): active_profiles.add_inc_ie(file, rule_obj) for incname in rule_obj.get_full_paths(profile_dir): - load_include(incname) + load_include(incname, in_preamble) elif RE_PROFILE_MOUNT.search(line): matches = RE_PROFILE_MOUNT.search(line).groups() @@ -2429,7 +2432,7 @@ def include_dir_filelist(include_name): return files -def load_include(incname): +def load_include(incname, in_preamble=False): load_includeslist = [incname] while load_includeslist: incfile = load_includeslist.pop(0) @@ -2440,7 +2443,7 @@ def load_include(incname): pass # already read, do nothing elif os.path.isfile(incfile): data = get_include_data(incfile) - incdata = parse_profile_data(data, incfile, True) + incdata = parse_profile_data(data, incfile, True, in_preamble) attach_profile_data(include, incdata) #If the include is a directory means include all subfiles elif os.path.isdir(incfile): @@ -2464,10 +2467,10 @@ def get_subdirectories(current_dir): return os.walk(current_dir).__next__()[1] def loadincludes(): - loadincludes_dir('tunables') - loadincludes_dir('abstractions') + loadincludes_dir('tunables', True) + loadincludes_dir('abstractions', False) -def loadincludes_dir(subdir): +def loadincludes_dir(subdir, in_preamble): idir = os.path.join(profile_dir, subdir) if os.path.isdir(idir): # if directory doesn't exist, silently skip loading it @@ -2477,7 +2480,7 @@ def loadincludes_dir(subdir): continue else: fi = os.path.join(dirpath, fi) - load_include(fi) + load_include(fi, in_preamble) def glob_common(path): globs = [] diff --git a/utils/test/test-aa.py b/utils/test/test-aa.py index 76bff7a79..e5d78de00 100644 --- a/utils/test/test-aa.py +++ b/utils/test/test-aa.py @@ -521,7 +521,7 @@ class AaTest_parse_profile_start_errors(AATest): class AaTest_parse_profile_data(AATest): def test_parse_empty_profile_01(self): - prof = parse_profile_data('/foo {\n}\n'.split(), 'somefile', False) + prof = parse_profile_data('/foo {\n}\n'.split(), 'somefile', False, False) self.assertEqual(list(prof.keys()), ['/foo']) self.assertEqual(list(prof['/foo'].keys()), ['/foo']) @@ -532,20 +532,20 @@ class AaTest_parse_profile_data(AATest): def test_parse_duplicate_profile(self): with self.assertRaises(AppArmorException): # file contains two profiles with the same name - parse_profile_data('profile /foo {\n}\nprofile /foo {\n}\n'.split(), 'somefile', False) + parse_profile_data('profile /foo {\n}\nprofile /foo {\n}\n'.split(), 'somefile', False, False) def test_parse_duplicate_child_profile(self): with self.assertRaises(AppArmorException): # file contains two child profiles with the same name - parse_profile_data('profile /foo {\nprofile /bar {\n}\nprofile /bar {\n}\n}\n'.split(), 'somefile', False) + parse_profile_data('profile /foo {\nprofile /bar {\n}\nprofile /bar {\n}\n}\n'.split(), 'somefile', False, False) def test_parse_duplicate_hat(self): with self.assertRaises(AppArmorException): # file contains two hats with the same name - parse_profile_data('profile /foo {\n^baz {\n}\n^baz {\n}\n}\n'.split(), 'somefile', False) + parse_profile_data('profile /foo {\n^baz {\n}\n^baz {\n}\n}\n'.split(), 'somefile', False, False) def test_parse_xattrs_01(self): - prof = parse_profile_data('/foo xattrs=(user.bar=bar) {\n}\n'.split(), 'somefile', False) + prof = parse_profile_data('/foo xattrs=(user.bar=bar) {\n}\n'.split(), 'somefile', False, False) self.assertEqual(list(prof.keys()), ['/foo']) self.assertEqual(list(prof['/foo'].keys()), ['/foo']) @@ -555,7 +555,7 @@ class AaTest_parse_profile_data(AATest): self.assertEqual(prof['/foo']['/foo']['xattrs'], 'user.bar=bar') def test_parse_xattrs_02(self): - prof = parse_profile_data('/foo xattrs=(user.bar=bar user.foo=*) {\n}\n'.split(), 'somefile', False) + prof = parse_profile_data('/foo xattrs=(user.bar=bar user.foo=*) {\n}\n'.split(), 'somefile', False, False) self.assertEqual(list(prof.keys()), ['/foo']) self.assertEqual(list(prof['/foo'].keys()), ['/foo']) @@ -566,7 +566,7 @@ class AaTest_parse_profile_data(AATest): def test_parse_xattrs_03(self): d = '/foo xattrs=(user.bar=bar) flags=(complain) {\n}\n' - prof = parse_profile_data(d.split(), 'somefile', False) + prof = parse_profile_data(d.split(), 'somefile', False, False) self.assertEqual(list(prof.keys()), ['/foo']) self.assertEqual(list(prof['/foo'].keys()), ['/foo']) @@ -579,7 +579,7 @@ class AaTest_parse_profile_data(AATest): with self.assertRaises(AppArmorException): # flags before xattrs d = '/foo flags=(complain) xattrs=(user.bar=bar) {\n}\n' - parse_profile_data(d.split(), 'somefile', False) + parse_profile_data(d.split(), 'somefile', False, False) class AaTest_write_header(AATest): tests = [ diff --git a/utils/test/test-parser-simple-tests.py b/utils/test/test-parser-simple-tests.py index 559d2ee6f..7333a0e1c 100644 --- a/utils/test/test-parser-simple-tests.py +++ b/utils/test/test-parser-simple-tests.py @@ -430,12 +430,12 @@ class TestParseParserTests(AATest): apparmor.active_profiles.init_file(params['file']) if expected: - apparmor.parse_profile_data(data, params['file'], 0) + apparmor.parse_profile_data(data, params['file'], 0, True) apparmor.active_profiles.get_all_merged_variables(params['file'], apparmor.include_list_recursive(apparmor.active_profiles.files[params['file']])) else: with self.assertRaises(AppArmorException): - apparmor.parse_profile_data(data, params['file'], 0) + apparmor.parse_profile_data(data, params['file'], 0, True) apparmor.active_profiles.get_all_merged_variables(params['file'], apparmor.include_list_recursive(apparmor.active_profiles.files[params['file']])) def parse_test_profiles(file_with_path):