[apparmor] [patch] fix save_profile() by fixing some other code

Christian Boltz apparmor at cboltz.de
Thu May 29 18:47:22 UTC 2014


Hello,

when creating a child profile while using genprof, I get a backtrace:

Traceback (most recent call last):
  File "aa-genprof", line 160, in <module>
    lp_ret = apparmor.do_logprof_pass(logmark, passno)
  File "/home/cb/apparmor/HEAD-CLEAN/utils/apparmor/aa.py", line 2291, in do_logprof_pass
    save_profiles()
  File "/home/cb/apparmor/HEAD-CLEAN/utils/apparmor/aa.py", line 2309, in save_profiles
    for prof_name in changed.keys():
RuntimeError: dictionary changed size during iteration

(See https://bugs.launchpad.net/apparmor/+bug/1014304 for more details.)


After digging into the code, it seems for some reason the child profile 
is added to "changed" - I doubt this is correct (guess why it's removed 
later... ;-)

After digging a bit more, I found out that create_new_profile() is 
(ab)used to create a new stub profile to be used as child profile. 
create_new_profile then adds the new child (which looks like a normal 
profile to it) to "changed".

This patch most probably makes the cleanup round in save_profile() 
superfluous by adding a is_stub parameter to create_new_profile(). If
this parameter is set, the new (child) profile is not added to "created" 
and "changed".


=== modified file 'utils/apparmor/aa.py'
--- utils/apparmor/aa.py        2014-05-29 14:53:02 +0000
+++ utils/apparmor/aa.py        2014-05-29 18:22:37 +0000
@@ -386,7 +386,7 @@
         return {local_profile: extras[local_profile]}
     return dict()
 
-def create_new_profile(localfile):
+def create_new_profile(localfile, is_stub = False):
     local_profile = hasher()
     local_profile[localfile]['flags'] = 'complain'
     local_profile[localfile]['include']['abstractions/base'] = 1
@@ -428,8 +428,9 @@
             for hat in sorted(cfg['required_hats'][hatglob].split()):
                 local_profile[hat]['flags'] = 'complain'
 
-    created.append(localfile)
-    changed[localfile] = True
+    if not is_stub:
+        created.append(localfile)
+        changed[localfile] = True
 
     debug_logger.debug("Profile for %s:\n\t%s" % (localfile, local_profile.__str__()))
     return {localfile: local_profile}
@@ -1411,7 +1421,7 @@
                                 if profile != hat:
                                     aa[profile][hat]['flags'] = aa[profile][profile]['flags']
 
-                                stub_profile = create_new_profile(hat)
+                                stub_profile = create_new_profile(hat, True)
 
                                 aa[profile][hat]['flags'] = 'complain'
 
@@ -2299,6 +2309,8 @@
     # Ensure the changed profiles are actual active profiles
     for prof_name in changed.keys():
         if not is_active_profile(prof_name):
+            print("*** save_profiles(): removing %s"%prof_name)
+            print('*** This should not happen. Please open a bugreport!')
             changed.pop(prof_name)
 
     changed_list = sorted(changed.keys())


BTW: I intentionally added the two print() lines in safe_profile because
a) I think they will never be displayed
b) I want to know if a is wrong ;-)
c) it's always nice to have a "nice" error message before displaying
   a backtrace ;-)

A final note: I hereby officially blame Steve for introducing this bug 
in AppArmor.pm r2019 without checking the side effects of this function.
(Kshitij is innocent because he just translated this well-hidden bug to
python ;-)


Regards,

Christian Boltz
-- 
Möglicherweise laufe ich sogar mit fliegenden Fahnen von Gnome zu KDE
über. Jedenfalls, bis sich das Gnome-Projekt dazu entschliesst, Nautilus
durch /irgendwas/ zu ersetzen. Notfalls eine Parkuhr oder einen
Bratenwender. Aber nicht dieses.... "Ding". [Ratti in suse-linux]




More information about the AppArmor mailing list