is_known_rule(): check includes recursively

is_known_rule() in aa.py checked only direct includes, but not includes
in the included files. As a result, aa-logprof asked about things that
are already covered by an indirect include.

For example, the dovecot/auth profile includes abstractions/nameservice,
and abstractions/nameservice includes abstractions/nis, which contains
"capability net_bind_service,".
Nevertheless, aa-logprof asked to add capability net_bind_service.

Reproducer: (asks for net_bind_service without this patch, should not
ask for anything after applying the patch):
python3 aa-logprof -d ../profiles/apparmor.d/ -f <(echo 'type=AVC msg=audit(1415403814.628:662): apparmor="ALLOWED" operation="capable" profile="/usr/lib/dovecot/auth" pid=15454 comm="auth" capability=13  capname="net_bind_service"')

The patch adds code to check include files included by other include
files. Note that python doesn't allow to change a list while looping
over it, therefore we have to use "while includelist" as workaround.

This fixes a regression for network rules (this patch is based on the
old match_net_include() code). Funnily it "only" fixes capability rule
handling (without the "regression" part) because the old
match_cap_include() didn't do the recursive include handling.


Acked-by: Steve Beattie <steve@nxnw.org>
This commit is contained in:
Christian Boltz 2015-07-08 22:43:48 +02:00
parent 9e601cb3ac
commit 16de4ee43d

View file

@ -4071,11 +4071,21 @@ def is_known_rule(profile, rule_type, rule_obj):
if profile[rule_type].is_covered(rule_obj, False): if profile[rule_type].is_covered(rule_obj, False):
return True return True
for incname in profile['include'].keys(): includelist = list(profile['include'].keys())
checked = []
while includelist:
incname = includelist.pop(0)
checked.append(incname)
if include[incname][incname].get(rule_type, False): if include[incname][incname].get(rule_type, False):
if include[incname][incname][rule_type].is_covered(rule_obj, False): if include[incname][incname][rule_type].is_covered(rule_obj, False):
return True return True
for childinc in include[incname][incname]['include'].keys():
if childinc not in checked:
includelist += [childinc]
return False return False
def reload_base(bin_path): def reload_base(bin_path):