1from os.path import basename 2import re 3import sys 4 5# A very limited parser whose job is to process the compatibility mapping 6# files and retrieve type and attribute information until proper support is 7# built into libsepol 8 9# get the text in the next matching parens 10 11class MiniCilParser: 12 types = set() # types declared in mapping 13 pubtypes = set() 14 typeattributes = set() # attributes declared in mapping 15 typeattributesets = {} # sets defined in mapping 16 rTypeattributesets = {} # reverse mapping of above sets 17 apiLevel = None 18 19 def _getNextStmt(self, infile): 20 parens = 0 21 s = "" 22 c = infile.read(1) 23 # get to first statement 24 while c and c != "(": 25 c = infile.read(1) 26 27 parens += 1 28 c = infile.read(1) 29 while c and parens != 0: 30 s += c 31 c = infile.read(1) 32 if c == ';': 33 # comment, get rid of rest of the line 34 while c != '\n': 35 c = infile.read(1) 36 elif c == '(': 37 parens += 1 38 elif c == ')': 39 parens -= 1 40 return s 41 42 def _parseType(self, stmt): 43 m = re.match(r"type\s+(.+)", stmt) 44 self.types.add(m.group(1)) 45 return 46 47 def _parseTypeattribute(self, stmt): 48 m = re.match(r"typeattribute\s+(.+)", stmt) 49 self.typeattributes.add(m.group(1)) 50 return 51 52 def _parseTypeattributeset(self, stmt): 53 m = re.match(r"typeattributeset\s+(.+?)\s+\((.+?)\)", stmt, flags = re.M |re.S) 54 ta = m.group(1) 55 # this isn't proper expression parsing, but will do for our 56 # current use 57 tas = m.group(2).split() 58 59 if self.typeattributesets.get(ta) is None: 60 self.typeattributesets[ta] = set() 61 self.typeattributesets[ta].update(set(tas)) 62 for t in tas: 63 if self.rTypeattributesets.get(t) is None: 64 self.rTypeattributesets[t] = set() 65 self.rTypeattributesets[t].update(set(ta)) 66 67 # check to see if this typeattributeset is a versioned public type 68 pub = re.match(r"(\w+)_\d+_\d+", ta) 69 if pub is not None: 70 self.pubtypes.add(pub.group(1)) 71 return 72 73 def _parseStmt(self, stmt): 74 if re.match(r"type\s+.+", stmt): 75 self._parseType(stmt) 76 elif re.match(r"typeattribute\s+.+", stmt): 77 self._parseTypeattribute(stmt) 78 elif re.match(r"typeattributeset\s+.+", stmt): 79 self._parseTypeattributeset(stmt) 80 elif re.match(r"expandtypeattribute\s+.+", stmt): 81 # To silence the build warnings. 82 pass 83 else: 84 m = re.match(r"(\w+)\s+.+", stmt) 85 ret = "Warning: Unknown statement type (" + m.group(1) + ") in " 86 ret += "mapping file, perhaps consider adding support for it in " 87 ret += "system/sepolicy/tests/mini_parser.py!\n" 88 print ret 89 return 90 91 def __init__(self, policyFile): 92 with open(policyFile, 'r') as infile: 93 s = self._getNextStmt(infile) 94 while s: 95 self._parseStmt(s) 96 s = self._getNextStmt(infile) 97 fn = basename(policyFile) 98 m = re.match(r"(\d+\.\d+).+\.cil", fn) 99 self.apiLevel = m.group(1) 100 101if __name__ == '__main__': 102 f = sys.argv[1] 103 p = MiniCilParser(f) 104