2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-31 14:25:52 +00:00

Fix aa-mergeprof crash caused by accidentially initialzed hat

Hasher causes some fun in aa-mergeprof: If the profile in
/etc/apparmor.d/ has a hat or subprofile that doesn't exist in the
to-be-merged profile, aa-mergeprof crashes. This is caused by reading
self.other.aa[program][hat]['include'] which accidently "creates" that
profile inside the aa hasher as empty hasher (instead of ProfileStorage).

Later, the code loops over self.other.aa[profile].keys(), expects
everything to be ProfileStorage, and explodes [1] when for example
trying to run .delete_duplicates on the hasher (which obviously doesn't
provide this method).

This patch adds checks to all self.other.aa accesses in
CleanProf.remove_duplicate_rules() to avoid accidently creating new keys
in the hasher.

Interestingly this bug survived unnoticed for years (at least since
2.11).

[1] last lines of the backtrace:
  File ".../utils/apparmor/cleanprofile.py", line 42, in compare_profiles
    deleted += self.remove_duplicate_rules(profile)
  File ".../utils/apparmor/cleanprofile.py", line 65, in remove_duplicate_rules
    deleted += apparmor.delete_duplicates(self.other.aa[program][hat], inc)
  File ".../utils/apparmor/aa.py", line 1680, in delete_duplicates
    deleted += profile[rule_type].delete_duplicates(include[incname][incname][rule_type])
AttributeError: 'collections.defaultdict' object has no attribute 'delete_duplicates'
This commit is contained in:
Christian Boltz
2018-10-11 19:49:26 +02:00
parent 999263c831
commit bc492533cc

View File

@@ -54,20 +54,24 @@ class CleanProf(object):
#If different files remove duplicate includes in the other profile
if not self.same_file:
for inc in includes:
if self.other.aa[program][hat]['include'].get(inc, False):
self.other.aa[program][hat]['include'].pop(inc)
deleted += 1
if self.other.aa[program].get(hat): # carefully avoid to accidently initialize self.other.aa[program][hat]
for inc in includes:
if self.other.aa[program][hat]['include'].get(inc, False):
self.other.aa[program][hat]['include'].pop(inc)
deleted += 1
#Clean up superfluous rules from includes in the other profile
for inc in includes:
if not self.profile.include.get(inc, {}).get(inc, False):
apparmor.load_include(inc)
deleted += apparmor.delete_duplicates(self.other.aa[program][hat], inc)
if self.other.aa[program].get(hat): # carefully avoid to accidently initialize self.other.aa[program][hat]
deleted += apparmor.delete_duplicates(self.other.aa[program][hat], inc)
#Clean duplicate rules in other profile
for ruletype in apparmor.ruletypes:
if not self.same_file:
deleted += self.other.aa[program][hat][ruletype].delete_duplicates(self.profile.aa[program][hat][ruletype])
if self.other.aa[program].get(hat): # carefully avoid to accidently initialize self.other.aa[program][hat]
deleted += self.other.aa[program][hat][ruletype].delete_duplicates(self.profile.aa[program][hat][ruletype])
else:
deleted += self.other.aa[program][hat][ruletype].delete_duplicates(None)