-
Notifications
You must be signed in to change notification settings - Fork 3
/
sepolicy.py
200 lines (136 loc) · 3.92 KB
/
sepolicy.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
import re
def typetransition_varargs_index(parts):
l = len(parts)
if l == 6 or l == 5:
return l
raise Exception(f'Invalid typetransition length: {l}, rule: {parts}')
def typeattribute_varargs_index(parts):
l = len(parts)
if l == 2 or l == 3:
return l
raise Exception(f'Invalid typeattribute length: {l}, rule: {parts}')
keyword_parts_main_type = {
'genfscon': 5,
}
keyword_varargs_index = {
'allow': 4,
'allowx': 5,
'neverallowx': 5,
'dontaudit': 4,
'auditallow': 4,
'genfscon': 8,
'neverallow': 4,
'roletype': 3,
'type': 2,
'typeattribute': typeattribute_varargs_index,
'typeattributeset': 2,
'typetransition': typetransition_varargs_index,
'attribute': 2,
}
keyword_varargs_keep_order = {
'typeattributeset': True,
'allowx': True,
'neverallowx': True,
}
def keep_varargs_order(parts):
return keyword_varargs_keep_order.get(parts[0], False)
def split_varargs(parts):
index = keyword_varargs_index.get(parts[0], 2)
if callable(index):
index = index(parts)
return parts[:index], parts[index:]
def parts_main_type(parts):
index = keyword_parts_main_type.get(parts[0], 1)
return parts[index]
def sanitize_type(type):
type = re.sub(r'(_\d+)+$', '', type)
return type
def extract_type(type):
type = re.sub(r'^vendor_', '', type)
type = re.sub(r'_exec$', '', type)
type = re.sub(r'_client$', '', type)
type = re.sub(r'_server$', '', type)
type = re.sub(r'_default$', '', type)
type = re.sub(r'_hwservice$', '', type)
type = re.sub(r'_qti$', '', type)
return type
def format_macro(rule):
params_str = ', '.join(rule.parts[1:])
return f'{rule.parts[0]}({params_str})'
def sort_varargs(varargs):
if isinstance(varargs, set):
varargs = list(varargs)
varargs.sort()
return varargs
def join_varargs(varargs):
s = ' '.join(varargs)
if len(varargs) > 1:
s = '{ ' + s + ' }'
return s
def format_allow(rule):
varargs = sort_varargs(rule.varargs)
return '{} {} {}:{} {};'.format(*rule.parts, join_varargs(varargs));
def format_allowx(rule):
if rule.parts[0] == 'allowx':
rule_type = 'allowxperm'
elif rule.parts[0] == 'neverallowx':
rule_type = 'neverallowxperm'
return '{} {} {}:{} {} {};'.format(rule_type, *rule.parts[1:], join_varargs(rule.varargs));
def format_type(rule):
varargs = sort_varargs(rule.varargs)
s = ', '.join(varargs)
return '{} {}, {};'.format(*rule.parts, s);
def format_attribute(rule):
return '{} {};'.format(*rule.parts)
def format_typetransition(rule):
l = len(rule.parts)
if l == 6:
name = ' ' + rule.parts[4]
else:
name = ''
return 'type_transition {} {}:{} {}{};'.format(*rule.parts[1:4], rule.parts[l - 1], name);
def format_permissive(rule):
return 'permissive {};'.format(rule.parts[1])
def format_genfscon(rule):
return '{} {} {} {}:{}:{}:{}'.format(*rule.parts)
def format_noop(rule):
return ''
keyword_format_fn = {
'allow': format_allow,
'allowx': format_allowx,
'neverallowx': format_allowx,
'dontaudit': format_allow,
'auditallow': format_allow,
'neverallow': format_allow,
'type': format_type,
'attribute': format_attribute,
'typetransition': format_typetransition,
'genfscon': format_genfscon,
'typepermissive': format_permissive,
}
def format_rule(rule):
keyword = rule.parts[0]
if keyword in keyword_format_fn:
return keyword_format_fn[keyword](rule)
return format_macro(rule)
class Rule:
def __init__(self, parts, varargs=None, main_type=None):
if varargs is None:
parts, varargs = split_varargs(parts)
if not isinstance(varargs, set) and not keep_varargs_order(parts):
varargs = set(varargs)
if main_type is None:
main_type = parts_main_type(parts)
self.parts = parts
self.varargs = varargs
self.main_type = main_type
def __str__(self):
return format_rule(self)
def __eq__(self, other):
return self.parts == other.parts and self.varargs == other.varargs
class Type:
def __init__(self, type_name):
self.type_name = type_name
self.rules = []
def add_rule(self, rule):
self.rules.append(rule)