Hello,

this patch moves the code that does the c -> a and d -> w replacement
in denied_mask and requested_mask so that it only runs for path events,
but not for other events (like dbus and ptrace). The validate_log_mode() 
and log_str_to_mode() calls are also moved.
                                                  
Technically, this means moving code from parse_event() to the path
section in add_event_to_tree().

This also means aa-logprof no longer crashes if it hits a ptrace or
dbus event in the log.

The "if dmask:" and "if rmask:" checks are removed - if a path event
doesn't have these two, it is totally broken and worth a aa-logprof
crash ;-)
 
Also adjust the parse_event() tests to expect the "raw" mask instead of
a set.


This patch fixes
https://bugs.launchpad.net/apparmor/+bug/1426651 and
https://bugs.launchpad.net/apparmor/+bug/1243932


I manually tested that
- c and d log events are still converted to a and w
- ptrace events no longer crash aa-logprof

Note: add_event_to_tree() is not covered by tests.



[ 30-logparser-change-mask-only-for-path-events.diff ]

=== modified file utils/apparmor/logparser.py
--- utils/apparmor/logparser.py 2015-03-29 21:23:50.441294500 +0200
+++ utils/apparmor/logparser.py 2015-03-29 22:25:37.256978665 +0200
@@ -112,34 +112,14 @@
         ev['task'] = event.task
         ev['info'] = event.info
         ev['error_code'] = event.error_code
-        dmask = event.denied_mask
-        rmask = event.requested_mask
+        ev['denied_mask'] = event.denied_mask
+        ev['request_mask'] = event.requested_mask
         ev['magic_token'] = event.magic_token
         if ev['operation'] and self.op_type(ev['operation']) == 'net':
             ev['family'] = event.net_family
             ev['protocol'] = event.net_protocol
             ev['sock_type'] = event.net_sock_type
         LibAppArmor.free_record(event)
-        # Map c (create) to a and d (delete) to w, logprof doesn't support c 
and d
-        if rmask:
-            rmask = rmask.replace('c', 'a')
-            rmask = rmask.replace('d', 'w')
-            if not validate_log_mode(hide_log_mode(rmask)):
-                raise AppArmorException(_('Log contains unknown mode %s') % 
rmask)
-        if dmask:
-            dmask = dmask.replace('c', 'a')
-            dmask = dmask.replace('d', 'w')
-            if not validate_log_mode(hide_log_mode(dmask)):
-                raise AppArmorException(_('Log contains unknown mode %s') % 
dmask)
-        #print('parse_event:', ev['profile'], dmask, ev['name2'])
-        mask, name = log_str_to_mode(ev['profile'], dmask, ev['name2'])
-
-        ev['denied_mask'] = mask
-        ev['name2'] = name
-
-        mask, name = log_str_to_mode(ev['profile'], rmask, ev['name2'])
-        ev['request_mask'] = mask
-        ev['name2'] = name
 
         if not ev['time']:
             ev['time'] = int(time.time())
@@ -267,7 +247,25 @@
             e['operation'] in ['open', 'truncate', 'mkdir', 'mknod', 'chmod', 
'rename_src',
                                 'rename_dest', 'unlink', 'rmdir', 
'symlink_create', 'link',
                                 'sysctl', 'getattr', 'setattr', 'xattr'] ):
-            #print(e['operation'], e['name'])
+
+            # Map c (create) to a and d (delete) to w (logging is more 
detailed than the profile language)
+            rmask = e['request_mask']
+            rmask = rmask.replace('c', 'a')
+            rmask = rmask.replace('d', 'w')
+            if not validate_log_mode(hide_log_mode(rmask)):
+                raise AppArmorException(_('Log contains unknown mode %s') % 
rmask)
+
+            dmask = e['denied_mask']
+            dmask = dmask.replace('c', 'a')
+            dmask = dmask.replace('d', 'w')
+            if not validate_log_mode(hide_log_mode(dmask)):
+                raise AppArmorException(_('Log contains unknown mode %s') % 
dmask)
+
+            # convert rmask and dmask to mode arrays
+            e['denied_mask'],  e['name2'] = log_str_to_mode(e['profile'], 
dmask, e['name2'])
+            e['request_mask'], e['name2'] = log_str_to_mode(e['profile'], 
rmask, e['name2'])
+
+            # check if this is an exec event
             is_domain_change = False
             if e['operation'] == 'inode_permission' and (e['denied_mask'] & 
AA_MAY_EXEC) and aamode == 'PERMITTING':
                 following = self.peek_at_next_log_entry()
=== modified file utils/test/test-capability.py
--- utils/test/test-capability.py       2015-03-03 19:52:15.160640000 +0100
+++ utils/test/test-capability.py       2015-03-29 22:41:54.412007617 +0200
@@ -102,8 +102,8 @@
         parsed_event = parser.parse_event(event)
 
         self.assertEqual(parsed_event, {
-            'request_mask': set(),
-            'denied_mask': set(),
+            'request_mask': None,
+            'denied_mask': None,
             'error_code': 0,
             'magic_token': 0,
             'parent': 0,
=== modified file utils/test/test-logparser.py
--- utils/test/test-logparser.py        2015-03-03 22:16:55.549199117 +0100
+++ utils/test/test-logparser.py        2015-03-29 22:41:02.093109280 +0200
@@ -1,5 +1,6 @@
 # ----------------------------------------------------------------------
 #    Copyright (C) 2013 Kshitij Gupta <kgupta8...@gmail.com>
+#    Copyright (C) 2015 Christian Boltz <appar...@cboltz.de>
 #
 #    This program is free software; you can redistribute it and/or
 #    modify it under the terms of version 2 of the GNU General Public
@@ -26,7 +26,7 @@
         self.assertEqual(parsed_event['name'], 
'/home/www/foo.bar.in/httpdocs/apparmor/images/test/image 1.jpg')
         self.assertEqual(parsed_event['profile'], 
'/usr/sbin/httpd2-prefork//vhost_foo')
         self.assertEqual(parsed_event['aamode'], 'PERMITTING')
-        self.assertEqual(parsed_event['request_mask'], set(['w', 'a', '::w', 
'::a']))
+        self.assertEqual(parsed_event['request_mask'], 'wc')
 
         self.assertIsNotNone(ReadLog.RE_LOG_v2_6_audit.search(event))
         self.assertIsNone(ReadLog.RE_LOG_v2_6_syslog.search(event))
@@ -37,7 +37,7 @@
         self.assertEqual(parsed_event['name'], '/home/foo/.bash_history')
         self.assertEqual(parsed_event['profile'], 'foo bar')
         self.assertEqual(parsed_event['aamode'], 'PERMITTING')
-        self.assertEqual(parsed_event['request_mask'], set(['r', 'w', 
'a','::r' , '::w', '::a']))
+        self.assertEqual(parsed_event['request_mask'], 'rw')
 
         self.assertIsNotNone(ReadLog.RE_LOG_v2_6_audit.search(event))
         self.assertIsNone(ReadLog.RE_LOG_v2_6_syslog.search(event))
@@ -49,7 +49,7 @@
         self.assertEqual(parsed_event['name'], '/dev/tty')
         self.assertEqual(parsed_event['profile'], 
'/home/cb/linuxtag/apparmor/scripts/hello')
         self.assertEqual(parsed_event['aamode'], 'PERMITTING')
-        self.assertEqual(parsed_event['request_mask'], set(['r', 'w', 'a', 
'::r', '::w', '::a']))
+        self.assertEqual(parsed_event['request_mask'], 'rw')
 
         self.assertIsNone(ReadLog.RE_LOG_v2_6_audit.search(event))
         self.assertIsNotNone(ReadLog.RE_LOG_v2_6_syslog.search(event))
@@ -61,7 +61,7 @@
         self.assertEqual(parsed_event['name'], '/usr/bin/')
         self.assertEqual(parsed_event['profile'], '/home/simi/bin/aa-test')
         self.assertEqual(parsed_event['aamode'], 'PERMITTING')
-        self.assertEqual(parsed_event['request_mask'], set(['r', '::r']))
+        self.assertEqual(parsed_event['request_mask'], 'r')
 
         self.assertIsNone(ReadLog.RE_LOG_v2_6_audit.search(event))
         self.assertIsNotNone(ReadLog.RE_LOG_v2_6_syslog.search(event))
@@ -75,7 +75,7 @@
             'aamode': 'ERROR',   # aamode for disconnected paths overridden 
aamode in parse_event()
             'active_hat': None,
             'attr': None,
-            'denied_mask': {'r', '::r'},
+            'denied_mask': 'r',
             'error_code': 13,
             'info': 'Failed name lookup - disconnected path',
             'magic_token': 0,
@@ -85,7 +85,7 @@
             'parent': 0,
             'pid': 25333,
             'profile': '/sbin/klogd',
-            'request_mask': {'r', '::r'},
+            'request_mask': 'r',
             'resource': 'Failed name lookup - disconnected path',
             'task': 0,
             'time': 1424425690



Regards,

Christian Boltz
-- 
Some gone-crazy stupid laywer filled tags with *PAGES* of license
restriction. Overwhelming mass of data made fontlinge_base believe
the font to be broken.
- increased limits
- going to get a gun   [Ratti in fontlinge-cvs]


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

Reply via email to