From 420aea62629573b3d7a23727de90bb46dc7907da Mon Sep 17 00:00:00 2001 From: Christian Boltz Date: Wed, 3 Oct 2018 16:29:20 +0200 Subject: [PATCH] Add basic support for abi rules to the tools Add basic "understand and keep" support for abi rules, where "understand" means to not error out when seeing an abi rule, and "keep" simply means to keep the original abi rule when serializing a profile. On the long term, abi rules should be parsed (similar to include rules), but for now, this patch is the smallest possible changeset and easy to backport. Note that the only added test is via cleanprof_test.* which is used by minitools_test.py - and does _not_ run if you do a 'make check'. Oh, and of course the simple_tests/abi/ files also get parsed by test-parser-simple-tests.py. BTW: Even serialize_profile_from_old_profile() can handle abi rules :-) This is a backport of 072d3e04514b70bb3b29d4bfe400caa44dd574a2 / !202 to 2.13 (with some adjustments because that commit didn't appy cleanly) --- utils/apparmor/aa.py | 21 +++++++++++++++++---- utils/apparmor/profile_storage.py | 12 ++++++++++++ utils/apparmor/regex.py | 1 + utils/test/cleanprof_test.in | 2 ++ utils/test/cleanprof_test.out | 4 ++++ 5 files changed, 36 insertions(+), 4 deletions(-) diff --git a/utils/apparmor/aa.py b/utils/apparmor/aa.py index 6bbb8a099..42a4fe5dd 100644 --- a/utils/apparmor/aa.py +++ b/utils/apparmor/aa.py @@ -40,7 +40,7 @@ import apparmor.ui as aaui from apparmor.aamode import str_to_mode, split_mode from apparmor.regex import (RE_PROFILE_START, RE_PROFILE_END, RE_PROFILE_LINK, - RE_PROFILE_ALIAS, + RE_ABI, RE_PROFILE_ALIAS, RE_PROFILE_BOOLEAN, RE_PROFILE_VARIABLE, RE_PROFILE_CONDITIONAL, RE_PROFILE_CONDITIONAL_VARIABLE, RE_PROFILE_CONDITIONAL_BOOLEAN, RE_PROFILE_CHANGE_HAT, @@ -49,7 +49,7 @@ from apparmor.regex import (RE_PROFILE_START, RE_PROFILE_END, RE_PROFILE_LINK, RE_PROFILE_UNIX, RE_RULE_HAS_COMMA, RE_HAS_COMMENT_SPLIT, strip_quotes, parse_profile_start_line, re_match_include ) -from apparmor.profile_storage import ProfileStorage, add_or_remove_flag, ruletypes +from apparmor.profile_storage import ProfileStorage, add_or_remove_flag, ruletypes, write_abi import apparmor.rules as aarules @@ -2313,6 +2313,16 @@ def parse_profile_data(data, file, do_include): # Conditional Boolean defined pass + elif RE_ABI.search(line): + if profile: + profile_data[profile][hat]['abi'].append(line) + else: + if not filelist.get(file): + filelist[file] = hasher() + if not filelist[file].get('abi'): + filelist[file]['abi'] = [] + filelist[file]['abi'].append(line) + elif re_match_include(line): # Include files include_name = re_match_include(line) @@ -2781,7 +2791,8 @@ def write_file(prof_data, depth): return data def write_rules(prof_data, depth): - data = write_alias(prof_data, depth) + data = write_abi(prof_data, depth) + data += write_alias(prof_data, depth) data += write_list_vars(prof_data, depth) data += write_includes(prof_data, depth) data += write_rlimits(prof_data, depth) @@ -2871,6 +2882,7 @@ def serialize_profile(profile_data, name, options): prof_filename = get_profile_filename(name) if filelist.get(prof_filename, False): + data += write_abi(filelist[prof_filename], 0) data += write_alias(filelist[prof_filename], 0) data += write_list_vars(filelist[prof_filename], 0) data += write_includes(filelist[prof_filename], 0) @@ -2943,7 +2955,8 @@ def serialize_profile_from_old_profile(profile_data, name, options): with open_file_read(prof_filename) as f_in: profile = None hat = None - write_methods = {'alias': write_alias, + write_methods = {'abi': write_abi, + 'alias': write_alias, 'lvar': write_list_vars, 'include': write_includes, 'rlimit': write_rlimits, diff --git a/utils/apparmor/profile_storage.py b/utils/apparmor/profile_storage.py index cdb8a7602..815f3b4c3 100644 --- a/utils/apparmor/profile_storage.py +++ b/utils/apparmor/profile_storage.py @@ -52,6 +52,7 @@ class ProfileStorage: data[rule] = ruletypes[rule]['ruleset']() data['alias'] = dict() + data['abi'] = [] data['include'] = dict() data['localinclude'] = dict() data['lvar'] = dict() @@ -131,3 +132,14 @@ def add_or_remove_flag(flags, flag_to_change, set_flag): flags.remove(flag_to_change) return sorted(flags) + +def write_abi(ref, depth): + pre = ' ' * depth + data = [] + + if ref.get('abi'): + for line in ref.get('abi'): + data.append('%s%s' % (pre, line)) + data.append('') + + return data diff --git a/utils/apparmor/regex.py b/utils/apparmor/regex.py index 1cad58153..e3cdde365 100644 --- a/utils/apparmor/regex.py +++ b/utils/apparmor/regex.py @@ -132,6 +132,7 @@ def parse_profile_start_line(line, filename): return result +RE_ABI = re.compile('^\s*#?abi\s*(<(?P.*)>|"(?P.*)"|(?P[^<>"]*))' + RE_COMMA_EOL) RE_INCLUDE = re.compile('^\s*#?include\s*(<(?P.*)>|"(?P.*)"|(?P[^<>"]*))' + RE_EOL) diff --git a/utils/test/cleanprof_test.in b/utils/test/cleanprof_test.in index e26462430..c9cd27fcf 100644 --- a/utils/test/cleanprof_test.in +++ b/utils/test/cleanprof_test.in @@ -2,6 +2,7 @@ #include alias /foo -> /bar , + abi , /usr/bin/a/simple/cleanprof/test/profile { # Just for the heck of it, this comment wont see the day of light @@ -14,6 +15,7 @@ change_profile, network inet stream, + abi "abi/4.20" , network stream, #Below rule comes from abstractions/base diff --git a/utils/test/cleanprof_test.out b/utils/test/cleanprof_test.out index 09acc466e..71de1bd8e 100644 --- a/utils/test/cleanprof_test.out +++ b/utils/test/cleanprof_test.out @@ -1,3 +1,5 @@ +abi , + alias /foo -> /bar, #include @@ -6,6 +8,8 @@ alias /foo -> /bar, /usr/bin/a/simple/cleanprof/test/profile { + abi "abi/4.20" , + #include set rlimit nofile <= 256,