All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel J Walsh <dwalsh@redhat.com>
To: "'Chad Sellers'" <csellers@tresys.com>
Cc: Karl MacMillan <kmacmillan@tresys.com>, SELinux <selinux@tycho.nsa.gov>
Subject: Here is the current sepolgen patch from Fedora.
Date: Mon, 13 Dec 2010 13:36:03 -0500	[thread overview]
Message-ID: <4D066793.3060208@redhat.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 699 bytes --]

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

This patch incorporates to changes to make audit2allow rule generation
better.

First it adds audit2why functionality so that audit2allow can tell a
user when he is looking at the AVC messages a boolean exists to fix the
problem, or if the policy is fixed in the current release.

Secondly I added the open access and tried to change some of the weights
to make audit2allow -R work better.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/

iEYEARECAAYFAk0GZ5MACgkQrlYvE4MpobNB8wCgwqA7gzBO+qqDvjTboeWYTSz3
Z8cAn1SiNxTFJHuW0CsWI1krhgJQcIVG
=DWHT
-----END PGP SIGNATURE-----

[-- Attachment #2: libsepol-rhat.patch --]
[-- Type: text/plain, Size: 19197 bytes --]

diff --git a/sepolgen/src/sepolgen/access.py b/sepolgen/src/sepolgen/access.py
index 3eda2fd..649735f 100644
--- a/sepolgen/src/sepolgen/access.py
+++ b/sepolgen/src/sepolgen/access.py
@@ -32,6 +32,7 @@ in a variety of ways, but they are the fundamental representation of access.
 """
 
 import refpolicy
+from selinux import audit2why
 
 def is_idparam(id):
     """Determine if an id is a paramater in the form $N, where N is
@@ -85,6 +86,8 @@ class AccessVector:
             self.obj_class = None
             self.perms = refpolicy.IdSet()
             self.audit_msgs = []
+            self.type = audit2why.TERULE
+            self.bools = []
 
         # The direction of the information flow represented by this
         # access vector - used for matching
@@ -253,20 +256,22 @@ class AccessVectorSet:
         for av in l:
             self.add_av(AccessVector(av))
 
-    def add(self, src_type, tgt_type, obj_class, perms, audit_msg=None):
+    def add(self, src_type, tgt_type, obj_class, perms, audit_msg=None, avc_type=audit2why.TERULE, bools=[]):
         """Add an access vector to the set.
         """
         tgt = self.src.setdefault(src_type, { })
         cls = tgt.setdefault(tgt_type, { })
         
-        if cls.has_key(obj_class):
-            access = cls[obj_class]
+        if cls.has_key((obj_class, avc_type)):
+            access = cls[obj_class, avc_type]
         else:
             access = AccessVector()
             access.src_type = src_type
             access.tgt_type = tgt_type
             access.obj_class = obj_class
-            cls[obj_class] = access
+            access.bools = bools
+            access.type = avc_type
+            cls[obj_class, avc_type] = access
 
         access.perms.update(perms)
         if audit_msg:
diff --git a/sepolgen/src/sepolgen/audit.py b/sepolgen/src/sepolgen/audit.py
index 24e308e..e23725f 100644
--- a/sepolgen/src/sepolgen/audit.py
+++ b/sepolgen/src/sepolgen/audit.py
@@ -68,6 +68,17 @@ def get_dmesg_msgs():
                               stdout=subprocess.PIPE).communicate()[0]
     return output
 
+def get_log_msgs():
+    """Obtain all of the avc and policy load messages from /var/log/messages.
+
+    Returns:
+       string contain all of the audit messages returned by /var/log/messages.
+    """
+    import subprocess
+    output = subprocess.Popen(["/bin/grep", "avc",  "/var/log/messages"],
+                              stdout=subprocess.PIPE).communicate()[0]
+    return output
+
 # Classes representing audit messages
 
 class AuditMessage:
@@ -127,6 +138,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.
@@ -167,6 +181,8 @@ class AVCMessage(AuditMessage):
         self.path = ""
         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
@@ -226,7 +242,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):
@@ -469,10 +509,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:
diff --git a/sepolgen/src/sepolgen/defaults.py b/sepolgen/src/sepolgen/defaults.py
index 45ce61a..6d511c3 100644
--- a/sepolgen/src/sepolgen/defaults.py
+++ b/sepolgen/src/sepolgen/defaults.py
@@ -30,6 +30,9 @@ def perm_map():
 def interface_info():
     return data_dir() + "/interface_info"
 
+def attribute_info():
+    return data_dir() + "/attribute_info"
+
 def refpolicy_devel():
     return "/usr/share/selinux/devel"
 
