[apparmor] [patch] aa.py: use named match groups for capability
Christian Boltz
apparmor at cboltz.de
Fri Sep 26 20:00:33 UTC 2014
Hello,
this patch converts RE_PROFILE_CAP in aa.py and the code using it to
named match groups.
(capability is one of the easiest rule types, so it's good as a start.)
The patch also adds basic support for rules containing more than one
capability, like
capability chown dac_override,
Note that this is just a pass-through mode (instead of complaining about
an invalid line). aa-logprof will happily add another "capability chown"
if it hits a log entry for it. (But: we never got a bugreport about not
supporting multi-capability lines, so I guess they are rarely used ;-)
I also added a parse_audit_allow() function to handle the audit and
allow/deny keywords. They are used in most rule types, which means we
can get rid of some duplicated code with this function.
Finally, update utils/test/test-regex_matches.py - RE_PROFILE_CAP now
has 5 instead of 4 match groups because of the added multi-capability
support.
While on it, I also improved the error message in setup_regex_tests()
to also show the rule that causes a problem.
Feel free to comment about named match groups and the other changes
introduced with this patch in general. Capability is the "prototype",
similar patches for other rule types will follow sooner or later.
(I won't complain if someone "grabs" one of the rule types so that I
don't have to do everything ;-)
=== modified file 'utils/apparmor/aa.py'
--- utils/apparmor/aa.py 2014-09-22 21:41:54 +0000
+++ utils/apparmor/aa.py 2014-09-26 18:58:57 +0000
@@ -2618,7 +2627,7 @@
RE_PROFILE_START = re.compile('^\s*("?(/.+?)"??|(profile\s+"?(.+?)"??))\s+((flags=)?\((.+)\)\s+)?\{' + RE_EOL)
RE_PROFILE_END = re.compile('^\s*\}' + RE_EOL)
-RE_PROFILE_CAP = re.compile(RE_AUDIT_DENY + 'capability(\s+\S+)?' + RE_COMMA_EOL)
+RE_PROFILE_CAP = re.compile(RE_AUDIT_DENY + 'capability(?P<capability>(\s+\S+)+)?' + RE_COMMA_EOL)
RE_PROFILE_LINK = re.compile(RE_AUDIT_DENY + 'link\s+(((subset)|(<=))\s+)?([\"\@\/].*?"??)\s+->\s*([\"\@\/].*?"??)' + RE_COMMA_EOL)
RE_PROFILE_CHANGE_PROFILE = re.compile('^\s*change_profile\s+->\s*("??.+?"??)' + RE_COMMA_EOL)
RE_PROFILE_ALIAS = re.compile('^\s*alias\s+("??.+?"??)\s+->\s*("??.+?"??)' + RE_COMMA_EOL)
@@ -2747,22 +2759,18 @@
initial_comment = ''
elif RE_PROFILE_CAP.search(line):
- matches = RE_PROFILE_CAP.search(line).groups()
+ matches = RE_PROFILE_CAP.search(line)
if not profile:
raise AppArmorException(_('Syntax Error: Unexpected capability entry found in file: %(file)s line: %(line)s') % { 'file': file, 'line': lineno + 1 })
- audit = False
- if matches[0]:
- audit = True
-
- allow = 'allow'
- if matches[1] and matches[1].strip() == 'deny':
- allow = 'deny'
+ audit, allow, allow_keyword = parse_audit_allow(matches)
+ # TODO: honor allow_keyword
capability = ALL
- if matches[2]:
- capability = matches[2].strip()
+ if matches.group('capability'):
+ capability = matches.group('capability').strip()
+ # TODO: can contain more than one capability- split it?
profile_data[profile][hat][allow]['capability'][capability]['set'] = True
profile_data[profile][hat][allow]['capability'][capability]['audit'] = audit
@@ -3216,6 +3224,21 @@
return profile_data
+def parse_audit_allow(matches):
+ audit = False
+ if matches.group('audit'):
+ audit = True
+
+ allow = 'allow'
+ allow_keyword = False
+ if matches.group('allow'):
+ allow = matches.group('allow').strip()
+ allow_keyword = True
+ if allow != 'allow' and allow != 'deny': # should never happen
+ raise AppArmorException(_("Invalid allow/deny keyword %s" % allow))
+
+ return (audit, allow, allow_keyword)
+
# RE_DBUS_ENTRY = re.compile('^dbus\s*()?,\s*$')
# use stuff like '(?P<action>(send|write|w|receive|read|r|rw))'
=== modified file 'utils/test/test-regex_matches.py'
--- utils/test/test-regex_matches.py 2014-09-04 01:22:04 +0000
+++ utils/test/test-regex_matches.py 2014-09-26 19:24:14 +0000
@@ -162,7 +162,7 @@
for (i, group) in enumerate(groups):
if group:
group = group.strip()
- self.assertEqual(group, expected[i], 'Group %d mismatch' % i)
+ self.assertEqual(group, expected[i], 'Group %d mismatch in rule %s' % (i,line))
def setup_regex_tests(test_class):
@@ -188,10 +188,10 @@
self.regex = aa.RE_PROFILE_CAP
tests = [
- (' capability net_raw,', (None, None, 'net_raw', None)),
- ('capability net_raw , ', (None, None, 'net_raw', None)),
- (' capability,', (None, None, None, None)),
- (' capability , ', (None, None, None, None)),
+ (' capability net_raw,', (None, None, 'net_raw', 'net_raw', None)),
+ ('capability net_raw , ', (None, None, 'net_raw', 'net_raw', None)),
+ (' capability,', (None, None, None, None, None)),
+ (' capability , ', (None, None, None, None, None)),
(' capabilitynet_raw,', False)
]
Regards,
Christian Boltz
--
Der geistige Horizont ist der Abstand zwischen Brett und Kopf.
More information about the AppArmor
mailing list