aa-genprof: crash in is_known_rule

Bug #1673028 reported by john
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
AppArmor
New
Undecided
Unassigned

Bug Description

Details are as follows.
Could it be a problem with python installation?
I have this same bug in work and at home.

KeyError
Python 3.4.5: /usr/bin/python3.4

A problem occurred in a Python script. Here is the sequence of
function calls leading up to the error, in the order they occurred.

 /usr/lib/python-exec/python3.4/aa-genprof in <module>()
  100
  101 profile_filename = apparmor.get_profile_filename(program)
  102 if os.path.exists(profile_filename):
  103 apparmor.helpers[program] = apparmor.get_profile_flags(profile_filename, program)
  104 else:
  105 apparmor.autodep(program)
  106 apparmor.helpers[program] = 'enforce'
  107
  108 if apparmor.helpers[program] == 'enforce':
  109 apparmor.complain(program)
apparmor = <module 'apparmor.aa' from '/usr/lib64/python3.4/site-packages/apparmor/aa.py'>
apparmor.autodep = <function autodep>
program = '/usr/sbin/tcpdump'

 /usr/lib64/python3.4/site-packages/apparmor/aa.py in autodep(bin_name='/usr/sbin/tcpdump', pname='/usr/sbin/tcpdump')
  647 pname = bin_full
  648 read_inactive_profiles()
  649 profile_data = get_profile(pname)
  650 # Create a new profile if no existing profile
  651 if not profile_data:
  652 profile_data = create_new_profile(pname)
  653 file = get_profile_filename(pname)
  654 profile_data[pname][pname]['filename'] = None # will be stored in /etc/apparmor.d when saving, so it shouldn't carry the extra_profile_dir filename
  655 attach_profile_data(aa, profile_data)
  656 attach_profile_data(original_aa, profile_data)
profile_data = None
global create_new_profile = <function create_new_profile>
pname = '/usr/sbin/tcpdump'

 /usr/lib64/python3.4/site-packages/apparmor/aa.py in create_new_profile(localfile='/usr/sbin/tcpdump', is_stub=False)
  493
  494 handle_binfmt(local_profile[localfile], interpreter_path)
  495 else:
  496 local_profile[localfile]['file'].add(FileRule(localfile, 'mr', None, FileRule.ALL, owner=False))
  497
  498 handle_binfmt(local_profile[localfile], localfile)
  499 # Add required hats to the profile if they match the localfile
  500 for hatglob in cfg['required_hats'].keys():
  501 if re.search(hatglob, localfile):
  502 for hat in sorted(cfg['required_hats'][hatglob].split()):
