17f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashmanfrom os.path import basename 27f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashmanimport re 37f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashmanimport sys 47f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman 57f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman# A very limited parser whose job is to process the compatibility mapping 67f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman# files and retrieve type and attribute information until proper support is 77f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman# built into libsepol 87f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman 97f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman# get the text in the next matching parens 107f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman 117f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashmanclass MiniCilParser: 127f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman types = set() # types declared in mapping 137f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman pubtypes = set() 147f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman typeattributes = set() # attributes declared in mapping 157f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman typeattributesets = {} # sets defined in mapping 167f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman rTypeattributesets = {} # reverse mapping of above sets 177f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman apiLevel = None 187f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman 197f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman def _getNextStmt(self, infile): 207f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman parens = 0 217f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman s = "" 227f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman c = infile.read(1) 237f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman # get to first statement 247f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman while c and c != "(": 257f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman c = infile.read(1) 267f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman 277f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman parens += 1 287f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman c = infile.read(1) 297f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman while c and parens != 0: 307f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman s += c 317f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman c = infile.read(1) 327f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman if c == ';': 337f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman # comment, get rid of rest of the line 347f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman while c != '\n': 357f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman c = infile.read(1) 367f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman elif c == '(': 377f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman parens += 1 387f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman elif c == ')': 397f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman parens -= 1 407f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman return s 417f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman 427f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman def _parseType(self, stmt): 437f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman m = re.match(r"type\s+(.+)", stmt) 448682d712d961d7a4937c648277f3dfeb47e27d52Dan Cashman self.types.add(m.group(1)) 457f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman return 467f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman 477f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman def _parseTypeattribute(self, stmt): 487f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman m = re.match(r"typeattribute\s+(.+)", stmt) 498682d712d961d7a4937c648277f3dfeb47e27d52Dan Cashman self.typeattributes.add(m.group(1)) 507f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman return 517f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman 527f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman def _parseTypeattributeset(self, stmt): 537f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman m = re.match(r"typeattributeset\s+(.+?)\s+\((.+?)\)", stmt, flags = re.M |re.S) 547f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman ta = m.group(1) 557f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman # this isn't proper expression parsing, but will do for our 567f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman # current use 577f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman tas = m.group(2).split() 587f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman 597f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman if self.typeattributesets.get(ta) is None: 607f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman self.typeattributesets[ta] = set() 617f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman self.typeattributesets[ta].update(set(tas)) 627f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman for t in tas: 637f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman if self.rTypeattributesets.get(t) is None: 647f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman self.rTypeattributesets[t] = set() 657f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman self.rTypeattributesets[t].update(set(ta)) 667f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman 677f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman # check to see if this typeattributeset is a versioned public type 687f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman pub = re.match(r"(\w+)_\d+_\d+", ta) 697f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman if pub is not None: 708682d712d961d7a4937c648277f3dfeb47e27d52Dan Cashman self.pubtypes.add(pub.group(1)) 717f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman return 727f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman 737f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman def _parseStmt(self, stmt): 747f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman if re.match(r"type\s+.+", stmt): 757f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman self._parseType(stmt) 767f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman elif re.match(r"typeattribute\s+.+", stmt): 777f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman self._parseTypeattribute(stmt) 787f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman elif re.match(r"typeattributeset\s+.+", stmt): 797f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman self._parseTypeattributeset(stmt) 807f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman else: 817f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman m = re.match(r"(\w+)\s+.+", stmt) 827f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman ret = "Warning: Unknown statement type (" + m.group(1) + ") in " 837f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman ret += "mapping file, perhaps consider adding support for it in " 847f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman ret += "system/sepolicy/tests/mini_parser.py!\n" 857f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman print ret 867f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman return 877f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman 887f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman def __init__(self, policyFile): 897f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman with open(policyFile, 'r') as infile: 907f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman s = self._getNextStmt(infile) 917f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman while s: 927f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman self._parseStmt(s) 937f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman s = self._getNextStmt(infile) 947f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman fn = basename(policyFile) 957f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman m = re.match(r"(\d+\.\d+).+\.cil", fn) 967f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman self.apiLevel = m.group(1) 977f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman 987f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashmanif __name__ == '__main__': 997f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman f = sys.argv[1] 1007f7c3b8229b245bc4928cb4a52c0db0e52609f21Dan Cashman p = MiniCilParser(f) 101