sepolicy: Make manpage and transition faster
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>
This commit is contained in:
parent
c624c4abaa
commit
960b943b2f
3 changed files with 73 additions and 26 deletions
|
@ -99,6 +99,7 @@ local_files = None
|
||||||
fcdict = None
|
fcdict = None
|
||||||
methods = []
|
methods = []
|
||||||
all_types = None
|
all_types = None
|
||||||
|
all_types_info = None
|
||||||
user_types = None
|
user_types = None
|
||||||
role_allows = None
|
role_allows = None
|
||||||
portrecs = None
|
portrecs = None
|
||||||
|
@ -113,6 +114,8 @@ bools = None
|
||||||
all_attributes = None
|
all_attributes = None
|
||||||
booleans = None
|
booleans = None
|
||||||
booleans_dict = None
|
booleans_dict = None
|
||||||
|
all_allow_rules = None
|
||||||
|
all_transitions = None
|
||||||
|
|
||||||
|
|
||||||
def get_installed_policy(root="/"):
|
def get_installed_policy(root="/"):
|
||||||
|
@ -168,10 +171,10 @@ def info(setype, name=None):
|
||||||
q.name = name
|
q.name = name
|
||||||
|
|
||||||
return ({
|
return ({
|
||||||
'aliases': map(str, x.aliases()),
|
'aliases': list(map(str, x.aliases())),
|
||||||
'name': str(x),
|
'name': str(x),
|
||||||
'permissive': bool(x.ispermissive),
|
'permissive': bool(x.ispermissive),
|
||||||
'attributes': map(str, x.attributes())
|
'attributes': list(map(str, x.attributes()))
|
||||||
} for x in q.results())
|
} for x in q.results())
|
||||||
|
|
||||||
elif setype == ROLE:
|
elif setype == ROLE:
|
||||||
|
@ -181,8 +184,8 @@ def info(setype, name=None):
|
||||||
|
|
||||||
return ({
|
return ({
|
||||||
'name': str(x),
|
'name': str(x),
|
||||||
'roles': map(str, x.expand()),
|
'roles': list(map(str, x.expand())),
|
||||||
'types': map(str, x.types()),
|
'types': list(map(str, x.types())),
|
||||||
} for x in q.results())
|
} for x in q.results())
|
||||||
|
|
||||||
elif setype == ATTRIBUTE:
|
elif setype == ATTRIBUTE:
|
||||||
|
@ -192,7 +195,7 @@ def info(setype, name=None):
|
||||||
|
|
||||||
return ({
|
return ({
|
||||||
'name': str(x),
|
'name': str(x),
|
||||||
'types': map(str, x.expand()),
|
'types': list(map(str, x.expand())),
|
||||||
} for x in q.results())
|
} for x in q.results())
|
||||||
|
|
||||||
elif setype == PORT:
|
elif setype == PORT:
|
||||||
|
@ -220,7 +223,7 @@ def info(setype, name=None):
|
||||||
return ({
|
return ({
|
||||||
'range': str(x.mls_range),
|
'range': str(x.mls_range),
|
||||||
'name': str(x),
|
'name': str(x),
|
||||||
'roles': map(str, x.roles),
|
'roles': list(map(str, x.roles)),
|
||||||
'level': str(x.mls_level),
|
'level': str(x.mls_level),
|
||||||
} for x in q.results())
|
} for x in q.results())
|
||||||
|
|
||||||
|
@ -362,17 +365,26 @@ def search(types, seinfo=None):
|
||||||
def get_conditionals(src, dest, tclass, perm):
|
def get_conditionals(src, dest, tclass, perm):
|
||||||
tdict = {}
|
tdict = {}
|
||||||
tlist = []
|
tlist = []
|
||||||
if dest.endswith("_t"):
|
src_list = [src]
|
||||||
allows = search([ALLOW], {SOURCE: src, TARGET: dest, CLASS: tclass, PERMS: perm})
|
dest_list = [dest]
|
||||||
else:
|
# add assigned attributes
|
||||||
# to include attribute
|
|
||||||
allows = search([ALLOW], {SOURCE: src, CLASS: tclass, PERMS: perm})
|
|
||||||
for i in allows:
|
|
||||||
if i['target'] == dest:
|
|
||||||
allows = []
|
|
||||||
allows.append(i)
|
|
||||||
try:
|
try:
|
||||||
for i in map(lambda y: (y), filter(lambda x: set(perm).issubset(x[PERMS]) and x['boolean'], allows)):
|
src_list += list(filter(lambda x: x['name'] == src, get_all_types_info()))[0]['attributes']
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
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']})
|
tdict.update({'source': i['source'], 'boolean': i['boolean']})
|
||||||
if tdict not in tlist:
|
if tdict not in tlist:
|
||||||
tlist.append(tdict)
|
tlist.append(tdict)
|
||||||
|
@ -734,6 +746,11 @@ def get_all_types():
|
||||||
all_types = [x['name'] for x in info(TYPE)]
|
all_types = [x['name'] for x in info(TYPE)]
|
||||||
return all_types
|
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():
|
def get_user_types():
|
||||||
global user_types
|
global user_types
|
||||||
|
@ -1018,12 +1035,23 @@ def gen_short_name(setype):
|
||||||
short_name = domainname + "_"
|
short_name = domainname + "_"
|
||||||
return (domainname, short_name)
|
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):
|
def get_bools(setype):
|
||||||
bools = []
|
bools = []
|
||||||
domainbools = []
|
domainbools = []
|
||||||
domainname, short_name = gen_short_name(setype)
|
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:
|
for b in i:
|
||||||
if not isinstance(b, tuple):
|
if not isinstance(b, tuple):
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -938,7 +938,11 @@ selinux(8), %s(8), semanage(8), restorecon(8), chcon(1), sepolicy(8)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _entrypoints(self):
|
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:
|
if len(entrypoints) == 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -980,15 +984,23 @@ For example one process might be launched with %(type)s_t:s0:c1,c2, and another
|
||||||
""" % {'type': self.domainname})
|
""" % {'type': self.domainname})
|
||||||
|
|
||||||
def _writes(self):
|
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:
|
if permlist is None or len(permlist) == 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
all_writes = []
|
all_writes = []
|
||||||
attributes = ["proc_type", "sysctl_type"]
|
attributes = ["proc_type", "sysctl_type"]
|
||||||
for i in permlist:
|
|
||||||
if not i['target'].endswith("_t"):
|
|
||||||
attributes.append(i['target'])
|
|
||||||
|
|
||||||
for i in permlist:
|
for i in permlist:
|
||||||
if self._valid_write(i['target'], attributes):
|
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))
|
""" % ",".join(ports))
|
||||||
|
|
||||||
def _home_exec(self):
|
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("""
|
self.fd.write("""
|
||||||
.SH HOME_EXEC
|
.SH HOME_EXEC
|
||||||
""")
|
""")
|
||||||
|
|
|
@ -30,7 +30,9 @@ def _entrypoint(src):
|
||||||
|
|
||||||
|
|
||||||
def _get_trans(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:
|
class setrans:
|
||||||
|
@ -53,8 +55,8 @@ class setrans:
|
||||||
if not self.dest:
|
if not self.dest:
|
||||||
self.sdict[source]["map"] = trans
|
self.sdict[source]["map"] = trans
|
||||||
else:
|
else:
|
||||||
self.sdict[source]["map"] = map(lambda y: y, filter(lambda x: x["transtype"] == self.dest, trans))
|
self.sdict[source]["map"] = list(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]["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"]:
|
for s in self.sdict[source]["child"]:
|
||||||
self._process(s)
|
self._process(s)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue