2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-09-02 15:25:27 +00:00

Merge hat parsing into ProfileStorage.parse()

... and into parse_profile_start_line() (which is used by
ProfileStorage.parse()).

With this change, the section handling RE_PROFILE_HAT_DEF in
parse_profile_data() becomes superfluous.

A nice side effect is that two simple_tests parse failures get
accidently ;-) fixed.
This commit is contained in:
Christian Boltz
2021-05-23 17:52:03 +02:00
parent 0325ba06da
commit 6f15bea74c
4 changed files with 22 additions and 41 deletions

View File

@@ -44,7 +44,7 @@ from apparmor.regex import (RE_PROFILE_START, RE_PROFILE_END,
RE_PROFILE_HAT_DEF, RE_PROFILE_MOUNT, RE_PROFILE_HAT_DEF, RE_PROFILE_MOUNT,
RE_PROFILE_PIVOT_ROOT, RE_PROFILE_PIVOT_ROOT,
RE_PROFILE_UNIX, RE_RULE_HAS_COMMA, RE_HAS_COMMENT_SPLIT, RE_PROFILE_UNIX, RE_RULE_HAS_COMMA, RE_HAS_COMMENT_SPLIT,
strip_quotes, parse_profile_start_line, re_match_include ) parse_profile_start_line, re_match_include )
from apparmor.profile_list import ProfileList, preamble_ruletypes from apparmor.profile_list import ProfileList, preamble_ruletypes
@@ -1813,7 +1813,7 @@ def parse_profile_data(data, file, do_include, in_preamble):
else: else:
load_include(incname, in_preamble) load_include(incname, in_preamble)
elif RE_PROFILE_START.search(line): # Starting line of a profile elif RE_PROFILE_START.search(line) or RE_PROFILE_HAT_DEF.search(line): # Starting line of a profile/hat
# in_contained_hat is needed to know if we are already in a profile or not. (Simply checking if we are in a hat doesn't work, # in_contained_hat is needed to know if we are already in a profile or not. (Simply checking if we are in a hat doesn't work,
# because something like "profile foo//bar" will set profile and hat at once, and later (wrongfully) expect another "}". # because something like "profile foo//bar" will set profile and hat at once, and later (wrongfully) expect another "}".
# The logic is simple and resembles a "poor man's stack" (with limited/hardcoded height). # The logic is simple and resembles a "poor man's stack" (with limited/hardcoded height).
@@ -1946,36 +1946,6 @@ def parse_profile_data(data, file, do_include, in_preamble):
aaui.UI_Important(_('Ignoring no longer supported change hat declaration "^%(hat)s," found in file: %(file)s line: %(line)s') % { aaui.UI_Important(_('Ignoring no longer supported change hat declaration "^%(hat)s," found in file: %(file)s line: %(line)s') % {
'hat': matches[0], 'file': file, 'line': lineno + 1 }) 'hat': matches[0], 'file': file, 'line': lineno + 1 })
elif RE_PROFILE_HAT_DEF.search(line):
# An embedded hat syntax definition starts
matches = RE_PROFILE_HAT_DEF.search(line)
if not profile:
raise AppArmorException(_('Syntax Error: Unexpected hat definition found in file: %(file)s line: %(line)s') % { 'file': file, 'line': lineno + 1 })
in_contained_hat = True
hat = matches.group('hat')
hat = strip_quotes(hat)
profname = combine_profname([profile, hat])
if profile_data.get(profname, False) and not do_include:
raise AppArmorException('Profile %(profile)s defined twice in %(file)s, last found in line %(line)s' %
{ 'file': file, 'line': lineno + 1, 'profile': combine_name(profile, hat) })
# if hat is already known, the check above will error out (if not do_include)
# nevertheless, just to be sure, don't overwrite existing profile_data.
if not profile_data.get(profname, False):
profile_data[profname] = ProfileStorage(profile, hat, 'parse_profile_data() hat_def')
profile_data[profname]['filename'] = file
profile_data[profname]['is_hat'] = True
flags = matches.group('flags')
profile_data[profname]['flags'] = flags
if initial_comment:
profile_data[profname]['initial_comment'] = initial_comment
initial_comment = ''
elif line[0] == '#': elif line[0] == '#':
# Handle initial comments # Handle initial comments
if not profile: if not profile:

View File

