Hello, Am Montag, 25. Mai 2015 schrieb Christian Boltz: > [ 27-logprof-use-mergeprof-code-for-capability.diff ]
I should run "make check" more often :-/ I overlooked a "self.aa." (and didn't run into it in my manual tests), so here's v2 with this fixed. This patch replaces the code in aa.py ask_the_questions() that handles capabilities with the ask_the_questions() code from aa-mergeprof. This means to convert the capability log events to a CapabilityRuleset stored in the (new) log_obj hasher, and then let the code from aa-mergeprof operate on this hasher. Most of the code after the "aa-mergeprof also has this code" comment is a direct copy of the aa-mergeprof code, with the following changes: - filter for profile mode (enforce/complain) - set default button (allow or deny) based on profile mode - keep seen_events counter happy (even if it isn't displayed anywhere) - replace apparmor.aa.foo with just foo The user interface is mostly unchanged, with two exceptions: - options always displayed, even if there is only one option - some slightly changed texts BTW: I'm not sure if filtering and having different default buttons based on the profile mode makes sense, except for "historical reasons". Opinions? [ 27-logprof-use-mergeprof-code-for-capability.diff ] === modified file utils/apparmor/aa.py --- utils/apparmor/aa.py 2015-05-25 11:46:12.709387529 +0200 +++ utils/apparmor/aa.py 2015-05-25 11:46:08.085653465 +0200 @@ -1541,6 +1541,7 @@ def ask_the_questions(): found = 0 global seen_events + log_obj = hasher() for aamode in sorted(log_dict.keys()): # Describe the type of changes if aamode == 'PERMITTING': @@ -1564,106 +1565,107 @@ hats = [profile] + hats for hat in hats: + if not log_obj[profile][hat].get('capability', False): + log_obj[profile][hat]['capability'] = CapabilityRuleset() + for capability in sorted(log_dict[aamode][profile][hat]['capability'].keys()): - # skip if capability already in profile - capability_obj = CapabilityRule(capability) - if is_known_rule(aa[profile][hat], 'capability', capability_obj): - continue - # Load variables into sev_db? Not needed/used for capabilities. - severity = capability_obj.severity(sev_db) - default_option = 1 - options = [] - newincludes = match_includes(aa[profile][hat], 'capability', capability_obj) - q = aaui.PromptQuestion() + capability_obj = CapabilityRule(capability, log_event=aamode) + log_obj[profile][hat]['capability'].add(capability_obj) - if newincludes: - options += list(map(lambda inc: '#include <%s>' % inc, sorted(set(newincludes)))) + for ruletype in ['capability']: + # XXX aa-mergeprof also has this code - if you change it, keep aa-mergeprof in sync! + for rule_obj in log_obj[profile][hat][ruletype].rules: + + if rule_obj.log_event != aamode: # XXX does it really make sense to handle enforce and complain mode changes in different rounds? + continue + + if is_known_rule(aa[profile][hat], ruletype, rule_obj): + continue + + default_option = 1 + options = [] + newincludes = match_includes(aa[profile][hat], ruletype, rule_obj) + q = aaui.PromptQuestion() + if newincludes: + options += list(map(lambda inc: '#include <%s>' % inc, sorted(set(newincludes)))) - if options: - options.append('capability %s' % capability) + options.append(rule_obj.get_clean()) q.options = options q.selected = default_option - 1 - q.headers = [_('Profile'), combine_name(profile, hat)] - q.headers += [_('Capability'), capability] - q.headers += [_('Severity'), severity] - - audit_toggle = 0 - audit = '' - - q.functions = ['CMD_ALLOW', 'CMD_DENY', 'CMD_IGNORE_ENTRY', 'CMD_AUDIT_NEW', - 'CMD_ABORT', 'CMD_FINISHED'] - - # In complain mode: events default to allow - # In enforce mode: events default to deny - q.default = 'CMD_DENY' - if aamode == 'PERMITTING': - q.default = 'CMD_ALLOW' - - seen_events += 1 - - done = False - while not done: - ans, selected = q.promptUser() - - if ans == 'CMD_FINISHED': - save_profiles() - return - - # Ignore the log entry - if ans == 'CMD_IGNORE_ENTRY': - done = True - break - - if ans.startswith('CMD_AUDIT'): - audit_toggle = not audit_toggle - if audit_toggle: - audit = 'audit ' - audit_cmd = 'CMD_AUDIT_OFF' - else: - audit = '' - audit_cmd = 'CMD_AUDIT_NEW' + seen_events += 1 - q.functions = ['CMD_ALLOW', 'CMD_DENY', 'CMD_IGNORE_ENTRY', audit_cmd, - 'CMD_ABORT', 'CMD_FINISHED', ] + done = False + while not done: + q.headers = [_('Profile'), combine_name(profile, hat)] + q.headers += rule_obj.logprof_header() + + # Load variables into sev_db? Not needed/used for capabilities. + severity = rule_obj.severity(sev_db) + if severity != '--': + q.headers += [_('Severity'), severity] + + q.functions = available_buttons(rule_obj) + + # In complain mode: events default to allow + # In enforce mode: events default to deny + # XXX does this behaviour really make sense, except for "historical reasons"[tm]? + q.default = 'CMD_DENY' + if rule_obj.log_event == 'PERMITTING': + q.default = 'CMD_ALLOW' + + ans, selected = q.promptUser() + if ans == 'CMD_IGNORE_ENTRY': + done = True + break + + elif ans == 'CMD_FINISHED': + return + + elif ans.startswith('CMD_AUDIT'): + if ans == 'CMD_AUDIT_NEW': + rule_obj.audit = True + rule_obj.raw_rule = None + else: + rule_obj.audit = False + rule_obj.raw_rule = None + + options[len(options) - 1] = rule_obj.get_clean() + q.options = options + + elif ans == 'CMD_ALLOW': + done = True + changed[profile] = True - q.headers = [_('Profile'), combine_name(profile, hat), - _('Capability'), audit + capability, - _('Severity'), severity] - - if ans == 'CMD_ALLOW': - selection = '' - if options: selection = options[selected] - match = re_match_include(selection) - if match: - deleted = False - inc = match # .groups()[0] - deleted = delete_duplicates(aa[profile][hat], inc) - aa[profile][hat]['include'][inc] = True - - aaui.UI_Info(_('Adding %s to profile.') % selection) - if deleted: - aaui.UI_Info(_('Deleted %s previous matching profile entries.') % deleted) + + inc = re_match_include(selection) + if inc: + deleted = delete_duplicates(aa[profile][hat], inc) + + aa[profile][hat]['include'][inc] = True + + aaui.UI_Info(_('Adding %s to profile.') % selection) + if deleted: + aaui.UI_Info(_('Deleted %s previous matching profile entries.') % deleted) + + else: + aa[profile][hat][ruletype].add(rule_obj) + + aaui.UI_Info(_('Adding %s to profile.') % rule_obj.get_clean()) + + elif ans == 'CMD_DENY': + done = True + changed[profile] = True + + rule_obj.deny = True + rule_obj.raw_rule = None # reset raw rule after manually modifying rule_obj + aa[profile][hat][ruletype].add(rule_obj) + aaui.UI_Info(_('Adding %s to profile.') % rule_obj.get_clean()) else: - capability_obj = CapabilityRule(capability, audit=audit) - aa[profile][hat]['capability'].add(capability_obj) - aaui.UI_Info(_('Adding capability %s to profile.') % capability) - - changed[profile] = True - - done = True - - elif ans == 'CMD_DENY': - capability_obj = CapabilityRule(capability, audit=audit, deny=True) - aa[profile][hat]['capability'].add(capability_obj) - changed[profile] = True - - aaui.UI_Info(_('Denying capability %s to profile.') % capability) - done = True - else: - done = False + done = False + # END of code (mostly) shared with aa-mergeprof # Process all the path entries. for path in sorted(log_dict[aamode][profile][hat]['path'].keys()): Regards, Christian Boltz -- When that limitation is removed, there might be a tendency that for 12.2 the live image is 800MB, the next 1GB, next one 1.5GB. If not careful we end up with a live-blu-ray, live-data-centre or a live-cloud ;-)) [Hans Witvliet in opensuse-factory] -- AppArmor mailing list AppArmor@lists.ubuntu.com Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor