2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-31 22:35:35 +00:00

extend re_match_include_parse() to also match abi rules

... and add some tests
This commit is contained in:
Christian Boltz
2020-05-09 00:35:10 +02:00
parent b96fd81184
commit 8ca486715f
3 changed files with 56 additions and 12 deletions

View File

@@ -145,16 +145,23 @@ RE_MAGIC_OR_QUOTED_PATH = '(<(?P<magicpath>.*)>|"(?P<quotedpath>.*)"|(?P<unquote
RE_ABI = re.compile('^\s*#?abi\s*' + RE_MAGIC_OR_QUOTED_PATH + RE_COMMA_EOL)
RE_INCLUDE = re.compile('^\s*#?include(?P<ifexists>\s+if\s+exists)?\s*' + RE_MAGIC_OR_QUOTED_PATH + RE_EOL)
def re_match_include_parse(line, rule_name):
'''Matches the path for include, include if exists and abi rules
rule_name can be 'include' or 'abi'
def re_match_include_parse(line):
'''Matches the path for include or include if exists.
Returns a tuple with
- if the "if exists" condition is given
- the include path
- the include/abi path
- if the path is a magic path (enclosed in <...>)
'''
matches = RE_INCLUDE.search(line)
if rule_name == 'include':
matches = RE_INCLUDE.search(line)
elif rule_name == 'abi':
matches = RE_ABI.search(line)
else:
raise AppArmorBug('re_match_include_parse() called with invalid rule name %s' % rule_name)
if not matches:
return None, None, None
@@ -167,31 +174,31 @@ def re_match_include_parse(line):
elif matches.group('unquotedpath'):
# LP: #1738879 - parser doesn't handle unquoted paths everywhere
# path = matches.group('unquotedpath').strip()
raise AppArmorException(_('Syntax error: #include must use quoted path or <...>'))
raise AppArmorException(_('Syntax error: %s must use quoted path or <...>') % rule_name)
elif matches.group('quotedpath'):
path = matches.group('quotedpath')
# LP: 1738880 - parser doesn't handle relative paths everywhere, and
# neither do we (see aa.py)
if len(path) > 0 and path[0] != '/':
raise AppArmorException(_('Syntax error: #include must use quoted path or <...>'))
raise AppArmorException(_('Syntax error: %s must use quoted path or <...>') % rule_name)
# if path is empty or the empty string
if path is None or path == "":
raise AppArmorException(_('Syntax error: #include rule with empty filename'))
raise AppArmorException(_('Syntax error: %s rule with empty filename') % rule_name)
# LP: #1738877 - parser doesn't handle files with spaces in the name
if re.search('\s', path):
raise AppArmorException(_('Syntax error: #include rule filename cannot contain spaces'))
raise AppArmorException(_('Syntax error: %s rule filename cannot contain spaces') % rule_name)
ifexists = False
if matches.group('ifexists'):
if rule_name == 'include' and matches.group('ifexists'):
ifexists = True
return path, ifexists, ismagic
def re_match_include(line):
''' return path of a 'include' rule '''
(path, ifexists, ismagic) = re_match_include_parse(line)
(path, ifexists, ismagic) = re_match_include_parse(line, 'include')
if not ifexists:
return path

View File

@@ -68,7 +68,7 @@ class IncludeRule(BaseRule):
comment = parse_comment(matches)
# TODO: move re_match_include_parse() from regex.py to this class after converting all code to use IncludeRule
path, ifexists, ismagic = re_match_include_parse(raw_rule)
path, ifexists, ismagic = re_match_include_parse(raw_rule, cls.rule_name)
return IncludeRule(path, ifexists, ismagic,
audit=False, deny=False, allow_keyword=False, comment=comment)

View File

@@ -567,10 +567,47 @@ class Test_re_match_include_parse(AATest):
(' /etc/fstab r,', (None, None, None ) ),
('/usr/include r,', (None, None, None ) ),
('/include r,', (None, None, None ) ),
('abi <abi/4.19>,', (None, None, None ) ), # abi rule
]
def _run_test(self, params, expected):
self.assertEqual(re_match_include_parse(params), expected)
self.assertEqual(re_match_include_parse(params, 'include'), expected)
class Test_re_match_include_parse_abi(AATest):
tests = [
# path if exists magic path
('abi <abi/4.19>,', ('abi/4.19', False, True ) ), # magic path
('abi <abi/4.19>, # comment', ('abi/4.19', False, True ) ),
(' abi <abi/4.19> , # comment', ('abi/4.19', False, True ) ),
('abi "/abi/4.19" ,', ('/abi/4.19', False, False) ), # quoted path starting with /
('abi "/abi/4.19", # comment', ('/abi/4.19', False, False) ),
(' abi "/abi/4.19" , # comment ', ('/abi/4.19', False, False) ),
# (' abi "abi/4.19" , # comment ', ('abi/4.19', False, False) ), # quoted path, no leading /
# ('abi abi/4.19,', ('abi/4.19', False, False) ), # without quotes
('some abi <abi/4.19>,', (None, None, None ) ), # non-matching
(' /etc/fstab r,', (None, None, None ) ),
('/usr/abi r,', (None, None, None ) ),
('/abi r,', (None, None, None ) ),
('#include <abstractions/base>', (None, None, None ) ), # include rule path
]
def _run_test(self, params, expected):
self.assertEqual(re_match_include_parse(params, 'abi'), expected)
class Test_re_match_include_parse_empty_filename(AATest):
tests = [
(('include <>', 'include'), AppArmorException),
(('include ""', 'include'), AppArmorException),
(('include ', 'include'), AppArmorException),
(('abi <>,', 'abi'), AppArmorException),
(('abi "",', 'abi'), AppArmorException),
(('abi ,', 'abi'), AppArmorException),
]
def _run_test(self, params, expected):
with self.assertRaises(expected):
rule, rule_name = params
re_match_include_parse(rule, rule_name)
class TestStripParenthesis(AATest):
tests = [