diff --git a/sepolgen/src/sepolgen/interfaces.py b/sepolgen/src/sepolgen/interfaces.py
index d8b3e34..ae1c9c5 100644
--- a/sepolgen/src/sepolgen/interfaces.py
+++ b/sepolgen/src/sepolgen/interfaces.py
@@ -29,6 +29,8 @@ import matching
 
 from sepolgeni18n import _
 
+import copy
+
 class Param:
     """
     Object representing a paramater for an interface.
@@ -197,10 +199,48 @@ def ifcall_extract_params(ifcall, params):
                 ret = 1
 
     return ret
-            
+
+class AttributeVector:
+    def __init__(self):
+        self.name = ""
+        self.access = access.AccessVectorSet()
+
+    def add_av(self, av):
+        self.access.add_av(av)
+
+class AttributeSet:
+    def __init__(self):
+        self.attributes = { }
+
+    def add_attr(self, attr):
+        self.attributes[attr.name] = attr
+
+    def from_file(self, fd):
+        def parse_attr(line):
+            fields = line[1:-1].split()
+            if len(fields) != 2 or fields[0] != "Attribute":
+                raise SyntaxError("Syntax error Attribute statement %s" % line)
+            a = AttributeVector()
+            a.name = fields[1]
+
+            return a
+
+        a = None
+        for line in fd:
+            line = line[:-1]
+            if line[0] == "[":
+                if a:
+                    self.add_attr(a)
+                a = parse_attr(line)
+            elif a:
+                l = line.split(",")
+                av = access.AccessVector(l)
+                a.add_av(av)
+        if a:
+            self.add_attr(a)
 
 class InterfaceVector:
-    def __init__(self, interface=None):
+    def __init__(self, interface=None, attributes={}):
         # Enabled is a loose concept currently - we are essentially
         # not enabling interfaces that we can't handle currently.
         # See InterfaceVector.add_ifv for more information.
@@ -214,10 +254,10 @@ class InterfaceVector:
         # value: Param object).
         self.params = { }
         if interface:
-            self.from_interface(interface)
+            self.from_interface(interface, attributes)
         self.expanded = False
 
-    def from_interface(self, interface):
+    def from_interface(self, interface, attributes={}):
         self.name = interface.name
 
         # Add allow rules
@@ -232,6 +272,23 @@ class InterfaceVector:
             for av in avs:
                 self.add_av(av)
 
+        # Add typeattribute access
+        if attributes != None:
+            for typeattribute in interface.typeattributes():
+                for attr in typeattribute.attributes:
+                    if not attributes.attributes.has_key(attr):
+                        # print "missing attribute " + attr
+                        continue
+                    attr_vec = attributes.attributes[attr]
+                    for a in attr_vec.access:
+                        av = copy.copy(a)
+                        if av.src_type == attr_vec.name:
+                            av.src_type = typeattribute.type
+                        if av.tgt_type == attr_vec.name:
+                            av.tgt_type = typeattribute.type
+                        self.add_av(av)
+
+
         # Extract paramaters from roles
         for role in interface.roles():
             if role_extract_params(role, self.params):
@@ -346,13 +403,13 @@ class InterfaceSet:
                 l = self.tgt_type_map.setdefault(type, [])
                 l.append(ifv)
 
-    def add(self, interface):
-        ifv = InterfaceVector(interface)
+    def add(self, interface, attributes={}):
+        ifv = InterfaceVector(interface, attributes)
         self.add_ifv(ifv)
 
-    def add_headers(self, headers, output=None):
+    def add_headers(self, headers, output=None, attributes={}):
         for i in itertools.chain(headers.interfaces(), headers.templates()):
-            self.add(i)
+            self.add(i, attributes)
 
         self.expand_ifcalls(headers)
         self.index()
diff --git a/sepolgen/src/sepolgen/matching.py b/sepolgen/src/sepolgen/matching.py
index 1a9a3e5..d56dd92 100644
--- a/sepolgen/src/sepolgen/matching.py
+++ b/sepolgen/src/sepolgen/matching.py
@@ -50,7 +50,7 @@ class Match:
                 return 1
 
 class MatchList:
-    DEFAULT_THRESHOLD = 120
+    DEFAULT_THRESHOLD = 150
     def __init__(self):
         # Match objects that pass the threshold
         self.children = []
@@ -63,14 +63,15 @@ class MatchList:
     def best(self):
         if len(self.children):
             return self.children[0]
-        else:
-            return None
+        if len(self.bastards):
+            return self.bastards[0]
+        return None
 
     def __len__(self):
         # Only return the length of the matches so
         # that this can be used to test if there is
         # a match.
-        return len(self.children)
+        return len(self.children) + len(self.bastards)
 
     def __iter__(self):
         return iter(self.children)
diff --git a/sepolgen/src/sepolgen/policygen.py b/sepolgen/src/sepolgen/policygen.py
index 0e6b502..6e1ebf0 100644
--- a/sepolgen/src/sepolgen/policygen.py
+++ b/sepolgen/src/sepolgen/policygen.py
@@ -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 += "#Contraint 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)
 
 
diff --git a/sepolgen/src/sepolgen/refparser.py b/sepolgen/src/sepolgen/refparser.py
index abcd508..243efad 100644
--- a/sepolgen/src/sepolgen/refparser.py
+++ b/sepolgen/src/sepolgen/refparser.py
@@ -1044,7 +1044,7 @@ def parse_headers(root, output=None, expand=True, debug=False):
         # of misc_macros. We are just going to pretend that this is an interface
         # to make the expansion work correctly.
         can_exec = refpolicy.Interface("can_exec")
-        av = access.AccessVector(["$1","$2","file","execute_no_trans","read",
+        av = access.AccessVector(["$1","$2","file","execute_no_trans","open", "read",
                                   "getattr","lock","execute","ioctl"])
 
         can_exec.children.append(refpolicy.AVRule(av))
diff --git a/sepolgen/src/share/perm_map b/sepolgen/src/share/perm_map
index eb2e23b..ca4fa4d 100644
--- a/sepolgen/src/share/perm_map
+++ b/sepolgen/src/share/perm_map
@@ -124,7 +124,7 @@ class filesystem 10
           quotamod     w           1
           quotaget     r           1
 
-class file 20
+class file 21
   execute_no_trans     r           1
         entrypoint     r           1
            execmod     n           1
@@ -141,48 +141,50 @@ class file 20
             unlink     w           1
               link     w           1
             rename     w           5
-           execute     r           100
+           execute     r           10
             swapon     b           1
            quotaon     b           1
            mounton     b           1
+	      open     r	   1
 
-class dir 22
-          add_name     w           5
+class dir 23
+          add_name     w           1
        remove_name     w           1
           reparent     w           1
             search     r           1
              rmdir     b           1
              ioctl     n           1
-              read     r          10
-             write     w          10
+              read     r           1
+             write     w           1
             create     w           1
-           getattr     r           7
-           setattr     w           7
+           getattr     r           1
+           setattr     w           1
               lock     n           1
-       relabelfrom     r           10
-         relabelto     w           10
+       relabelfrom     r           1
+         relabelto     w           1
             append     w           1
             unlink     w           1
               link     w           1
-            rename     w           5
+            rename     w           1
            execute     r           1
             swapon     b           1
            quotaon     b           1
            mounton     b           1
+	      open     r	   1
 
 class fd 1
                use     b           1
 
-class lnk_file 17
+class lnk_file 18
              ioctl     n           1
-              read     r          10
-             write     w          10
+              read     r           1
+             write     w           1
             create     w           1
-           getattr     r           7
-           setattr     w           7
+           getattr     r           1
+           setattr     w           1
               lock     n           1
-       relabelfrom     r           10
-         relabelto     w           10
+       relabelfrom     r           1
+         relabelto     w           1
             append     w           1
             unlink     w           1
               link     w           1
@@ -191,8 +193,9 @@ class lnk_file 17
             swapon     b           1
            quotaon     b           1
            mounton     b           1
+	      open     r	   1
 
-class chr_file 20
+class chr_file 21
   execute_no_trans     r           1
         entrypoint     r           1
            execmod     n           1
@@ -213,8 +216,9 @@ class chr_file 20
             swapon     b           1
            quotaon     b           1
            mounton     b           1
+	      open     r	   1
 
-class blk_file 17
+class blk_file 18
              ioctl     n           1
               read     r          10
              write     w          10
@@ -232,8 +236,9 @@ class blk_file 17
             swapon     b           1
            quotaon     b           1
            mounton     b           1
+	      open     r	   1
 
-class sock_file 17
+class sock_file 18
              ioctl     n           1
               read     r          10
              write     w          10
@@ -251,8 +256,9 @@ class sock_file 17
             swapon     b           1
            quotaon     b           1
            mounton     b           1
+	      open     r	   1
 
-class fifo_file 17
+class fifo_file 18
              ioctl     n           1
               read     r          10
              write     w          10
@@ -270,6 +276,7 @@ class fifo_file 17
             swapon     b           1
            quotaon     b           1
            mounton     b           1
+	      open     r	   1
 
 class socket 22
              ioctl     n           1

[-- Attachment #3: libsepol-rhat.patch.sig --]
[-- Type: application/pgp-signature, Size: 72 bytes --]

                 reply	other threads:[~2010-12-13 18:36 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4D066793.3060208@redhat.com \
    --to=dwalsh@redhat.com \
    --cc=csellers@tresys.com \
    --cc=kmacmillan@tresys.com \
    --cc=selinux@tycho.nsa.gov \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.