@@ -99,6 +99,7 @@ local_files = None
fcdict = None
methods = []
all_types = None
+all_types_info = None
user_types = None
role_allows = None
portrecs = None
@@ -113,6 +114,8 @@ bools = None
all_attributes = None
booleans = None
booleans_dict = None
+all_allow_rules = None
+all_transitions = None
def get_installed_policy(root="/"):
@@ -168,10 +171,10 @@ def info(setype, name=None):
q.name = name
return ({
- 'aliases': map(str, x.aliases()),
+ 'aliases': list(map(str, x.aliases())),
'name': str(x),
'permissive': bool(x.ispermissive),
- 'attributes': map(str, x.attributes())
+ 'attributes': list(map(str, x.attributes()))
} for x in q.results())
elif setype == ROLE:
@@ -181,8 +184,8 @@ def info(setype, name=None):
return ({
'name': str(x),
- 'roles': map(str, x.expand()),
- 'types': map(str, x.types()),
+ 'roles': list(map(str, x.expand())),
+ 'types': list(map(str, x.types())),
} for x in q.results())
elif setype == ATTRIBUTE:
@@ -192,7 +195,7 @@ def info(setype, name=None):
return ({
'name': str(x),
- 'types': map(str, x.expand()),
+ 'types': list(map(str, x.expand())),
} for x in q.results())
elif setype == PORT:
@@ -220,7 +223,7 @@ def info(setype, name=None):
return ({
'range': str(x.mls_range),
'name': str(x),
- 'roles': map(str, x.roles),
+ 'roles': list(map(str, x.roles)),
'level': str(x.mls_level),
} for x in q.results())
@@ -362,17 +365,26 @@ def search(types, seinfo=None):
def get_conditionals(src, dest, tclass, perm):
tdict = {}
tlist = []
- if dest.endswith("_t"):
- allows = search([ALLOW], {SOURCE: src, TARGET: dest, CLASS: tclass, PERMS: perm})
- else:
- # to include attribute
- allows = search([ALLOW], {SOURCE: src, CLASS: tclass, PERMS: perm})
- for i in allows:
- if i['target'] == dest:
- allows = []
- allows.append(i)
+ src_list = [src]
+ dest_list = [dest]
+ # add assigned attributes
+ try:
+ src_list += list(filter(lambda x: x['name'] == src, get_all_types_info()))[0]['attributes']
+ except:
+ pass
try:
- for i in map(lambda y: (y), filter(lambda x: set(perm).issubset(x[PERMS]) and x['boolean'], allows)):
+ dest_list += list(filter(lambda x: x['name'] == dest, get_all_types_info()))[0]['attributes']
+ except:
+ pass
+ allows = map(lambda y: y, filter(lambda x:
+ x['source'] in src_list and
+ x['target'] in dest_list and
+ set(perm).issubset(x[PERMS]) and
+ 'boolean' in x,
+ get_all_allow_rules()))
+
+ try:
+ for i in allows:
tdict.update({'source': i['source'], 'boolean': i['boolean']})
if tdict not in tlist:
tlist.append(tdict)
@@ -734,6 +746,11 @@ def get_all_types():
all_types = [x['name'] for x in info(TYPE)]
return all_types
+def get_all_types_info():
+ global all_types_info
+ if all_types_info is None:
+ all_types_info = list(info(TYPE))
+ return all_types_info
def get_user_types():
global user_types
@@ -1018,12 +1035,23 @@ def gen_short_name(setype):
short_name = domainname + "_"
return (domainname, short_name)
+def get_all_allow_rules():
+ global all_allow_rules
+ if not all_allow_rules:
+ all_allow_rules = search([ALLOW])
+ return all_allow_rules
+
+def get_all_transitions():
+ global all_transitions
+ if not all_transitions:
+ all_transitions = list(search([TRANSITION]))
+ return all_transitions
def get_bools(setype):
bools = []
domainbools = []
domainname, short_name = gen_short_name(setype)
- for i in map(lambda x: x['boolean'], filter(lambda x: 'boolean' in x, search([ALLOW], {'source': setype}))):
+ for i in map(lambda x: x['boolean'], filter(lambda x: 'boolean' in x and x['source'] == setype, get_all_allow_rules())):
for b in i:
if not isinstance(b, tuple):
continue
@@ -938,7 +938,11 @@ selinux(8), %s(8), semanage(8), restorecon(8), chcon(1), sepolicy(8)
return True
def _entrypoints(self):
- entrypoints = [x['target'] for x in sepolicy.search([sepolicy.ALLOW], {'source': self.type, 'permlist': ['entrypoint'], 'class': 'file'})]
+ entrypoints = [x['target'] for x in filter(lambda y:
+ y['source'] == self.type and y['class'] == 'file' and 'entrypoint' in y['permlist'],
+ sepolicy.get_all_allow_rules()
+ )]
+
if len(entrypoints) == 0:
return
@@ -980,15 +984,23 @@ For example one process might be launched with %(type)s_t:s0:c1,c2, and another
""" % {'type': self.domainname})
def _writes(self):
- permlist = sepolicy.search([sepolicy.ALLOW], {'source': self.type, 'permlist': ['open', 'write'], 'class': 'file'})
+ # add assigned attributes
+ src_list = [self.type]
+ try:
+ src_list += list(filter(lambda x: x['name'] == self.type, sepolicy.get_all_types_info()))[0]['attributes']
+ except:
+ pass
+
+ permlist = list(filter(lambda x:
+ x['source'] in src_list and
+ set(['open', 'write']).issubset(x['permlist']) and
+ x['class'] == 'file',
+ sepolicy.get_all_allow_rules()))
if permlist is None or len(permlist) == 0:
return
all_writes = []
attributes = ["proc_type", "sysctl_type"]
- for i in permlist:
- if not i['target'].endswith("_t"):
- attributes.append(i['target'])
for i in permlist:
if self._valid_write(i['target'], attributes):
@@ -1187,7 +1199,12 @@ The SELinux user %s_u is able to connect to the following tcp ports.
""" % ",".join(ports))
def _home_exec(self):
- permlist = sepolicy.search([sepolicy.ALLOW], {'source': self.type, 'target': 'user_home_type', 'class': 'file', 'permlist': ['ioctl', 'read', 'getattr', 'execute', 'execute_no_trans', 'open']})
+ permlist = list(filter(lambda x:
+ x['source'] == self.type and
+ x['target'] == 'user_home_type' and
+ x['class'] == 'file' and
+ set(['ioctl', 'read', 'getattr', 'execute', 'execute_no_trans', 'open']).issubset(set(x['permlist'])),
+ sepolicy.get_all_allow_rules()))
self.fd.write("""
.SH HOME_EXEC
""")
@@ -30,7 +30,9 @@ def _entrypoint(src):
def _get_trans(src):
- return sepolicy.search([sepolicy.TRANSITION], {sepolicy.SOURCE: src, sepolicy.CLASS: "process"})
+ src_list = [src] + list(filter(lambda x: x['name'] == src, sepolicy.get_all_types_info()))[0]['attributes']
+ trans_list = list(filter(lambda x: x['source'] in src_list and x['class'] == 'process', sepolicy.get_all_transitions()))
+ return trans_list
class setrans:
@@ -53,8 +55,8 @@ class setrans:
if not self.dest:
self.sdict[source]["map"] = trans
else:
- self.sdict[source]["map"] = map(lambda y: y, filter(lambda x: x["transtype"] == self.dest, trans))
- self.sdict[source]["child"] = map(lambda y: y["transtype"], filter(lambda x: x["transtype"] not in [self.dest, source], trans))
+ self.sdict[source]["map"] = list(map(lambda y: y, filter(lambda x: x["transtype"] == self.dest, trans)))
+ self.sdict[source]["child"] = list(map(lambda y: y["transtype"], filter(lambda x: x["transtype"] not in [self.dest, source], trans)))
for s in self.sdict[source]["child"]:
self._process(s)
SETools4 and Python 3 versions of map() and filter() uses iterators to generates query results and these iterators can't be imply re-used. It makes manpage and transitions operations really slow as they do lot of queries. This patch changes it in the way that it caches results in lists for all types, allow rules and transitions first and use cached results to filter them using Python's filter() function. Before: $ time sepolicy manpage -d httpd_t sshd_t init_t real 0m53.486s user 0m53.171s sys 0m0.054s After: $ time sepolicy manpage -d httpd_t sshd_t init_t real 0m10.532s user 0m10.368s sys 0m0.114s Signed-off-by: Petr Lautrbach <plautrba@redhat.com> --- python/sepolicy/sepolicy/__init__.py | 62 ++++++++++++++++++++++++---------- python/sepolicy/sepolicy/manpage.py | 29 ++++++++++++---- python/sepolicy/sepolicy/transition.py | 8 +++-- 3 files changed, 73 insertions(+), 26 deletions(-)