diff --git a/utils/apparmor/aa.py b/utils/apparmor/aa.py index c814bd11f..9241692bb 100644 --- a/utils/apparmor/aa.py +++ b/utils/apparmor/aa.py @@ -1703,17 +1703,16 @@ def read_profile(file, is_active_profile, read_error_fatal=False): extra_profiles.add_profile(filename, profile, attachment, profile_data[profile]) -def get_local_include(profile_name): - # If a local profile already exists, we use it. - for rule in active_profiles[profile_name]['inc_ie'].rules: - if rule.path.startswith("local/"): - return rule.path - return None - - +# TODO: Split profiles' creating and saving. def create_local_profile_if_needed(profile_name): - base_profile = profile_name.split("/", 1)[0] - local_include = get_local_include(profile_name) + base_profile = profile_name + while True: + parent = active_profiles[base_profile].data.get('parent') + if parent == '': + break + base_profile = parent + + local_include = active_profiles[profile_name].get_local_include() # Not found: we add a mention of the local profile in the main profile if not local_include: @@ -1756,7 +1755,7 @@ def write_include(include_data, incfile, out_dir=None, include_metadata=True): include_string = serialize_include(include_data, include_metadata=include_metadata) - with NamedTemporaryFile('w', suffix='~', delete=False) as tmp: + with NamedTemporaryFile('w', suffix='~', delete=False, dir=profile_dir + "/local") as tmp: if os.path.exists(target_file): shutil.copymode(target_file, tmp.name) else: diff --git a/utils/apparmor/profile_storage.py b/utils/apparmor/profile_storage.py index 26fd91ee8..e35d1c565 100644 --- a/utils/apparmor/profile_storage.py +++ b/utils/apparmor/profile_storage.py @@ -199,6 +199,21 @@ class ProfileStorage: return data + def get_local_include(self): + inc = None + preferred_inc = self.data['name'] + if preferred_inc.startswith('/'): + preferred_inc = preferred_inc[1:] + preferred_inc = 'local/' + preferred_inc.replace('/', '.') + + # If a local profile already exists, we use it. + for rule in self.data['inc_ie'].rules: + if rule.path.startswith("local/"): + inc = rule.path + if rule.path == preferred_inc: # Prefer includes that matches the profile name. + break + return inc + @classmethod def parse(cls, line, file, lineno, profile, hat): """parse a profile start line (using parse_profile_startline()) and convert it to an instance of this class""" diff --git a/utils/apparmor/update_profile.py b/utils/apparmor/update_profile.py index 4c83046b3..4864a9d0a 100755 --- a/utils/apparmor/update_profile.py +++ b/utils/apparmor/update_profile.py @@ -46,9 +46,9 @@ def add_to_profile(rule_obj, profile_name): def add_to_local_profile(rule_obj, profile_name): - inc_file = aa.create_local_profile_if_needed(profile_name, cleanup=True) + inc_file = aa.create_local_profile_if_needed(profile_name) - aa.include[inc_file][inc_file].data[rule_obj.rule_name].add(rule_obj) + aa.include[inc_file][inc_file].data[rule_obj.rule_name].add(rule_obj, cleanup=True) aa.write_include_ui_feedback(aa.include[inc_file][inc_file], inc_file) @@ -66,7 +66,7 @@ def add_rule(mode, rule, profile_name): elif mode == 'no': add_to_profile(rule_obj, profile_name) elif mode == 'auto': - if aa.get_local_include(profile_name): + if aa.active_profiles[profile_name].get_local_include(): add_to_local_profile(rule_obj, profile_name) else: add_to_profile(rule_obj, profile_name)