diff --git a/utils/aa-genprof b/utils/aa-genprof index e244a6d47..21988cdeb 100755 --- a/utils/aa-genprof +++ b/utils/aa-genprof @@ -49,8 +49,8 @@ def last_audit_entry_time(): out = subprocess.check_output(['tail', '-1', apparmor.logfile]) logmark = None out = out.decode('ascii') - if re.search('^.*msg=audit\((\d+\.\d+:\d+).*\).*$', out): - logmark = re.search('^.*msg=audit\((\d+\.\d+:\d+).*\).*$', out).groups()[0] + if re.search(r'^.*msg=audit\((\d+\.\d+:\d+).*\).*$', out): + logmark = re.search(r'^.*msg=audit\((\d+\.\d+:\d+).*\).*$', out).groups()[0] else: logmark = '' return logmark diff --git a/utils/aa-notify b/utils/aa-notify index e51820f7c..a4db7c9e2 100755 --- a/utils/aa-notify +++ b/utils/aa-notify @@ -255,18 +255,18 @@ def get_apparmor_events(logfile, since=0): def parse_logdata(logsource): """Traverse any iterable log source and extract relevant AppArmor events""" - re_audit_time_id = '(msg=)?audit\([\d\.\:]+\):\s+' # 'audit(1282626827.320:411): ' - re_kernel_time = '\[[\d\.\s]+\]' # '[ 1612.746129]' - re_type_num = '1[45][0-9][0-9]' # 1400..1599 + re_audit_time_id = r'(msg=)?audit\([\d\.\:]+\):\s+' # 'audit(1282626827.320:411): ' + re_kernel_time = r'\[[\d\.\s]+\]' # '[ 1612.746129]' + re_type_num = '1[45][0-9][0-9]' # 1400..1599 re_aa_or_op = '(apparmor=|operation=)' re_log_parts = [ - 'kernel:\s+(' + re_kernel_time + '\s+)?(audit:\s+)?type=' + re_type_num + '\s+' + re_audit_time_id + re_aa_or_op, # v2_6 syslog - 'kernel:\s+(' + re_kernel_time + '\s+)?' + re_audit_time_id + 'type=' + re_type_num + '\s+' + re_aa_or_op, - 'type=(AVC|APPARMOR[_A-Z]*|' + re_type_num + ')\s+' + re_audit_time_id + '(type=' + re_type_num + '\s+)?' + re_aa_or_op, # v2_6 audit and dmesg - 'type=USER_AVC\s+' + re_audit_time_id + '.*apparmor=', # dbus - 'type=UNKNOWN\[' + re_type_num + '\]\s+' + re_audit_time_id + re_aa_or_op, - 'dbus\[[0-9]+\]:\s+apparmor=', # dbus + r'kernel:\s+(' + re_kernel_time + r'\s+)?(audit:\s+)?type=' + re_type_num + r'\s+' + re_audit_time_id + re_aa_or_op, # v2_6 syslog + r'kernel:\s+(' + re_kernel_time + r'\s+)?' + re_audit_time_id + 'type=' + re_type_num + r'\s+' + re_aa_or_op, + 'type=(AVC|APPARMOR[_A-Z]*|' + re_type_num + r')\s+' + re_audit_time_id + '(type=' + re_type_num + r'\s+)?' + re_aa_or_op, # v2_6 audit and dmesg + r'type=USER_AVC\s+' + re_audit_time_id + '.*apparmor=', # dbus + r'type=UNKNOWN\[' + re_type_num + r'\]\s+' + re_audit_time_id + re_aa_or_op, + r'dbus\[[0-9]+\]:\s+apparmor=', # dbus ] # Pre-filter log lines so that we hand over only relevant lines to LibAppArmor parsing diff --git a/utils/apparmor/aa.py b/utils/apparmor/aa.py index 4f432daed..5c9f860ae 100644 --- a/utils/apparmor/aa.py +++ b/utils/apparmor/aa.py @@ -360,8 +360,8 @@ def get_output(params): def get_reqs(file): """Returns a list of paths from ldd output""" - pattern1 = re.compile('^\s*\S+ => (/\S+)') - pattern2 = re.compile('^\s*(/\S+)') + pattern1 = re.compile(r'^\s*\S+ => (/\S+)') + pattern2 = re.compile(r'^\s*(/\S+)') reqs = [] ldd = conf.find_first_file(cfg['settings'].get('ldd')) or '/usr/bin/ldd' @@ -439,9 +439,9 @@ def get_interpreter_and_abstraction(exec_target): abstraction = 'abstractions/bash' elif interpreter == 'perl': abstraction = 'abstractions/perl' - elif re.search('^python([23]|[23]\.[0-9]+)?$', interpreter): + elif re.search(r'^python([23]|[23]\.[0-9]+)?$', interpreter): abstraction = 'abstractions/python' - elif re.search('^ruby([0-9]+(\.[0-9]+)*)?$', interpreter): + elif re.search(r'^ruby([0-9]+(\.[0-9]+)*)?$', interpreter): abstraction = 'abstractions/ruby' else: abstraction = None @@ -2539,10 +2539,10 @@ def loadincludes_dir(subdir, in_preamble): def glob_common(path): globs = [] - if re.search('[\d.]+\.so$', path) or re.search('\.so\.[\d.]+$', path): + if re.search(r'[\d.]+\.so$', path) or re.search(r'\.so\.[\d.]+$', path): libpath = path - libpath = re.sub('[\d.]+\.so$', '*.so', libpath) - libpath = re.sub('\.so\.[\d.]+$', '.so.*', libpath) + libpath = re.sub(r'[\d.]+\.so$', '*.so', libpath) + libpath = re.sub(r'\.so\.[\d.]+$', '.so.*', libpath) if libpath != path: globs.append(libpath) diff --git a/utils/apparmor/aare.py b/utils/apparmor/aare.py index 4839d5dae..573c46637 100644 --- a/utils/apparmor/aare.py +++ b/utils/apparmor/aare.py @@ -92,25 +92,25 @@ class AARE: if self.regex.endswith('/'): if self.regex.endswith(('/**/', '/*/')): # /foo/**/ and /foo/*/ => /**/ - newpath = re.sub('/[^/]+/\*{1,2}/$', '/**/', self.regex) # re.sub('/[^/]+/\*{1,2}$/', '/\*\*/', self.regex) - elif re.search('/[^/]+\*\*[^/]*/$', self.regex): + newpath = re.sub(r'/[^/]+/\*{1,2}/$', '/**/', self.regex) + elif re.search(r'/[^/]+\*\*[^/]*/$', self.regex): # /foo**/ and /foo**bar/ => /**/ - newpath = re.sub('/[^/]+\*\*[^/]*/$', '/**/', self.regex) - elif re.search('/\*\*[^/]+/$', self.regex): + newpath = re.sub(r'/[^/]+\*\*[^/]*/$', '/**/', self.regex) + elif re.search(r'/\*\*[^/]+/$', self.regex): # /**bar/ => /**/ - newpath = re.sub('/\*\*[^/]+/$', '/**/', self.regex) + newpath = re.sub(r'/\*\*[^/]+/$', '/**/', self.regex) else: newpath = re.sub('/[^/]+/$', '/*/', self.regex) else: if self.regex.endswith(('/**', '/*')): # /foo/** and /foo/* => /** - newpath = re.sub('/[^/]+/\*{1,2}$', '/**', self.regex) - elif re.search('/[^/]*\*\*[^/]+$', self.regex): + newpath = re.sub(r'/[^/]+/\*{1,2}$', '/**', self.regex) + elif re.search(r'/[^/]*\*\*[^/]+$', self.regex): # /**foo and /foor**bar => /** - newpath = re.sub('/[^/]*\*\*[^/]+$', '/**', self.regex) - elif re.search('/[^/]+\*\*$', self.regex): + newpath = re.sub(r'/[^/]*\*\*[^/]+$', '/**', self.regex) + elif re.search(r'/[^/]+\*\*$', self.regex): # /foo** => /** - newpath = re.sub('/[^/]+\*\*$', '/**', self.regex) + newpath = re.sub(r'/[^/]+\*\*$', '/**', self.regex) else: newpath = re.sub('/[^/]+$', '/*', self.regex) return AARE(newpath, False) @@ -119,24 +119,24 @@ class AARE: """Glob given file path with extension Files without extensions and directories won't be changed""" # match /**.ext and /*.ext - match = re.search('/\*{1,2}(\.[^/]+)$', self.regex) + match = re.search(r'/\*{1,2}(\.[^/]+)$', self.regex) if match: # /foo/**.ext and /foo/*.ext => /**.ext - newpath = re.sub('/[^/]+/\*{1,2}\.[^/]+$', '/**' + match.groups()[0], self.regex) - elif re.search('/[^/]+\*\*[^/]*\.[^/]+$', self.regex): + newpath = re.sub(r'/[^/]+/\*{1,2}\.[^/]+$', '/**' + match.groups()[0], self.regex) + elif re.search(r'/[^/]+\*\*[^/]*\.[^/]+$', self.regex): # /foo**.ext and /foo**bar.ext => /**.ext - match = re.search('/[^/]+\*\*[^/]*(\.[^/]+)$', self.regex) - newpath = re.sub('/[^/]+\*\*[^/]*\.[^/]+$', '/**' + match.groups()[0], self.regex) - elif re.search('/\*\*[^/]+\.[^/]+$', self.regex): + match = re.search(r'/[^/]+\*\*[^/]*(\.[^/]+)$', self.regex) + newpath = re.sub(r'/[^/]+\*\*[^/]*\.[^/]+$', '/**' + match.groups()[0], self.regex) + elif re.search(r'/\*\*[^/]+\.[^/]+$', self.regex): # /**foo.ext => /**.ext - match = re.search('/\*\*[^/]+(\.[^/]+)$', self.regex) - newpath = re.sub('/\*\*[^/]+\.[^/]+$', '/**' + match.groups()[0], self.regex) + match = re.search(r'/\*\*[^/]+(\.[^/]+)$', self.regex) + newpath = re.sub(r'/\*\*[^/]+\.[^/]+$', '/**' + match.groups()[0], self.regex) else: newpath = self.regex - match = re.search('(\.[^/]+)$', self.regex) + match = re.search(r'(\.[^/]+)$', self.regex) if match: - newpath = re.sub('/[^/]+(\.[^/]+)$', '/*' + match.groups()[0], self.regex) - return AARE(newpath, False) + newpath = re.sub(r'/[^/]+(\.[^/]+)$', '/*' + match.groups()[0], self.regex) + return type(self)(newpath, False) def convert_expression_to_aare(expression): diff --git a/utils/apparmor/easyprof.py b/utils/apparmor/easyprof.py index f2536c83f..74b04316e 100644 --- a/utils/apparmor/easyprof.py +++ b/utils/apparmor/easyprof.py @@ -374,10 +374,10 @@ class AppArmorEasyProfile: if not pat.search(line): continue if line.startswith("POLICYGROUPS_DIR="): - d = re.split(r'=', line.strip())[1].strip('["\']') + d = re.split('=', line.strip())[1].strip('["\']') self.dirs['policygroups'] = d elif line.startswith("TEMPLATES_DIR="): - d = re.split(r'=', line.strip())[1].strip('["\']') + d = re.split('=', line.strip())[1].strip('["\']') self.dirs['templates'] = d keys = self.dirs.keys() diff --git a/utils/apparmor/regex.py b/utils/apparmor/regex.py index 47840e5ca..216e41407 100644 --- a/utils/apparmor/regex.py +++ b/utils/apparmor/regex.py @@ -21,67 +21,67 @@ from apparmor.translations import init_translation _ = init_translation() # Profile parsing Regex -RE_AUDIT_DENY = '^\s*(?Paudit\s+)?(?Pallow\s+|deny\s+)?' # line start, optionally: leading whitespace, and /deny -RE_EOL = '\s*(?P#.*?)?\s*$' # optional whitespace, optional , optional whitespace, end of the line -RE_COMMA_EOL = '\s*,' + RE_EOL # optional whitespace, comma + RE_EOL +RE_AUDIT_DENY = r'^\s*(?Paudit\s+)?(?Pallow\s+|deny\s+)?' # line start, optionally: leading whitespace, and /deny +RE_EOL = r'\s*(?P#.*?)?\s*$' # optional whitespace, optional , optional whitespace, end of the line +RE_COMMA_EOL = r'\s*,' + RE_EOL # optional whitespace, comma + RE_EOL -RE_PROFILE_NAME = '(?P<%s>(\S+|"[^"]+"))' # string without spaces, or quoted string. %s is the match group name -RE_PATH = '/\S*|"/[^"]*"' # filename (starting with '/') without spaces, or quoted filename. +RE_PROFILE_NAME = r'(?P<%s>(\S+|"[^"]+"))' # string without spaces, or quoted string. %s is the match group name +RE_PATH = r'/\S*|"/[^"]*"' # filename (starting with '/') without spaces, or quoted filename. RE_PROFILE_PATH = '(?P<%s>(' + RE_PATH + '))' # quoted or unquoted filename. %s is the match group name -RE_PROFILE_PATH_OR_VAR = '(?P<%s>(' + RE_PATH + '|@{\S+}\S*|"@{\S+}[^"]*"))' # quoted or unquoted filename or variable. %s is the match group name +RE_PROFILE_PATH_OR_VAR = '(?P<%s>(' + RE_PATH + r'|@{\S+}\S*|"@{\S+}[^"]*"))' # quoted or unquoted filename or variable. %s is the match group name RE_SAFE_OR_UNSAFE = '(?P(safe|unsafe))' -RE_XATTRS = '(\s+xattrs\s*=\s*\((?P([^)=]+(=[^)=]+)?\s?)+)\)\s*)?' -RE_FLAGS = '(\s+(flags\s*=\s*)?\((?P[^)]+)\))?' +RE_XATTRS = r'(\s+xattrs\s*=\s*\((?P([^)=]+(=[^)=]+)?\s?)+)\)\s*)?' +RE_FLAGS = r'(\s+(flags\s*=\s*)?\((?P[^)]+)\))?' -RE_PROFILE_END = re.compile('^\s*\}' + RE_EOL) -RE_PROFILE_CAP = re.compile(RE_AUDIT_DENY + 'capability(?P(\s+\S+)+)?' + RE_COMMA_EOL) -RE_PROFILE_ALIAS = re.compile('^\s*alias\s+(?P"??.+?"??)\s+->\s*(?P"??.+?"??)' + RE_COMMA_EOL) -RE_PROFILE_RLIMIT = re.compile('^\s*set\s+rlimit\s+(?P[a-z]+)\s*<=\s*(?P[^ ]+(\s+[a-zA-Z]+)?)' + RE_COMMA_EOL) -RE_PROFILE_BOOLEAN = re.compile('^\s*(?P\$\{?\w*\}?)\s*=\s*(?Ptrue|false)\s*,?' + RE_EOL, flags=re.IGNORECASE) -RE_PROFILE_VARIABLE = re.compile('^\s*(?P@\{?\w+\}?)\s*(?P\+?=)\s*(?P@*.+?)' + RE_EOL) -RE_PROFILE_CONDITIONAL = re.compile('^\s*if\s+(not\s+)?(\$\{?\w*\}?)\s*\{' + RE_EOL) -RE_PROFILE_CONDITIONAL_VARIABLE = re.compile('^\s*if\s+(not\s+)?defined\s+(@\{?\w+\}?)\s*\{\s*(#.*)?$') -RE_PROFILE_CONDITIONAL_BOOLEAN = re.compile('^\s*if\s+(not\s+)?defined\s+(\$\{?\w+\}?)\s*\{\s*(#.*)?$') -RE_PROFILE_NETWORK = re.compile(RE_AUDIT_DENY + 'network(?P
\s+.*)?' + RE_COMMA_EOL) -RE_PROFILE_CHANGE_HAT = re.compile('^\s*\^(\"??.+?\"??)' + RE_COMMA_EOL) -RE_PROFILE_HAT_DEF = re.compile('^(?P\s*)(?P\^|hat\s+)(?P\"??[^)]+?\"??)' + RE_FLAGS + '\s*\{' + RE_EOL) -RE_PROFILE_DBUS = re.compile(RE_AUDIT_DENY + '(dbus\s*,|dbus(?P
\s+[^#]*)\s*,)' + RE_EOL) -RE_PROFILE_MOUNT = re.compile(RE_AUDIT_DENY + '((mount|remount|umount|unmount)(\s+[^#]*)?\s*,)' + RE_EOL) -RE_PROFILE_SIGNAL = re.compile(RE_AUDIT_DENY + '(signal\s*,|signal(?P
\s+[^#]*)\s*,)' + RE_EOL) -RE_PROFILE_PTRACE = re.compile(RE_AUDIT_DENY + '(ptrace\s*,|ptrace(?P
\s+[^#]*)\s*,)' + RE_EOL) -RE_PROFILE_PIVOT_ROOT = re.compile(RE_AUDIT_DENY + '(pivot_root\s*,|pivot_root\s+[^#]*\s*,)' + RE_EOL) -RE_PROFILE_UNIX = re.compile(RE_AUDIT_DENY + '(unix\s*,|unix\s+[^#]*\s*,)' + RE_EOL) +RE_PROFILE_END = re.compile(r'^\s*\}' + RE_EOL) +RE_PROFILE_CAP = re.compile(RE_AUDIT_DENY + r'capability(?P(\s+\S+)+)?' + RE_COMMA_EOL) +RE_PROFILE_ALIAS = re.compile(r'^\s*alias\s+(?P"??.+?"??)\s+->\s*(?P"??.+?"??)' + RE_COMMA_EOL) +RE_PROFILE_RLIMIT = re.compile(r'^\s*set\s+rlimit\s+(?P[a-z]+)\s*<=\s*(?P[^ ]+(\s+[a-zA-Z]+)?)' + RE_COMMA_EOL) +RE_PROFILE_BOOLEAN = re.compile(r'^\s*(?P\$\{?\w*\}?)\s*=\s*(?Ptrue|false)\s*,?' + RE_EOL, flags=re.IGNORECASE) +RE_PROFILE_VARIABLE = re.compile(r'^\s*(?P@\{?\w+\}?)\s*(?P\+?=)\s*(?P@*.+?)' + RE_EOL) +RE_PROFILE_CONDITIONAL = re.compile(r'^\s*if\s+(not\s+)?(\$\{?\w*\}?)\s*\{' + RE_EOL) +RE_PROFILE_CONDITIONAL_VARIABLE = re.compile(r'^\s*if\s+(not\s+)?defined\s+(@\{?\w+\}?)\s*\{\s*(#.*)?$') +RE_PROFILE_CONDITIONAL_BOOLEAN = re.compile(r'^\s*if\s+(not\s+)?defined\s+(\$\{?\w+\}?)\s*\{\s*(#.*)?$') +RE_PROFILE_NETWORK = re.compile(RE_AUDIT_DENY + r'network(?P
\s+.*)?' + RE_COMMA_EOL) +RE_PROFILE_CHANGE_HAT = re.compile(r'^\s*\^("??.+?"??)' + RE_COMMA_EOL) +RE_PROFILE_HAT_DEF = re.compile(r'^(?P\s*)(?P\^|hat\s+)(?P"??[^)]+?"??)' + RE_FLAGS + r'\s*\{' + RE_EOL) +RE_PROFILE_DBUS = re.compile(RE_AUDIT_DENY + r'(dbus\s*,|dbus(?P
\s+[^#]*)\s*,)' + RE_EOL) +RE_PROFILE_MOUNT = re.compile(RE_AUDIT_DENY + r'((mount|remount|umount|unmount)(\s+[^#]*)?\s*,)' + RE_EOL) +RE_PROFILE_SIGNAL = re.compile(RE_AUDIT_DENY + r'(signal\s*,|signal(?P
\s+[^#]*)\s*,)' + RE_EOL) +RE_PROFILE_PTRACE = re.compile(RE_AUDIT_DENY + r'(ptrace\s*,|ptrace(?P
\s+[^#]*)\s*,)' + RE_EOL) +RE_PROFILE_PIVOT_ROOT = re.compile(RE_AUDIT_DENY + r'(pivot_root\s*,|pivot_root\s+[^#]*\s*,)' + RE_EOL) +RE_PROFILE_UNIX = re.compile(RE_AUDIT_DENY + r'(unix\s*,|unix\s+[^#]*\s*,)' + RE_EOL) # match anything that's not " or #, or matching quotes with anything except quotes inside __re_no_or_quoted_hash = '([^#"]|"[^"]*")*' RE_RULE_HAS_COMMA = re.compile( '^' + __re_no_or_quoted_hash - + ',\s*(#.*)?$') # match comma plus any trailing comment + + r',\s*(#.*)?$') # match comma plus any trailing comment RE_HAS_COMMENT_SPLIT = re.compile( '^(?P' + __re_no_or_quoted_hash + ')' # store in 'not_comment' group + '(?P#.*)$') # match trailing comment and store in 'comment' group RE_PROFILE_START = re.compile( - '^(?P\s*)' + r'^(?P\s*)' + '(' + RE_PROFILE_PATH_OR_VAR % 'plainprofile' # just a path + '|' # or - + '(' + 'profile' + '\s+' + RE_PROFILE_NAME % 'namedprofile' + '(\s+' + RE_PROFILE_PATH_OR_VAR % 'attachment' + ')?' + ')' # 'profile', profile name, optionally attachment + + '(' + 'profile' + r'\s+' + RE_PROFILE_NAME % 'namedprofile' + r'(\s+' + RE_PROFILE_PATH_OR_VAR % 'attachment' + ')?' + ')' # 'profile', profile name, optionally attachment + ')' + RE_XATTRS + RE_FLAGS - + '\s*\{' + + r'\s*\{' + RE_EOL) RE_PROFILE_CHANGE_PROFILE = re.compile( RE_AUDIT_DENY + 'change_profile' - + '(\s+' + RE_SAFE_OR_UNSAFE + ')?' # optionally exec mode - + '(\s+' + RE_PROFILE_PATH_OR_VAR % 'execcond' + ')?' # optionally exec condition - + '(\s+->\s*' + RE_PROFILE_NAME % 'targetprofile' + ')?' # optionally '->' target profile + + r'(\s+' + RE_SAFE_OR_UNSAFE + ')?' # optionally exec mode + + r'(\s+' + RE_PROFILE_PATH_OR_VAR % 'execcond' + ')?' # optionally exec condition + + r'(\s+->\s*' + RE_PROFILE_NAME % 'targetprofile' + ')?' # optionally '->' target profile + RE_COMMA_EOL) @@ -91,22 +91,22 @@ RE_PATH_PERMS = '(?P<%s>[mrwalkPUCpucix]+)' RE_PROFILE_FILE_ENTRY = re.compile( RE_AUDIT_DENY - + '(?Powner\s+)?' # optionally: + + r'(?Powner\s+)?' # optionally: + '(' + '(?Pfile)' # bare 'file,' + '|' # or - + '(?Pfile\s+)?' # optional 'file' keyword + + r'(?Pfile\s+)?' # optional 'file' keyword + '(' - + RE_PROFILE_PATH_OR_VAR % 'path' + '\s+' + RE_PATH_PERMS % 'perms' # path and perms + + RE_PROFILE_PATH_OR_VAR % 'path' + r'\s+' + RE_PATH_PERMS % 'perms' # path and perms + '|' # or - + RE_PATH_PERMS % 'perms2' + '\s+' + RE_PROFILE_PATH_OR_VAR % 'path2' # perms and path + + RE_PATH_PERMS % 'perms2' + r'\s+' + RE_PROFILE_PATH_OR_VAR % 'path2' # perms and path + ')' - + '(\s+->\s*' + RE_PROFILE_NAME % 'target' + ')?' + + r'(\s+->\s*' + RE_PROFILE_NAME % 'target' + ')?' + '|' # or - + '(?Plink\s+)' # 'link' keyword - + '(?Psubset\s+)?' # optional 'subset' keyword + + r'(?Plink\s+)' # 'link' keyword + + r'(?Psubset\s+)?' # optional 'subset' keyword + RE_PROFILE_PATH_OR_VAR % 'link_path' # path - + '\s+' + '->' + '\s+' # ' -> ' + + r'\s+' + '->' + r'\s+' # ' -> ' + RE_PROFILE_PATH_OR_VAR % 'link_target' # path + ')' + RE_COMMA_EOL) @@ -163,8 +163,8 @@ def parse_profile_start_line(line, filename): RE_MAGIC_OR_QUOTED_PATH = '(<(?P.*)>|"(?P.*)"|(?P[^<>"]*))' -RE_ABI = re.compile('^\s*#?abi\s*' + RE_MAGIC_OR_QUOTED_PATH + RE_COMMA_EOL) -RE_INCLUDE = re.compile('^\s*#?include(?P\s+if\s+exists)?\s*' + RE_MAGIC_OR_QUOTED_PATH + RE_EOL) +RE_ABI = re.compile(r'^\s*#?abi\s*' + RE_MAGIC_OR_QUOTED_PATH + RE_COMMA_EOL) +RE_INCLUDE = re.compile(r'^\s*#?include(?P\s+if\s+exists)?\s*' + RE_MAGIC_OR_QUOTED_PATH + RE_EOL) def re_match_include_parse(line, rule_name): @@ -195,7 +195,7 @@ def re_match_include_parse(line, rule_name): ismagic = True elif matches.group('unquotedpath'): path = matches.group('unquotedpath').strip() - if re.search('\s', path): + if re.search(r'\s', path): raise AppArmorException(_('Syntax error: %s must use quoted path or <...>') % rule_name) # LP: #1738879 - parser doesn't handle unquoted paths everywhere if rule_name == 'include': @@ -211,7 +211,7 @@ def re_match_include_parse(line, rule_name): raise AppArmorException(_('Syntax error: %s rule with empty filename') % rule_name) # LP: #1738877 - parser doesn't handle files with spaces in the name - if rule_name == 'include' and re.search('\s', path): + if rule_name == 'include' and re.search(r'\s', path): raise AppArmorException(_('Syntax error: %s rule filename cannot contain spaces') % rule_name) ifexists = False diff --git a/utils/apparmor/rule/dbus.py b/utils/apparmor/rule/dbus.py index af406b732..4a595795d 100644 --- a/utils/apparmor/rule/dbus.py +++ b/utils/apparmor/rule/dbus.py @@ -27,43 +27,43 @@ message_keywords = ['send', 'receive', 'r', 'read', 'w', 'write', 'rw'] access_keywords = ['bind', 'eavesdrop'] + message_keywords # XXX joint_access_keyword and RE_ACCESS_KEYWORDS exactly as in SignalRule - move to function? -joint_access_keyword = '(' + '(\s|,)*' + '(' + '|'.join(access_keywords) + ')(\s|,)*' + ')' +joint_access_keyword = '(' + r'(\s|,)*' + '(' + '|'.join(access_keywords) + r')(\s|,)*' + ')' RE_ACCESS_KEYWORDS = ( joint_access_keyword # one of the access_keyword + '|' # or - + '\(' + '(\s|,)*' + joint_access_keyword + '?' + '(' + '(\s|,)+' + joint_access_keyword + ')*' + '\)' # one or more access_keyword in (...) + + r'\(' + r'(\s|,)*' + joint_access_keyword + '?' + '(' + r'(\s|,)+' + joint_access_keyword + ')*' + r'\)' # one or more access_keyword in (...) ) -RE_FLAG = '(?P<%s>(\S+|"[^"]+"|\(\s*\S+\s*\)|\(\s*"[^"]+"\)\s*))' # string without spaces, or quoted string, optionally wrapped in (...). %s is the match group name +RE_FLAG = r'(?P<%s>(\S+|"[^"]+"|\(\s*\S+\s*\)|\(\s*"[^"]+"\)\s*))' # string without spaces, or quoted string, optionally wrapped in (...). %s is the match group name # plaintext version: | * | "* " | ( * ) | ( " * " ) | # XXX this regex will allow repeated parameters, last one wins # XXX (the parser will reject such rules) RE_DBUS_DETAILS = re.compile( '^' - + '(\s+(?P' + RE_ACCESS_KEYWORDS + '))?' # optional access keyword(s) + + r'(\s+(?P' + RE_ACCESS_KEYWORDS + '))?' # optional access keyword(s) + '(' - + '(\s+(bus\s*=\s*' + RE_FLAG % 'bus' + '))?|' # optional bus= system | session | AARE, (...) optional - + '(\s+(path\s*=\s*' + RE_FLAG % 'path' + '))?|' # optional path=AARE, (...) optional - + '(\s+(name\s*=\s*' + RE_FLAG % 'name' + '))?|' # optional name=AARE, (...) optional - + '(\s+(interface\s*=\s*' + RE_FLAG % 'interface' + '))?|' # optional interface=AARE, (...) optional - + '(\s+(member\s*=\s*' + RE_FLAG % 'member' + '))?|' # optional member=AARE, (...) optional - + '(\s+(peer\s*=\s*\((,|\s)*' # optional peer=(name=AARE and/or label=AARE), (...) required + + r'(\s+(bus\s*=\s*' + RE_FLAG % 'bus' + '))?|' # optional bus= system | session | AARE, (...) optional + + r'(\s+(path\s*=\s*' + RE_FLAG % 'path' + '))?|' # optional path=AARE, (...) optional + + r'(\s+(name\s*=\s*' + RE_FLAG % 'name' + '))?|' # optional name=AARE, (...) optional + + r'(\s+(interface\s*=\s*' + RE_FLAG % 'interface' + '))?|' # optional interface=AARE, (...) optional + + r'(\s+(member\s*=\s*' + RE_FLAG % 'member' + '))?|' # optional member=AARE, (...) optional + + r'(\s+(peer\s*=\s*\((,|\s)*' # optional peer=(name=AARE and/or label=AARE), (...) required + '(' - + '(' + '(,|\s)*' + ')' # empty peer=() + + '(' + r'(,|\s)*' + ')' # empty peer=() + '|' # or - + '(' + 'name\s*=\s*' + RE_PROFILE_NAME % 'peername1' + ')' # only peer name (match group peername1) + + '(' + r'name\s*=\s*' + RE_PROFILE_NAME % 'peername1' + ')' # only peer name (match group peername1) + '|' # or - + '(' 'label\s*=\s*' + RE_PROFILE_NAME % 'peerlabel1' + ')' # only peer label (match group peerlabel1) + + '(' r'label\s*=\s*' + RE_PROFILE_NAME % 'peerlabel1' + ')' # only peer label (match group peerlabel1) + '|' # or - + '(' + 'name\s*=\s*' + RE_PROFILE_NAME % 'peername2' + '(,|\s)+' + 'label\s*=\s*' + RE_PROFILE_NAME % 'peerlabel2' + ')' # peer name + label (match name peername2/peerlabel2) + + '(' + r'name\s*=\s*' + RE_PROFILE_NAME % 'peername2' + r'(,|\s)+' + r'label\s*=\s*' + RE_PROFILE_NAME % 'peerlabel2' + ')' # peer name + label (match name peername2/peerlabel2) + '|' # or - + '(' + 'label\s*=\s*' + RE_PROFILE_NAME % 'peerlabel3' + '(,|\s)+' + 'name\s*=\s*' + RE_PROFILE_NAME % 'peername3' + ')' # peer label + name (match name peername3/peerlabel3) + + '(' + r'label\s*=\s*' + RE_PROFILE_NAME % 'peerlabel3' + r'(,|\s)+' + r'name\s*=\s*' + RE_PROFILE_NAME % 'peername3' + ')' # peer label + name (match name peername3/peerlabel3) + ')' - + '(,|\s)*\)))?' + + r'(,|\s)*\)))?' + '){0,6}' - + '\s*$') + + r'\s*$') class DbusRule(BaseRule): @@ -79,7 +79,7 @@ class DbusRule(BaseRule): rule_name = 'dbus' def __init__(self, access, bus, path, name, interface, member, peername, peerlabel, - audit=False, deny=False, allow_keyword=False, comment='', log_event=None): + audit=False, deny=False, allow_keyword=False, comment='', log_event=None): super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment, log_event=log_event) diff --git a/utils/apparmor/rule/network.py b/utils/apparmor/rule/network.py index 5e6600443..713bed61b 100644 --- a/utils/apparmor/rule/network.py +++ b/utils/apparmor/rule/network.py @@ -37,10 +37,10 @@ RE_NETWORK_TYPE = '(' + '|'.join(network_type_keywords) + ')' RE_NETWORK_PROTOCOL = '(' + '|'.join(network_protocol_keywords) + ')' RE_NETWORK_DETAILS = re.compile( - '^\s*' + r'^\s*' + '(?P' + RE_NETWORK_DOMAIN + ')?' # optional domain - + '(\s+(?P' + RE_NETWORK_TYPE + '|' + RE_NETWORK_PROTOCOL + '))?' # optional type or protocol - + '\s*$') + + r'(\s+(?P' + RE_NETWORK_TYPE + '|' + RE_NETWORK_PROTOCOL + '))?' # optional type or protocol + + r'\s*$') class NetworkRule(BaseRule): diff --git a/utils/apparmor/rule/ptrace.py b/utils/apparmor/rule/ptrace.py index e2872e9c5..57e382298 100644 --- a/utils/apparmor/rule/ptrace.py +++ b/utils/apparmor/rule/ptrace.py @@ -26,17 +26,17 @@ _ = init_translation() access_keywords = ['r', 'w', 'rw', 'wr', 'read', 'write', 'readby', 'trace', 'tracedby'] # XXX 'wr' and 'write' accepted by the parser, but not documented in apparmor.d.pod # XXX joint_access_keyword and RE_ACCESS_KEYWORDS exactly as in PtraceRule - move to function! -joint_access_keyword = '\s*(' + '|'.join(access_keywords) + ')\s*' +joint_access_keyword = r'\s*(' + '|'.join(access_keywords) + r')\s*' RE_ACCESS_KEYWORDS = (joint_access_keyword # one of the access_keyword + '|' # or - + '\(' + joint_access_keyword + '(' + '(\s|,)+' + joint_access_keyword + ')*' + '\)') # one or more access_keyword in (...) + + r'\(' + joint_access_keyword + '(' + r'(\s|,)+' + joint_access_keyword + ')*' + r'\)') # one or more access_keyword in (...) RE_PTRACE_DETAILS = re.compile( '^' - + '(\s+(?P' + RE_ACCESS_KEYWORDS + '))?' # optional access keyword(s) - + '(\s+(peer=' + RE_PROFILE_NAME % 'peer' + '))?' # optional peer - + '\s*$') + + r'(\s+(?P' + RE_ACCESS_KEYWORDS + '))?' # optional access keyword(s) + + r'(\s+(peer=' + RE_PROFILE_NAME % 'peer' + '))?' # optional peer + + r'\s*$') class PtraceRule(BaseRule): diff --git a/utils/apparmor/rule/rlimit.py b/utils/apparmor/rule/rlimit.py index 6fbb20a5f..12d1d45bc 100644 --- a/utils/apparmor/rule/rlimit.py +++ b/utils/apparmor/rule/rlimit.py @@ -29,9 +29,9 @@ rlimit_nice = ['nice'] # a number between -20 and 19. rlimit_all = rlimit_size + rlimit_number + rlimit_time + rlimit_nice -RE_NUMBER_UNIT = re.compile('^(?P[0-9]+)\s*(?P[a-zA-Z]*)$') +RE_NUMBER_UNIT = re.compile(r'^(?P[0-9]+)\s*(?P[a-zA-Z]*)$') RE_NUMBER = re.compile('^[0-9]+$') -RE_UNIT_SIZE = re.compile('^[0-9]+\s*([KMG]B?)?$') +RE_UNIT_SIZE = re.compile(r'^[0-9]+\s*([KMG]B?)?$') RE_NICE = re.compile('^(-20|-[01]?[0-9]|[01]?[0-9])$') diff --git a/utils/apparmor/rule/signal.py b/utils/apparmor/rule/signal.py index 78630d3e7..3eb50b15d 100644 --- a/utils/apparmor/rule/signal.py +++ b/utils/apparmor/rule/signal.py @@ -33,34 +33,34 @@ signal_keywords = [ 'segv', 'usr2', 'pipe', 'alrm', 'term', 'stkflt', 'chld', 'cont', 'stop', 'stp', 'ttin', 'ttou', 'urg', 'xcpu', 'xfsz', 'vtalrm', 'prof', 'winch', 'io', 'pwr', 'sys', 'emt', 'exists'] -RE_SIGNAL_REALTIME = re.compile('^rtmin\+0*([0-9]|[12][0-9]|3[0-2])$') # rtmin+0..rtmin+32, number may have leading zeros +RE_SIGNAL_REALTIME = re.compile(r'^rtmin\+0*([0-9]|[12][0-9]|3[0-2])$') # rtmin+0..rtmin+32, number may have leading zeros -joint_access_keyword = '\s*(' + '|'.join(access_keywords) + ')\s*' +joint_access_keyword = r'\s*(' + '|'.join(access_keywords) + r')\s*' RE_ACCESS_KEYWORDS = ( joint_access_keyword # one of the access_keyword + '|' # or - + '\(' + joint_access_keyword + '(' + '(\s|,)+' + joint_access_keyword + ')*' + '\)' # one or more access_keyword in (...) + + r'\(' + joint_access_keyword + '(' + r'(\s|,)+' + joint_access_keyword + ')*' + r'\)' # one or more access_keyword in (...) ) -signal_keyword = '\s*([a-z0-9+]+|"[a-z0-9+]+")\s*' # don't check against the signal keyword list in the regex to allow a more helpful error message +signal_keyword = r'\s*([a-z0-9+]+|"[a-z0-9+]+")\s*' # don't check against the signal keyword list in the regex to allow a more helpful error message RE_SIGNAL_KEYWORDS = ( - 'set\s*=\s*' + signal_keyword # one of the signal_keyword + r'set\s*=\s*' + signal_keyword # one of the signal_keyword + '|' # or - + 'set\s*=\s*\(' + signal_keyword + '(' + '(\s|,)+' + signal_keyword + ')*' + '\)' # one or more signal_keyword in (...) + + r'set\s*=\s*\(' + signal_keyword + '(' + r'(\s|,)+' + signal_keyword + ')*' + r'\)' # one or more signal_keyword in (...) ) RE_SIGNAL_DETAILS = re.compile( '^' - + '(\s+(?P' + RE_ACCESS_KEYWORDS + '))?' # optional access keyword(s) - + '(?P' + '(\s+(' + RE_SIGNAL_KEYWORDS + '))+' + ')?' # optional signal set(s) - + '(\s+(peer=' + RE_PROFILE_NAME % 'peer' + '))?' # optional peer - + '\s*$') + + r'(\s+(?P' + RE_ACCESS_KEYWORDS + '))?' # optional access keyword(s) + + '(?P' + r'(\s+(' + RE_SIGNAL_KEYWORDS + '))+' + ')?' # optional signal set(s) + + r'(\s+(peer=' + RE_PROFILE_NAME % 'peer' + '))?' # optional peer + + r'\s*$') -RE_FILTER_SET_1 = re.compile('set\s*=\s*\(([^)]*)\)') -RE_FILTER_SET_2 = re.compile('set\s*=') -RE_FILTER_PARENTHESIS = re.compile('\((.*)\)') +RE_FILTER_SET_1 = re.compile(r'set\s*=\s*\(([^)]*)\)') +RE_FILTER_SET_2 = re.compile(r'set\s*=') +RE_FILTER_PARENTHESIS = re.compile(r'\((.*)\)') RE_FILTER_QUOTES = re.compile('"([a-z0-9]+)"') # used to strip quotes around signal keywords - don't use for peer! diff --git a/utils/apparmor/rule/variable.py b/utils/apparmor/rule/variable.py index e6d8e0841..90eee9ba1 100644 --- a/utils/apparmor/rule/variable.py +++ b/utils/apparmor/rule/variable.py @@ -179,7 +179,7 @@ def separate_vars(vs): data = set() vs = vs.strip() - re_vars = re.compile('^(("[^"]*")|([^"\s]+))\s*(.*)$') + re_vars = re.compile(r'^(("[^"]*")|([^"\s]+))\s*(.*)$') while re_vars.search(vs): matches = re_vars.search(vs).groups() diff --git a/utils/apparmor/ui.py b/utils/apparmor/ui.py index 7395f78ce..7c3e73ac0 100644 --- a/utils/apparmor/ui.py +++ b/utils/apparmor/ui.py @@ -108,8 +108,8 @@ def get_translated_hotkey(translated, cmsg=''): msg = 'PromptUser: ' + _('Invalid hotkey for') # Originally (\S) was used but with translations it would not work :( - if re.search('\((\S+)\)', translated): - return re.search('\((\S+)\)', translated).groups()[0] + if re.search(r'\((\S+)\)', translated): + return re.search(r'\((\S+)\)', translated).groups()[0] else: if cmsg: raise AppArmorException(cmsg) @@ -439,7 +439,7 @@ class PromptQuestion: function_regexp = '^(' function_regexp += '|'.join(keys.keys()) if options: - function_regexp += '|\d' + function_regexp += r'|\d' function_regexp += ')$' ans = 'XXXINVALIDXXX' @@ -511,7 +511,7 @@ class PromptQuestion: # If they hit return choose default option ans = default_key - elif options and re.search('^\d$', ans): + elif options and re.search(r'^\d$', ans): ans = int(ans) if ans > 0 and ans <= len(options): selected = ans - 1 diff --git a/utils/test/test-aa-decode.py b/utils/test/test-aa-decode.py index 55974fc82..3abac701a 100755 --- a/utils/test/test-aa-decode.py +++ b/utils/test/test-aa-decode.py @@ -162,9 +162,9 @@ type=AVC msg=audit(1348982148.195:2933): apparmor="DENIED" operation="file_lock" self._run_file_test(content, expected_strings) def test_simple_embedded_backslash_carat(self): - """test simple decoding of embedded \^ in files""" + r"""test simple decoding of embedded \^ in files""" - expected_strings = ('name="/home/steve/tmp/my test \^file"',) + expected_strings = (r'name="/home/steve/tmp/my test \^file"',) content = \ '''type=AVC msg=audit(1349805073.402:6857): apparmor="DENIED" operation="mknod" parent=5890 profile="/usr/bin/test_profile" name=2F686F6D652F73746576652F746D702F6D792074657374205C5E66696C65 pid=5891 comm="touch" requested_mask="c" denied_mask="c" fsuid=1000 ouid=1000 ''' diff --git a/utils/test/test-aa-easyprof.py b/utils/test/test-aa-easyprof.py index 5b3c7368d..eb4ea0a85 100755 --- a/utils/test/test-aa-easyprof.py +++ b/utils/test/test-aa-easyprof.py @@ -2645,7 +2645,7 @@ POLICYGROUPS_DIR="%s/templates" 'foo<', 'foo>', 'foo?', - 'foo\/', + r'foo\/', 'foo,', '_foo', ] diff --git a/utils/test/test-aare.py b/utils/test/test-aare.py index d37e6dfba..7198470bb 100644 --- a/utils/test/test-aare.py +++ b/utils/test/test-aare.py @@ -21,17 +21,17 @@ from common_test import AATest, setup_all_loops class TestConvert_regexp(AATest): tests = ( - ('/foo', '^/foo$'), - ('/{foo,bar}', '^/(foo|bar)$'), - # ('/\{foo,bar}', '^/\{foo,bar}$'), # XXX gets converted to ^/\(foo|bar)$ - ('/fo[abc]', '^/fo[abc]$'), - ('/foo bar', '^/foo bar$'), - ('/x\y', '^/x\y$'), - ('/x\[y', '^/x\[y$'), - ('/x\\y', '^/x\\y$'), - ('/fo?', '^/fo[^/\000]$'), - ('/foo/*', '^/foo/(((?<=/)[^/\000]+)|((?audit\s+)?(?Pallow\s+|deny\s+|invalid\s+)?') + regex = re.compile(r'^\s*(?Paudit\s+)?(?Pallow\s+|deny\s+|invalid\s+)?') matches = regex.search('audit invalid ') with self.assertRaises(AppArmorBug):