sepolgen: better analysis of why things broke
combine analysys of audit2why into audit2allow, so users can see if a boolean would solve an AVC or if it is a constrain violation. Rather then blindly adding allow rules to modules. Signed-off-by: Eric Paris <eparis@redhat.com> Acked-by: Dan Walsh <dwalsh@redhat.com>
This commit is contained in:
parent
d65c02f066
commit
5c3211bcca
2 changed files with 69 additions and 4 deletions
|
@ -127,6 +127,9 @@ class PathMessage(AuditMessage):
|
|||
if fields[0] == "path":
|
||||
self.path = fields[1][1:-1]
|
||||
return
|
||||
import selinux.audit2why as audit2why
|
||||
|
||||
avcdict = {}
|
||||
|
||||
class AVCMessage(AuditMessage):
|
||||
"""AVC message representing an access denial or granted message.
|
||||
|
@ -168,6 +171,8 @@ class AVCMessage(AuditMessage):
|
|||
self.name = ""
|
||||
self.accesses = []
|
||||
self.denial = True
|
||||
self.type = audit2why.TERULE
|
||||
self.bools = []
|
||||
|
||||
def __parse_access(self, recs, start):
|
||||
# This is kind of sucky - the access that is in a space separated
|
||||
|
@ -229,7 +234,31 @@ class AVCMessage(AuditMessage):
|
|||
|
||||
if not found_src or not found_tgt or not found_class or not found_access:
|
||||
raise ValueError("AVC message in invalid format [%s]\n" % self.message)
|
||||
|
||||
self.analyze()
|
||||
|
||||
def analyze(self):
|
||||
tcontext = self.tcontext.to_string()
|
||||
scontext = self.scontext.to_string()
|
||||
access_tuple = tuple( self.accesses)
|
||||
if (scontext, tcontext, self.tclass, access_tuple) in avcdict.keys():
|
||||
self.type, self.bools = avcdict[(scontext, tcontext, self.tclass, access_tuple)]
|
||||
else:
|
||||
self.type, self.bools = audit2why.analyze(scontext, tcontext, self.tclass, self.accesses);
|
||||
if self.type == audit2why.NOPOLICY:
|
||||
self.type = audit2why.TERULE
|
||||
if self.type == audit2why.BADTCON:
|
||||
raise ValueError("Invalid Target Context %s\n" % tcontext)
|
||||
if self.type == audit2why.BADSCON:
|
||||
raise ValueError("Invalid Source Context %s\n" % scontext)
|
||||
if self.type == audit2why.BADSCON:
|
||||
raise ValueError("Invalid Type Class %s\n" % self.tclass)
|
||||
if self.type == audit2why.BADPERM:
|
||||
raise ValueError("Invalid permission %s\n" % " ".join(self.accesses))
|
||||
if self.type == audit2why.BADCOMPUTE:
|
||||
raise ValueError("Error during access vector computation")
|
||||
|
||||
avcdict[(scontext, tcontext, self.tclass, access_tuple)] = (self.type, self.bools)
|
||||
|
||||
class PolicyLoadMessage(AuditMessage):
|
||||
"""Audit message indicating that the policy was reloaded."""
|
||||
def __init__(self, message):
|
||||
|
@ -472,10 +501,10 @@ class AuditParser:
|
|||
if avc_filter:
|
||||
if avc_filter.filter(avc):
|
||||
av_set.add(avc.scontext.type, avc.tcontext.type, avc.tclass,
|
||||
avc.accesses, avc)
|
||||
avc.accesses, avc, avc_type=avc.type, bools=avc.bools)
|
||||
else:
|
||||
av_set.add(avc.scontext.type, avc.tcontext.type, avc.tclass,
|
||||
avc.accesses, avc)
|
||||
avc.accesses, avc, avc_type=avc.type, bools=avc.bools)
|
||||
return av_set
|
||||
|
||||
class AVCTypeFilter:
|
||||
|
|
|
@ -29,6 +29,8 @@ import objectmodel
|
|||
import access
|
||||
import interfaces
|
||||
import matching
|
||||
import selinux.audit2why as audit2why
|
||||
from setools import *
|
||||
|
||||
# Constants for the level of explanation from the generation
|
||||
# routines
|
||||
|
@ -77,6 +79,7 @@ class PolicyGenerator:
|
|||
|
||||
self.dontaudit = False
|
||||
|
||||
self.domains = None
|
||||
def set_gen_refpol(self, if_set=None, perm_maps=None):
|
||||
"""Set whether reference policy interfaces are generated.
|
||||
|
||||
|
@ -151,8 +154,41 @@ class PolicyGenerator:
|
|||
rule = refpolicy.AVRule(av)
|
||||
if self.dontaudit:
|
||||
rule.rule_type = rule.DONTAUDIT
|
||||
rule.comment = ""
|
||||
if self.explain:
|
||||
rule.comment = refpolicy.Comment(explain_access(av, verbosity=self.explain))
|
||||
rule.comment = str(refpolicy.Comment(explain_access(av, verbosity=self.explain)))
|
||||
if av.type == audit2why.ALLOW:
|
||||
rule.comment += "#!!!! This avc is allowed in the current policy\n"
|
||||
if av.type == audit2why.DONTAUDIT:
|
||||
rule.comment += "#!!!! This avc has a dontaudit rule in the current policy\n"
|
||||
|
||||
if av.type == audit2why.BOOLEAN:
|
||||
if len(av.bools) > 1:
|
||||
rule.comment += "#!!!! This avc can be allowed using one of the these booleans:\n# %s\n" % ", ".join(map(lambda x: x[0], av.bools))
|
||||
else:
|
||||
rule.comment += "#!!!! This avc can be allowed using the boolean '%s'\n" % av.bools[0][0]
|
||||
|
||||
if av.type == audit2why.CONSTRAINT:
|
||||
rule.comment += "#!!!! This avc is a constraint violation. You will need to add an attribute to either the source or target type to make it work.\n"
|
||||
rule.comment += "#Constraint rule: "
|
||||
|
||||
if av.type == audit2why.TERULE:
|
||||
if "write" in av.perms:
|
||||
if "dir" in av.obj_class or "open" in av.perms:
|
||||
if not self.domains:
|
||||
self.domains = seinfo(ATTRIBUTE, name="domain")[0]["types"]
|
||||
types=[]
|
||||
|
||||
try:
|
||||
for i in map(lambda x: x[TCONTEXT], sesearch([ALLOW], {SCONTEXT: av.src_type, CLASS: av.obj_class, PERMS: av.perms})):
|
||||
if i not in self.domains:
|
||||
types.append(i)
|
||||
if len(types) == 1:
|
||||
rule.comment += "#!!!! The source type '%s' can write to a '%s' of the following type:\n# %s\n" % ( av.src_type, av.obj_class, ", ".join(types))
|
||||
elif len(types) >= 1:
|
||||
rule.comment += "#!!!! The source type '%s' can write to a '%s' of the following types:\n# %s\n" % ( av.src_type, av.obj_class, ", ".join(types))
|
||||
except:
|
||||
pass
|
||||
self.module.children.append(rule)
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue