Hello,

this patch adds various tests for set_profile_flags, and documents 
various interesting[tm] things I discovered while writing the tests (see 
the inline comments for details).


The most interesting[tm] thing I found is:
    regex_hat_flag = re.compile('^([a-z]*)\s+([A-Z]*)\s*(#.*)?$') 

I found a match, that, well, probably shouldn't match ;-)
    regex_hat_flag.search('   ')
(yes, really!)

oh, and it does _NOT_ match for real hat definitions like '  ^hat {'

You want more fun? Take this profile

/foo {
dbus
  ,
}

Now run set_profile_flags() on it and, voila:

/foo flags=(complain) {
dbus flags=(complain) {
     ,
 }

Funny, eh?


After so much fun, I also have some tests:


[ 15-add-tests-for-set_profile_flags.diff ]

--- utils/test/test-aa.py       2015-03-05 23:16:18.971117710 +0100
+++ utils/test/test-aa.py       2015-03-05 23:14:41.790946858 +0100
@@ -15,7 +15,7 @@ import shutil
 import tempfile
 from common_test import write_file
 
-from apparmor.aa import check_for_apparmor, get_profile_flags, 
is_skippable_file, parse_profile_start, serialize_parse_profile_start
+from apparmor.aa import check_for_apparmor, get_profile_flags, 
set_profile_flags, is_skippable_file, parse_profile_start, 
serialize_parse_profile_start
 from apparmor.common import AppArmorException, AppArmorBug
 
 class AaTestWithTempdir(unittest.TestCase):
@@ -104,6 +104,100 @@ class AaTest_get_profile_flags(AaTestWit
         with self.assertRaises(AppArmorException):
             self._test_get_flags('/no-such-profile flags=(complain)', 
'complain')
 
+class AaTest_set_profile_flags(AaTestWithTempdir):
+    def _test_set_flags(self, old_profile_header, flags, whitespace = '', 
comment = '', expected_flags = '@-@-@', check_new_flags = True, 
profile_name='/foo'):
+        self.file = write_file(self.tmpdir, 'profile', '%s%s {%s\n}\n' % 
(whitespace, old_profile_header, comment))
+        set_profile_flags(self.file, profile_name, flags)
+        if check_new_flags:
+            newflags = get_profile_flags(self.file, profile_name)
+            if expected_flags == '@-@-@':
+                expected_flags = flags
+            self.assertEqual(expected_flags, newflags)
+
+    # tests that actually don't change the flags
+    def test_set_flags_nochange_01(self):
+        self._test_set_flags('/foo', None)
+    def test_set_flags_nochange_02(self):
+        self._test_set_flags('/foo (  complain  )', '  complain  ', 
whitespace='   ')
+    def test_set_flags_nochange_03(self):
+        self._test_set_flags('/foo (complain)', 'complain')
+    def test_set_flags_nochange_04(self):
+        self._test_set_flags('/foo flags=(complain)', 'complain')
+    def test_set_flags_nochange_05(self):
+        self._test_set_flags('/foo flags=(complain,  audit)', 'complain,  
audit', whitespace='     ')
+    def test_set_flags_nochange_06(self):
+        self._test_set_flags('/foo flags=(complain,  audit)', 'complain,  
audit', whitespace='     ', comment=' # a comment')
+        # XXX check if the comment is kept
+    def test_set_flags_nochange_07(self):
+        self._test_set_flags('/foo flags=(complain,  audit)', 'complain,  
audit', whitespace='     ', comment='\n\n# a comment')
+        # XXX check if the comment is kept
+    def test_set_flags_nochange_08(self):
+        self._test_set_flags('profile /foo flags=(complain)', 'complain')
+    def test_set_flags_nochange_09(self):
+        self._test_set_flags('profile xy /foo flags=(complain)', 'complain', 
profile_name='xy /foo') # XXX profile_name should be 'xy'
+        #newflags = get_profile_flags(self.file, 'xy /foo')
+        #self.assertEqual(newflags, 'complain')
+
+    # tests that change the flags
+    def test_set_flags_01(self):
+        self._test_set_flags('/foo', 'audit')
+    def test_set_flags_02(self):
+        self._test_set_flags('/foo (  complain  )', 'audit ', whitespace='  ')
+    def test_set_flags_04(self):
+        self._test_set_flags('/foo (complain)', 'audit')
+    def test_set_flags_05(self):
+        self._test_set_flags('/foo flags=(complain)', 'audit')
+    def test_set_flags_06(self):
+        self._test_set_flags('/foo flags=(complain,  audit)', None, 
whitespace='    ')
+    def test_set_flags_07(self):
+        self._test_set_flags('/foo flags=(complain,  audit)', '', 
expected_flags=None)
+    def test_set_flags_08(self):
+        with self.assertRaises(AppArmorException):
+            # XXX '  ' should not make the profile invalid
+            self._test_set_flags('/foo flags=(complain,  audit)', '  ', 
expected_flags=None)
+    def test_set_flags_09(self):
+        self._test_set_flags('profile /foo flags=(complain)', 'audit')
+    def test_set_flags_10(self):
+        self._test_set_flags('profile xy /foo flags=(complain)', 'audit', 
profile_name='xy /foo') # XXX profile_name should be 'xy'
+
+    # XXX regex_hat_flag in set_profile_flags() is totally broken - it matches 
for '   ' and '  X ', but doesn't match for ' ^foo {'
+    # oh, it matches on a line like 'dbus' and changes it to 'dbus 
flags=(...)' if there's no leading whitespace (and no comma)
+    #def test_set_flags_hat_01(self):
+    #    self._test_set_flags('  ^hat {', 'audit')
+
+
+    # XXX current code/regex doesn't check for empty flags
+    #def test_set_flags_invalid_01(self):
+    #    with self.assertRaises(AppArmorBug):
+    #        self._test_set_flags('/foo ()', None, check_new_flags=False)
+    #def test_set_flags_invalid_02(self):
+    #    with self.assertRaises(AppArmorBug):
+    #        self._test_set_flags('/foo flags=()', None, check_new_flags=False)
+    #def test_set_flags_invalid_03(self):
+    #    with self.assertRaises(AppArmorException):
+    #        self._test_set_flags('/foo (  )', '  ', check_new_flags=False)
+
+    def test_set_flags_other_profile(self):
+        # test behaviour if the file doesn't contain the specified /foo profile
+
+        # XXX this silently fails - should it raise an exception instead?
+        self._test_set_flags('/no-such-profile flags=(complain)', 'audit', 
check_new_flags=False)
+
+        # the file should still not contain a profile for /foo
+        with self.assertRaises(AppArmorException):
+            newflags = get_profile_flags(self.file, '/foo')
+
+        # nothing should change for /no-such-profile
+        newflags = get_profile_flags(self.file, '/no-such-profile')
+        self.assertEqual(newflags, 'complain')
+
+    def test_set_flags_file_not_found(self):
+        # XXX this exits silently
+        # the easiest solution would be to drop the
+        #         if os.path.isfile(prof_filename):
+        # check and let open_file_read raise an exception
+        set_profile_flags('%s/file-not-found' % self.tmpdir, '/foo', 'audit')
+
 
 class AaTest_is_skippable_file(unittest.TestCase):
     def test_not_skippable_01(self):




Regards,

Christian Boltz
-- 
Key Signing Party? Was ist denn das?
Kultiges Zusammensitzen und gemeinsames Murmeln magischer Zahlen.
-- Gert Döring, FdI 95


-- 
AppArmor mailing list
AppArmor@lists.ubuntu.com
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/apparmor

Reply via email to