- Improvements to audit2allow from rhallise@redhat.com

* Check for mislabeled files.
    * Check for base file use and
    * Suggest writable files as alternatives
This commit is contained in:
Miroslav Grepl 2014-09-23 15:25:06 +02:00
parent 9c335fab20
commit 2a1e3be828
2 changed files with 243 additions and 1 deletions

View File

@ -0,0 +1,235 @@
diff --git a/sepolgen/src/sepolgen/access.py b/sepolgen/src/sepolgen/access.py
index cf13210..9154887 100644
--- a/sepolgen/src/sepolgen/access.py
+++ b/sepolgen/src/sepolgen/access.py
@@ -88,6 +88,8 @@ class AccessVector:
self.audit_msgs = []
self.type = audit2why.TERULE
self.data = []
+ self.obj_path = None
+ self.base_type = None
# The direction of the information flow represented by this
# access vector - used for matching
@@ -133,6 +135,11 @@ class AccessVector:
return "allow %s %s:%s %s;" % (self.src_type, self.tgt_type,
self.obj_class, self.perms.to_space_str())
+ def base_file_type(self):
+ base_type_array = []
+ base_type_array = [self.base_type, self.tgt_type, self.src_type]
+ return base_type_array
+
def __cmp__(self, other):
if self.src_type != other.src_type:
return cmp(self.src_type, other.src_type)
@@ -256,7 +263,8 @@ class AccessVectorSet:
for av in l:
self.add_av(AccessVector(av))
- def add(self, src_type, tgt_type, obj_class, perms, audit_msg=None, avc_type=audit2why.TERULE, data=[]):
+ def add(self, src_type, tgt_type, obj_class, perms, obj_path=None,
+ base_type=None, audit_msg=None, avc_type=audit2why.TERULE, data=[]):
"""Add an access vector to the set.
"""
tgt = self.src.setdefault(src_type, { })
@@ -269,7 +277,9 @@ class AccessVectorSet:
access.src_type = src_type
access.tgt_type = tgt_type
access.obj_class = obj_class
+ access.obj_path = obj_path
access.data = data
+ access.base_type = base_type
access.type = avc_type
cls[obj_class, avc_type] = access
diff --git a/sepolgen/src/sepolgen/audit.py b/sepolgen/src/sepolgen/audit.py
index 56919be..57263d0 100644
--- a/sepolgen/src/sepolgen/audit.py
+++ b/sepolgen/src/sepolgen/audit.py
@@ -169,6 +169,7 @@ class AVCMessage(AuditMessage):
self.exe = ""
self.path = ""
self.name = ""
+ self.ino = ""
self.accesses = []
self.denial = True
self.type = audit2why.TERULE
@@ -230,6 +231,10 @@ class AVCMessage(AuditMessage):
self.exe = fields[1][1:-1]
elif fields[0] == "name":
self.name = fields[1][1:-1]
+ elif fields[0] == "path":
+ self.path = fields[1][1:-1]
+ elif fields[0] == "ino":
+ self.ino = fields[1]
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)
@@ -354,7 +359,9 @@ class AuditParser:
self.path_msgs = []
self.by_header = { }
self.check_input_file = False
-
+ self.inode_dict = { }
+ self.__store_base_types()
+
# Low-level parsing function - tries to determine if this audit
# message is an SELinux related message and then parses it into
# the appropriate AuditMessage subclass. This function deliberately
@@ -492,6 +499,60 @@ class AuditParser:
return role_types
+ def __restore_path(self, name, inode):
+ import subprocess
+ import os
+ path = ""
+ # Optimizing
+ if name == "" or inode == "":
+ return path
+ for d in self.inode_dict:
+ if d == inode and self.inode_dict[d] == name:
+ return path
+ if d == inode and self.inode_dict[d] != name:
+ return self.inode_dict[d]
+ if inode not in self.inode_dict.keys():
+ self.inode_dict[inode] = name
+
+ command = "locate -b '\%s'" % name
+ try:
+ output = subprocess.check_output(command,
+ stderr=subprocess.STDOUT,
+ shell=True)
+ try:
+ ino = int(inode)
+ except ValueError:
+ pass
+ for file in output.split("\n"):
+ try:
+ if int(os.lstat(file).st_ino) == ino:
+ self.inode_dict[inode] = path = file
+ return path
+ except:
+ pass
+ except subprocess.CalledProcessError as e:
+ pass
+ return path
+
+ def __store_base_types(self):
+ import sepolicy
+ self.base_types = sepolicy.get_types_from_attribute("base_file_type")
+
+ def __get_base_type(self, tcontext, scontext):
+ import sepolicy
+ # Prevent unnecessary searching
+ if (self.old_scontext == scontext and
+ self.old_tcontext == tcontext):
+ return
+ self.old_scontext = scontext
+ self.old_tcontext = tcontext
+ for btype in self.base_types:
+ if btype == tcontext:
+ for writable in sepolicy.get_writable_files(scontext):
+ if writable.endswith(tcontext) and writable.startswith(scontext.rstrip("_t")):
+ return writable
+ return 0
+
def to_access(self, avc_filter=None, only_denials=True):
"""Convert the audit logs access into a an access vector set.
@@ -510,16 +571,23 @@ class AuditParser:
audit logs parsed by this object.
"""
av_set = access.AccessVectorSet()
+ self.old_scontext = ""
+ self.old_tcontext = ""
for avc in self.avc_msgs:
if avc.denial != True and only_denials:
continue
+ base_type = self.__get_base_type(avc.tcontext.type, avc.scontext.type)
+ if avc.path == "":
+ avc.path = self.__restore_path(avc.name, avc.ino)
if avc_filter:
if avc_filter.filter(avc):
av_set.add(avc.scontext.type, avc.tcontext.type, avc.tclass,
- avc.accesses, avc, avc_type=avc.type, data=avc.data)
+ avc.accesses, avc.path, base_type, avc,
+ avc_type=avc.type, data=avc.data)
else:
av_set.add(avc.scontext.type, avc.tcontext.type, avc.tclass,
- avc.accesses, avc, avc_type=avc.type, data=avc.data)
+ avc.accesses, avc.path, base_type, avc,
+ avc_type=avc.type, data=avc.data)
return av_set
class AVCTypeFilter:
diff --git a/sepolgen/src/sepolgen/policygen.py b/sepolgen/src/sepolgen/policygen.py
index 5f38577..39b0ce1 100644
--- a/sepolgen/src/sepolgen/policygen.py
+++ b/sepolgen/src/sepolgen/policygen.py
@@ -81,8 +81,9 @@ class PolicyGenerator:
self.module = refpolicy.Module()
self.dontaudit = False
-
+ self.mislabled = None
self.domains = None
+
def set_gen_refpol(self, if_set=None, perm_maps=None):
"""Set whether reference policy interfaces are generated.
@@ -152,6 +153,18 @@ class PolicyGenerator:
"""Return the generated module"""
return self.module
+ def __restore_label(self, av):
+ import selinux
+ try:
+ context = selinux.matchpathcon(av.obj_path, 0)
+ split = context[1].split(":")[2]
+ if split != av.tgt_type:
+ self.mislabled = split
+ return
+ except OSError:
+ pass
+ self.mislabled = None
+
def __add_allow_rules(self, avs):
for av in avs:
rule = refpolicy.AVRule(av)
@@ -160,6 +173,34 @@ class PolicyGenerator:
rule.comment = ""
if self.explain:
rule.comment = str(refpolicy.Comment(explain_access(av, verbosity=self.explain)))
+ # base_type[0] == 0 means there exists a base type but not the path
+ # base_type[0] == None means user isn't using base type
+ # base_type[1] contains the target context
+ # base_type[2] contains the source type
+ base_type = av.base_file_type()
+ if base_type[0] == 0 and av.type != audit2why.ALLOW:
+ rule.comment += "\n#!!!! WARNING: '%s' is a base type." % "".join(base_type[1])
+ for perm in av.perms:
+ if perm == "write" or perm == "create":
+ permission = True
+ break
+ else:
+ permission = False
+
+ # Catch perms 'write' and 'create' for base types
+ if (base_type[0] is not None and base_type[0] != 0
+ and permission and av.type != audit2why.ALLOW):
+ if av.obj_class == dir:
+ comp = "(/.*?)"
+ else:
+ comp = ""
+ rule.comment += "\n#!!!! WARNING '%s' is not allowed to write or create to %s. Change the label to %s." % ("".join(base_type[2]), "".join(base_type[1]), "".join(base_type[0]))
+ if av.obj_path != "":
+ rule.comment += "\n#!!!! $ semange fcontext -a -t %s %s%s \n#!!!! $ restorecon -R -v %s" % ("".join(base_type[0]), "".join(av.obj_path), "".join(comp) ,"".join(av.obj_path))
+
+ self.__restore_label(av)
+ if self.mislabled is not None and av.type != audit2why.ALLOW:
+ rule.comment += "\n#!!!! The file '%s' is mislabeled on your system. \n#!!!! Fix with $ restorecon -R -v %s" % ("".join(av.obj_path), "".join(av.obj_path))
if av.type == audit2why.ALLOW:
rule.comment += "\n#!!!! This avc is allowed in the current policy"
if av.type == audit2why.DONTAUDIT:

View File

@ -7,7 +7,7 @@
Summary: SELinux policy core utilities
Name: policycoreutils
Version: 2.3
Release: 10%{?dist}
Release: 11%{?dist}
License: GPLv2
Group: System Environment/Base
# Based on git repository with tag 20101221
@ -19,6 +19,7 @@ Source3: system-config-selinux.png
Source4: sepolicy-icons.tgz
Patch: policycoreutils-rhat.patch
Patch1: 0001-Fix-setfiles-to-work-correctly-if-r-option-is-define.patch
Patch2: 0002-audit2allow-improvements.patch
Obsoletes: policycoreutils < 2.0.61-2
Conflicts: filesystem < 3
Provides: /sbin/fixfiles
@ -383,6 +384,12 @@ The policycoreutils-restorecond package contains the restorecond service.
%systemd_postun_with_restart restorecond.service
%changelog
* Tue Sep 23 2014 Miroslav Grepl <mgrepl@redhat.com> - 2.3-11
- Improvements to audit2allow from rhallise@redhat.com
* Check for mislabeled files.
* Check for base file use and
* Suggest writable files as alternatives
* Sun Aug 17 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.3-10
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild