From 80bfb955acd6a7cc84764a4b412e6c9a39c9b27c Mon Sep 17 00:00:00 2001 From: Christian Boltz Date: Mon, 23 May 2016 23:24:30 +0200 Subject: [PATCH] [9/9] Add support for dbus events to aa-logprof In detail, this means: - handle ptrace events in logparser.py - "translate" those events in aa.py - from log (logparser.py readlog()) to prelog (handle_children()) to log_dict (collapse_log())) - finally ask the user about the ptrace in ask_the_questions() (no code change needed there) Note that these changes are not covered by tests, however they worked in a manual test with the log examples in the libapparmor testsuite. Unfortunately there's no example log for eavesdrop, so it might be a good idea to a) add such a log line and b) test with it Acked-by: Seth Arnold Note: as discussed on #apparmor, I changed the mapping of peer_profile so that it ends up in peer=(label=...) instead of the wrong peer=(name=...). --- utils/apparmor/aa.py | 32 ++++++++++++++++++++++++++++++++ utils/apparmor/logparser.py | 3 +++ 2 files changed, 35 insertions(+) diff --git a/utils/apparmor/aa.py b/utils/apparmor/aa.py index eba3b9e01..5f0701442 100644 --- a/utils/apparmor/aa.py +++ b/utils/apparmor/aa.py @@ -1122,6 +1122,16 @@ def handle_children(profile, hat, root): continue prelog[aamode][profile][hat]['capability'][capability] = True + elif typ == 'dbus': + # If dbus then we (should) have pid, profile, hat, program, mode, access, bus, name, path, interface, member, peer_profile + pid, p, h, prog, aamode, access, bus, path, name, interface, member, peer_profile = entry + if not regex_nullcomplain.search(p) and not regex_nullcomplain.search(h): + profile = p + hat = h + if not profile or not hat: + continue + prelog[aamode][profile][hat]['dbus'][access][bus][path][name][interface][member][peer_profile] = True + elif typ == 'ptrace': # If ptrace then we (should) have pid, profile, hat, program, mode, access and peer pid, p, h, prog, aamode, access, peer = entry @@ -2440,6 +2450,28 @@ def collapse_log(): if not is_known_rule(aa[profile][hat], 'capability', cap_event): log_dict[aamode][profile][hat]['capability'].add(cap_event) + dbus = prelog[aamode][profile][hat]['dbus'] + for access in dbus: + for bus in dbus[access]: + for path in dbus[access][bus]: + for name in dbus[access][bus][path]: + for interface in dbus[access][bus][path][name]: + for member in dbus[access][bus][path][name][interface]: + for peer_profile in dbus[access][bus][path][name][interface][member]: + # Depending on the access type, not all parameters are allowed. + # Ignore them, even if some of them appear in the log. + # Also, the log doesn't provide a peer name, therefore always use ALL. + if access in ['send', 'receive']: + dbus_event = DbusRule(access, bus, path, DbusRule.ALL, interface, member, DbusRule.ALL, peer_profile, log_event=True) + elif access == 'bind': + dbus_event = DbusRule(access, bus, DbusRule.ALL, name, DbusRule.ALL, DbusRule.ALL, DbusRule.ALL, DbusRule.ALL, log_event=True) + elif access == 'eavesdrop': + dbus_event = DbusRule(access, bus, DbusRule.ALL, DbusRule.ALL, DbusRule.ALL, DbusRule.ALL, DbusRule.ALL, DbusRule.ALL, log_event=True) + else: + raise AppArmorBug('unexpected dbus access: %s') + + log_dict[aamode][profile][hat]['dbus'].add(dbus_event) + nd = prelog[aamode][profile][hat]['netdomain'] for family in nd.keys(): for sock_type in nd[family].keys(): diff --git a/utils/apparmor/logparser.py b/utils/apparmor/logparser.py index 4adb30d61..925845391 100644 --- a/utils/apparmor/logparser.py +++ b/utils/apparmor/logparser.py @@ -371,6 +371,9 @@ class ReadLog: elif e['operation'] == 'signal': return(e['pid'], e['parent'], 'signal', [profile, hat, prog, aamode, e['denied_mask'], e['signal'], e['peer']]) + elif e['operation'].startswith('dbus_'): + return(e['pid'], e['parent'], 'dbus', + [profile, hat, prog, aamode, e['denied_mask'], e['bus'], e['path'], e['name'], e['interface'], e['member'], e['peer_profile']]) else: self.debug_logger.debug('UNHANDLED: %s' % e)