[apparmor] [patch 1/2] add and use parse_profile_start_line()

Steve Beattie steve at nxnw.org
Tue Mar 31 10:30:15 UTC 2015


On Wed, Mar 04, 2015 at 10:40:40PM +0100, Christian Boltz wrote:
> 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.

This all looks good, so Acked-by: Steve Beattie <steve at nxnw.org>,
except that I don't like having patches committed that break the
tests, so please commit 11-update-test-aa-for-parse_profile_start.diff
immediately afterward.

> [ 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]
> 
> 
> -- 
> AppArmor mailing list
> AppArmor at lists.ubuntu.com
> Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor

-- 
Steve Beattie
<sbeattie at ubuntu.com>
http://NxNW.org/~steve/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <https://lists.ubuntu.com/archives/apparmor/attachments/20150331/6b885fec/attachment.pgp>


More information about the AppArmor mailing list