global handle_binfmt = <function handle_binfmt>
local_profile = defaultdict(<function hasher at 0x7f2fddf95d90>,...e_new_profile()', 'hat': '/usr/sbin/tcpdump'}})})
localfile = '/usr/sbin/tcpdump'

 /usr/lib64/python3.4/site-packages/apparmor/aa.py in handle_binfmt(profile=defaultdict(<function hasher at 0x7f2fddf95d90>,...ate_new_profile()', 'hat': '/usr/sbin/tcpdump'}}), path='/usr/sbin/tcpdump')
  392 reqs += get_reqs(library)
  393 reqs_processed[library] = True
  394
  395 library_rule = FileRule(library, 'mr', None, FileRule.ALL, owner=False, log_event=True)
  396
  397 if not is_known_rule(profile, 'file', library_rule):
  398 globbed_library = glob_common(library)
  399 if globbed_library:
  400 # glob_common returns a list, just use the first element (typically '/lib/libfoo.so.*')
  401 library_rule = FileRule(globbed_library[0], 'mr', None, FileRule.ALL, owner=False)
global is_known_rule = <function is_known_rule>
profile = defaultdict(<function hasher at 0x7f2fddf95d90>,...ate_new_profile()', 'hat': '/usr/sbin/tcpdump'}})
library_rule = <FileRule> /lib64/libpthread-2.23.so mr,

 /usr/lib64/python3.4/site-packages/apparmor/aa.py in is_known_rule(profile=defaultdict(<function hasher at 0x7f2fddf95d90>,...ate_new_profile()', 'hat': '/usr/sbin/tcpdump'}}), rule_type='file', rule_obj=<FileRule> /lib64/libpthread-2.23.so mr,)
 3448 checked.append(incname)
 3449
 3450 if os.path.isdir(profile_dir + '/' + incname):
 3451 includelist += include_dir_filelist(profile_dir, incname)
 3452 else:
 3453 if include[incname][incname].get(rule_type, False):
 3454 if include[incname][incname][rule_type].is_covered(rule_obj, False):
 3455 return True
 3456
 3457 for childinc in include[incname][incname]['include'].keys():
global include = {}
incname = 'abstractions/base'
].get undefined
rule_type = 'file'
KeyError: 'abstractions/base'
    __cause__ = None
    __class__ = <class 'KeyError'>
    __context__ = None
    __delattr__ = <method-wrapper '__delattr__' of KeyError object>
    __dict__ = {}
    __dir__ = <built-in method __dir__ of KeyError object>
    __doc__ = 'Mapping key not found.'
    __eq__ = <method-wrapper '__eq__' of KeyError object>
    __format__ = <built-in method __format__ of KeyError object>
    __ge__ = <method-wrapper '__ge__' of KeyError object>
    __getattribute__ = <method-wrapper '__getattribute__' of KeyError object>
    __gt__ = <method-wrapper '__gt__' of KeyError object>
    __hash__ = <method-wrapper '__hash__' of KeyError object>
    __init__ = <method-wrapper '__init__' of KeyError object>
    __le__ = <method-wrapper '__le__' of KeyError object>
    __lt__ = <method-wrapper '__lt__' of KeyError object>
    __ne__ = <method-wrapper '__ne__' of KeyError object>
    __new__ = <built-in method __new__ of type object>
    __reduce__ = <built-in method __reduce__ of KeyError object>
    __reduce_ex__ = <built-in method __reduce_ex__ of KeyError object>
    __repr__ = <method-wrapper '__repr__' of KeyError object>
    __setattr__ = <method-wrapper '__setattr__' of KeyError object>
    __setstate__ = <built-in method __setstate__ of KeyError object>
    __sizeof__ = <built-in method __sizeof__ of KeyError object>
    __str__ = <method-wrapper '__str__' of KeyError object>
    __subclasshook__ = <built-in method __subclasshook__ of type object>
    __suppress_context__ = False
    __traceback__ = <traceback object>
    args = ('abstractions/base',)
    with_traceback = <built-in method with_traceback of KeyError object>

The above is a description of an error in a Python program. Here is
the original traceback:

Traceback (most recent call last):
  File "/usr/lib/python-exec/python3.4/aa-genprof", line 105, in <module>
    apparmor.autodep(program)
  File "/usr/lib64/python3.4/site-packages/apparmor/aa.py", line 652, in autodep
    profile_data = create_new_profile(pname)
  File "/usr/lib64/python3.4/site-packages/apparmor/aa.py", line 498, in create_new_profile
    handle_binfmt(local_profile[localfile], localfile)
  File "/usr/lib64/python3.4/site-packages/apparmor/aa.py", line 397, in handle_binfmt
    if not is_known_rule(profile, 'file', library_rule):
  File "/usr/lib64/python3.4/site-packages/apparmor/aa.py", line 3453, in is_known_rule
    if include[incname][incname].get(rule_type, False):
KeyError: 'abstractions/base'

Tags: aa-tools
Revision history for this message
Christian Boltz (cboltz) wrote :

That looks like you don't have an abstractions/base file (actually you don't seem to have any abstractions/* file), which would be very unusual.

Can you please exist if /etc/apparmor.d/abstractions/base exists on your system?

The bug itsself is easy to explain - create_new_profile() blindly assumes abstractions/base exists and adds it to the profile. It's not surprising that this explodes later - checking something in a non-existing file rarely works ;-)

tags: added: aa-tools
Revision history for this message
Seth Arnold (seth-arnold) wrote :

It might be nice to modify the tools to only #include <abstractions/base> if it actually exists. We should aim to keep the tools entirely separate from the policy for those who need to replace the policy entirely.

Thanks

Revision history for this message
john (staticc) wrote :

It is awkward, but it was my fault.
I an on Gentoo and I did not have installed 'sec-policy/apparmor-profiles'.
I saw 'sec-policy' and subconsciously associated it with selinux.
That is why I omitted it.
Beats me why.

But thanks for the hint.
Now it works as it supposed to.

On a small different note.
aa-genprof kept complaining about "ERROR: Include file /etc/apparmor.d/local/usr.sbin.sshd not found".
Even if I run it with completely unrelated app, like tcpdump or spotify.
I had to create empty '/etc/apparmor.d/local/usr.sbin.sshd' to make it work.

Revision history for this message
Seth Arnold (seth-arnold) wrote :

Hi John, that's expected behaviour. Sort of. Most of the python-based tools will read all the profiles in /etc/apparmor.d/ in order to learn which profiles are stored in which files. Thus there's no way to avoid errors in one profile causing annoyances when trying to profile something else.

But I'm surprised that the local/usr.sbin.sshd file wasn't on your system, to avoid exactly this situation. Do you have any guesses how you got an sshd profile without the corresponding local/usr.sbin.sshd file?

Thanks

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.