[apparmor] [patch 1/2] add and use parse_profile_start_line()
Christian Boltz
apparmor at cboltz.de
Wed Mar 4 21:40:40 UTC 2015
Hello,
this patch adds the parse_profile_start_line() function to regex.py,
which is a wrapper for RE_PROFILE_START_2 and returns an array with
named matches.
It also changes some places in aa.py from using RE_PROFILE_START to the
parse_profile_start_line() function.
Notes:
- until everything is migrated to the new function, I'll keep the old
RE_PROFILE_START unchanged - that's the reason to add the new regex
as RE_PROFILE_START_2
- the patch changes only aa.py sections that are covered by tests already
(which means some users of RE_PROFILE_START are remaining)
- parse_profile_start_line() merges 'profile' and 'attachment' into
'profile' (aka the old, broken behaviour) until aa.py can handle the
attachment properly. The alternative would be to ignore 'attachment',
which would be worse.
I propose this patch for trunk and 2.9.
[ add-and-use-parse_profile_start_line.diff ]
=== modified file 'utils/apparmor/aa.py'
--- utils/apparmor/aa.py 2015-03-03 19:15:00 +0000
+++ utils/apparmor/aa.py 2015-03-04 20:45:29 +0000
@@ -49,7 +49,7 @@
RE_PROFILE_HAT_DEF, RE_PROFILE_DBUS, RE_PROFILE_MOUNT,
RE_PROFILE_SIGNAL, RE_PROFILE_PTRACE, RE_PROFILE_PIVOT_ROOT,
RE_PROFILE_UNIX, RE_RULE_HAS_COMMA, RE_HAS_COMMENT_SPLIT,
- strip_quotes )
+ strip_quotes, parse_profile_start_line )
import apparmor.rules as aarules
@@ -613,11 +613,9 @@
with open_file_read(filename) as f_in:
for line in f_in:
if RE_PROFILE_START.search(line):
- matches = RE_PROFILE_START.search(line).groups()
- profile = matches[1] or matches[3]
- flags = matches[6]
- if flags and flags.strip() == '':
- raise AppArmorException(_('Invalid syntax in %(filename)s for profile %(profile)s: Empty set of flags.' % { 'filename': filename, 'profile': profile } ))
+ matches = parse_profile_start_line(line, filename)
+ profile = matches['profile']
+ flags = matches['flags']
if profile == program or program is None:
return flags
@@ -2637,26 +2645,23 @@
def parse_profile_start(line, file, lineno, profile, hat):
- matches = RE_PROFILE_START.search(line).groups()
+ matches = parse_profile_start_line(line, file)
pps_set_profile = False
pps_set_hat_external = False
if profile:
#print(profile, hat)
- if profile != hat or not matches[3]:
+ if profile != hat or not matches['profile_keyword']:
raise AppArmorException(_('%(profile)s profile in %(file)s contains syntax errors in line: %(line)s.') % { 'profile': profile, 'file': file, 'line': lineno + 1 })
# Keep track of the start of a profile
- if profile and profile == hat and matches[3]:
+ if profile and profile == hat and matches['profile_keyword']:
# local profile
- hat = matches[3]
+ hat = matches['profile']
in_contained_hat = True
pps_set_profile = True
else:
- if matches[1]:
- profile = matches[1]
- else:
- profile = matches[3]
+ profile = matches['profile']
#print(profile)
if len(profile.split('//')) >= 2:
profile, hat = profile.split('//')[:2]
@@ -2668,11 +2673,7 @@
else:
hat = profile
- flags = matches[6]
-
- profile = strip_quotes(profile)
- if hat:
- hat = strip_quotes(hat)
+ flags = matches['flags']
return (profile, hat, flags, in_contained_hat, pps_set_profile, pps_set_hat_external)
=== modified file 'utils/apparmor/regex.py'
--- utils/apparmor/regex.py 2015-03-03 19:15:00 +0000
+++ utils/apparmor/regex.py 2015-03-04 20:56:07 +0000
@@ -14,6 +14,11 @@
# ----------------------------------------------------------------------
import re
+from apparmor.common import AppArmorBug, AppArmorException
+
+# setup module translations
+from apparmor.translations import init_translation
+_ = init_translation()
## Profile parsing Regex
RE_AUDIT_DENY = '^\s*(?P<audit>audit\s+)?(?P<allow>allow\s+|deny\s+)?' # line start, optionally: leading whitespace, <audit> and <allow>/deny
@@ -56,6 +62,52 @@
'(?P<comment>#.*)$') # match trailing comment and store in 'comment' group
+
+RE_PROFILE_START_2 = re.compile(
+ '^(?P<leadingspace>\s*)' +
+ '(' +
+ '(?P<plainprofile>(/\S+|"[^"]+"))' + # just a path
+ '|' + # or
+ '(' + 'profile' + '\s+(?P<namedprofile>(\S+|"[^"]+"))' + '(\s+(?P<attachment>(/\S+|"/[^"]+")))?' + ')' + # 'profile', profile name, optionally attachment
+ ')' +
+ '\s+((flags=)?\((?P<flags>.+)\)\s+)?\{' +
+ RE_EOL)
+
+def parse_profile_start_line(line, filename):
+ matches = RE_PROFILE_START_2.search(line)
+
+ if not matches:
+ raise AppArmorBug('The given line from file %(filename)s is not the start of a profile: %(line)s' % { 'filename': filename, 'line': line } )
+
+ result = {}
+
+ for section in [ 'leadingspace', 'plainprofile', 'namedprofile', 'attachment', 'flags', 'comment']:
+ if matches.group(section):
+ result[section] = matches.group(section)
+
+ # sections with optional quotes
+ if section in ['plainprofile', 'namedprofile', 'attachment']:
+ result[section] = strip_quotes(result[section])
+ else:
+ result[section] = None
+
+ if result['flags'] and result['flags'].strip() == '':
+ raise AppArmorException(_('Invalid syntax in %(filename)s: Empty set of flags in line %(line)s.' % { 'filename': filename, 'line': line } ))
+
+ if result['plainprofile']:
+ result['profile'] = result['plainprofile']
+ result['profile_keyword'] = False
+ else:
+ result['profile'] = result['namedprofile']
+ result['profile_keyword'] = True
+
+ if result['attachment']:
+ # XXX keep the broken behaviour until proper handling for attachment is implemented
+ result['profile'] = "%s %s" % (result['profile'], result['attachment'])
+
+ return result
+
+
def strip_quotes(data):
if data[0] + data[-1] == '""':
return data[1:-1]
Regards,
Christian Boltz
--
> > Gruß,
> > Jörg
> Huch? Wo ist denn Ratti hingekommen? ;-)
Das ist eine sehr gute Frage... ich weiss auch nicht...
[> Christian Boltz und (>>) Ratti in fontlinge-devel]
More information about the AppArmor
mailing list