1 from os.path import basename 2 import re 3 import 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 11 class 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 else: 81 m = re.match(r"(\w+)\s+.+", stmt) 82 ret = "Warning: Unknown statement type (" + m.group(1) + ") in " 83 ret += "mapping file, perhaps consider adding support for it in " 84 ret += "system/sepolicy/tests/mini_parser.py!\n" 85 print ret 86 return 87 88 def __init__(self, policyFile): 89 with open(policyFile, 'r') as infile: 90 s = self._getNextStmt(infile) 91 while s: 92 self._parseStmt(s) 93 s = self._getNextStmt(infile) 94 fn = basename(policyFile) 95 m = re.match(r"(\d+\.\d+).+\.cil", fn) 96 self.apiLevel = m.group(1) 97 98 if __name__ == '__main__': 99 f = sys.argv[1] 100 p = MiniCilParser(f) 101