2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-09-01 06:45:38 +00:00

Accept more log formats in logparser.py

logparser.py does a regex check on log lines as performance improvement
so that it only hands over lines that look like AppArmor events to
LibAppArmor parsing. Those regexes were incomplete and didn't cover all
log formats LibAppArmor accepts, with the end result of "overlooking"
events.

This patch splits off common parts of the regex, adds more regexes for
several log types and finally merges everything into one regex.

test-libapparmor-test_multi.py now also checks all test_multi log lines
against the regex to ensure logparser.py doesn't silently ignore events.

test-logparser.py gets adjusted to the merged RE_LOG_ALL regex.

Finally, add a new test that was posted on IRC to the test_multi set.


As already threatened nearly a month ago,
   Acked by <timeout> for trunk and 2.9
This commit is contained in:
Christian Boltz
2015-10-03 20:18:54 +02:00
parent 1a0294129e
commit ddc56bf3ac
3 changed files with 28 additions and 13 deletions

View File

@@ -26,8 +26,24 @@ from apparmor.translations import init_translation
_ = init_translation()
class ReadLog:
RE_LOG_v2_6_syslog = re.compile('kernel:\s+(\[[\d\.\s]+\]\s+)?(audit:\s+)?type=\d+\s+audit\([\d\.\:]+\):\s+apparmor=')
RE_LOG_v2_6_audit = re.compile('type=AVC\s+(msg=)?audit\([\d\.\:]+\):\s+apparmor=')
RE_audit_time_id = '(msg=)?audit\([\d\.\:]+\):\s+' # 'audit(1282626827.320:411): '
RE_kernel_time = '\[[\d\.\s]+\]' # '[ 1612.746129]'
RE_type_num = '1[45][0-9][0-9]' # 1400..1599
RE_aa_or_op = '(apparmor=|operation=)'
RE_log_parts = [
'kernel:\s+(' + RE_kernel_time + '\s+)?(audit:\s+)?type=' + RE_type_num + '\s+' + RE_audit_time_id + RE_aa_or_op, # v2_6 syslog
'kernel:\s+(' + RE_kernel_time + '\s+)?' + RE_audit_time_id + 'type=' + RE_type_num + '\s+' + RE_aa_or_op,
'type=(AVC|APPARMOR[_A-Z]*|' + RE_type_num + ')\s+' + RE_audit_time_id + '(type=' + RE_type_num + '\s+)?' + RE_aa_or_op, # v2_6 audit and dmesg
'type=USER_AVC\s+' + RE_audit_time_id + '.*apparmor=', # dbus
'type=UNKNOWN\[' + RE_type_num + '\]\s+' + RE_audit_time_id + RE_aa_or_op,
'dbus\[[0-9]+\]:\s+apparmor=', # dbus
]
# used to pre-filter log lines so that we hand over only relevant lines to LibAppArmor parsing
RE_LOG_ALL = re.compile('(' + '|'.join(RE_log_parts) + ')')
# Used by netdomain to identify the operation types
# New socket names
OPERATION_TYPES = {'create': 'net',
@@ -62,7 +78,7 @@ class ReadLog:
if self.next_log_entry:
sys.stderr.out('A log entry already present: %s' % self.next_log_entry)
self.next_log_entry = self.LOG.readline()
while not self.RE_LOG_v2_6_syslog.search(self.next_log_entry) and not self.RE_LOG_v2_6_audit.search(self.next_log_entry) and not (self.logmark and self.logmark in self.next_log_entry):
while not self.RE_LOG_ALL.search(self.next_log_entry) and not (self.logmark and self.logmark in self.next_log_entry):
self.next_log_entry = self.LOG.readline()
if not self.next_log_entry:
break

View File

@@ -44,6 +44,10 @@ class TestLibapparmorTestMulti(AATest):
if parsed_event and expected:
parsed_items = dict(parsed_event.items())
# check if the line passes the regex in logparser.py
if not parser.RE_LOG_ALL.search(loglines2[0]):
raise Exception("Log event doesn't match RE_LOG_ALL")
for label in expected:
if label in [
'file', # filename of the *.in file

View File

@@ -28,8 +28,7 @@ class TestParseEvent(unittest.TestCase):
self.assertEqual(parsed_event['aamode'], 'PERMITTING')
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))
self.assertIsNotNone(ReadLog.RE_LOG_ALL.search(event))
def test_parse_event_audit_2(self):
event = 'type=AVC msg=audit(1322614918.292:4376): apparmor="ALLOWED" operation="file_perm" parent=16001 profile=666F6F20626172 name="/home/foo/.bash_history" pid=17011 comm="bash" requested_mask="rw" denied_mask="rw" fsuid=0 ouid=1000'
@@ -39,8 +38,7 @@ class TestParseEvent(unittest.TestCase):
self.assertEqual(parsed_event['aamode'], 'PERMITTING')
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))
self.assertIsNotNone(ReadLog.RE_LOG_ALL.search(event))
def test_parse_event_syslog_1(self):
# from https://bugs.launchpad.net/apparmor/+bug/1399027
@@ -51,8 +49,7 @@ class TestParseEvent(unittest.TestCase):
self.assertEqual(parsed_event['aamode'], 'PERMITTING')
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))
self.assertIsNotNone(ReadLog.RE_LOG_ALL.search(event))
def test_parse_event_syslog_2(self):
# from https://bugs.launchpad.net/apparmor/+bug/1399027
@@ -63,8 +60,7 @@ class TestParseEvent(unittest.TestCase):
self.assertEqual(parsed_event['aamode'], 'PERMITTING')
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))
self.assertIsNotNone(ReadLog.RE_LOG_ALL.search(event))
def test_parse_disconnected_path(self):
# from https://bugzilla.opensuse.org/show_bug.cgi?id=918787
@@ -91,8 +87,7 @@ class TestParseEvent(unittest.TestCase):
'time': 1424425690
})
self.assertIsNotNone(ReadLog.RE_LOG_v2_6_audit.search(event))
self.assertIsNone(ReadLog.RE_LOG_v2_6_syslog.search(event))
self.assertIsNotNone(ReadLog.RE_LOG_ALL.search(event))
if __name__ == "__main__":