@@ -234,8 +234,11 @@ class ProfileStorage:
prof_storage['name'] = profile prof_storage['name'] = profile
prof_storage['filename'] = file prof_storage['filename'] = file
prof_storage['external'] = pps_set_hat_external prof_storage['external'] = pps_set_hat_external
prof_storage['attachment'] = matches['attachment'] or ''
prof_storage['flags'] = matches['flags'] prof_storage['flags'] = matches['flags']
prof_storage['is_hat'] = matches['is_hat']
if not matches['is_hat']:
prof_storage['attachment'] = matches['attachment'] or ''
prof_storage['xattrs'] = matches['xattrs'] prof_storage['xattrs'] = matches['xattrs']
return (profile, hat, prof_storage) return (profile, hat, prof_storage)

View File

@@ -112,19 +112,26 @@ RE_PROFILE_FILE_ENTRY = re.compile(
def parse_profile_start_line(line, filename): def parse_profile_start_line(line, filename):
common_sections = [ 'leadingspace', 'flags', 'comment']
sections = [ 'plainprofile', 'namedprofile', 'attachment', 'xattrs'] + common_sections
matches = RE_PROFILE_START.search(line) matches = RE_PROFILE_START.search(line)
if not matches:
sections = ['hat_keyword', 'hat'] + common_sections
matches = RE_PROFILE_HAT_DEF.search(line)
if not matches: 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 } ) raise AppArmorBug('The given line from file %(filename)s is not the start of a profile: %(line)s' % { 'filename': filename, 'line': line } )
result = {} result = {}
for section in [ 'leadingspace', 'plainprofile', 'namedprofile', 'attachment', 'xattrs', 'flags', 'comment']: for section in sections:
if matches.group(section): if matches.group(section):
result[section] = matches.group(section) result[section] = matches.group(section)
# sections with optional quotes # sections with optional quotes
if section in ['plainprofile', 'namedprofile', 'attachment']: if section in ['plainprofile', 'namedprofile', 'attachment', 'hat']:
result[section] = strip_quotes(result[section]) result[section] = strip_quotes(result[section])
else: else:
result[section] = None result[section] = None
@@ -132,7 +139,12 @@ def parse_profile_start_line(line, filename):
if result['flags'] and result['flags'].strip() == '': 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 } )) raise AppArmorException(_('Invalid syntax in %(filename)s: Empty set of flags in line %(line)s.' % { 'filename': filename, 'line': line } ))
if result['plainprofile']: result['is_hat'] = False
if result.get('hat'):
result['is_hat'] = True
result['profile'] = result['hat']
result['profile_keyword'] = True
elif result['plainprofile']:
result['profile'] = result['plainprofile'] result['profile'] = result['plainprofile']
result['profile_keyword'] = False result['profile_keyword'] = False
else: else:

View File

@@ -141,7 +141,6 @@ exception_not_raised = [
'profile/flags/flags_bad44.sd', 'profile/flags/flags_bad44.sd',
'profile/flags/flags_bad45.sd', 'profile/flags/flags_bad45.sd',
'profile/flags/flags_bad46.sd', 'profile/flags/flags_bad46.sd',
'profile/simple_bad_no_close_brace4.sd',
'profile/profile_ns_bad8.sd', # 'profile :ns/t' without terminating ':' 'profile/profile_ns_bad8.sd', # 'profile :ns/t' without terminating ':'
'ptrace/bad_05.sd', # actually contains a capability rule with invalid (ptrace-related) keyword 'ptrace/bad_05.sd', # actually contains a capability rule with invalid (ptrace-related) keyword
'ptrace/bad_06.sd', # actually contains a capability rule with invalid (ptrace-related) keyword 'ptrace/bad_06.sd', # actually contains a capability rule with invalid (ptrace-related) keyword
@@ -306,9 +305,6 @@ syntax_failure = [
# missing profile keywords # missing profile keywords
'profile/re_named_ok2.sd', 'profile/re_named_ok2.sd',
# Syntax Error: Unexpected hat definition found (external hat)
'change_hat/new_style4.sd',
# Syntax Errors caused by boolean conditions (parse_profile_data() gets confused by the closing '}') # Syntax Errors caused by boolean conditions (parse_profile_data() gets confused by the closing '}')
'conditional/defined_1.sd', 'conditional/defined_1.sd',
'conditional/defined_2.sd', 'conditional/defined_2.sd',