blob: fbeaff8e59ffd7d6e442a0e97eb498fdec3c2a70 [file] [log] [blame]
Dan Cashman91d398d2017-09-26 12:58:29 -07001from 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 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
98if __name__ == '__main__':
99 f = sys.argv[1]
100 p = MiniCilParser(f)