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