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