1 # Authors: Karl MacMillan <kmacmillan (at] mentalrootkit.com> 2 # 3 # Copyright (C) 2006 Red Hat 4 # see file 'COPYING' for use and warranty information 5 # 6 # This program is free software; you can redistribute it and/or 7 # modify it under the terms of the GNU General Public License as 8 # published by the Free Software Foundation; version 2 only 9 # 10 # This program is distributed in the hope that it will be useful, 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 # GNU General Public License for more details. 14 # 15 # You should have received a copy of the GNU General Public License 16 # along with this program; if not, write to the Free Software 17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 # 19 20 """ 21 This module provides knowledge object classes and permissions. It should 22 be used to keep this knowledge from leaking into the more generic parts of 23 the policy generation. 24 """ 25 26 # Objects that can be implicitly typed - these objects do 27 # not _have_ to be implicitly typed (e.g., sockets can be 28 # explicitly labeled), but they often are. 29 # 30 # File is in this list for /proc/self 31 # 32 # This list is useful when dealing with rules that have a 33 # type (or param) used as both a subject and object. For 34 # example: 35 # 36 # allow httpd_t httpd_t : socket read; 37 # 38 # This rule makes sense because the socket was (presumably) created 39 # by a process with the type httpd_t. 40 implicitly_typed_objects = ["socket", "fd", "process", "file", "lnk_file", "fifo_file", 41 "dbus", "capability", "unix_stream_socket"] 42 43 #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 44 # 45 #Information Flow 46 # 47 # All of the permissions in SELinux can be described in terms of 48 # information flow. For example, a read of a file is a flow of 49 # information from that file to the process reading. Viewing 50 # permissions in these terms can be used to model a varity of 51 # security properties. 52 # 53 # Here we have some infrastructure for understanding permissions 54 # in terms of information flow 55 # 56 #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 57 58 # Information flow deals with information either flowing from a subject 59 # to and object ("write") or to a subject from an object ("read"). Read 60 # or write is described from the subject point-of-view. It is also possible 61 # for a permission to represent both a read and write (though the flow is 62 # typical asymettric in terms of bandwidth). It is also possible for 63 # permission to not flow information (meaning that the result is pure 64 # side-effect). 65 # 66 # The following constants are for representing the directionality 67 # of information flow. 68 FLOW_NONE = 0 69 FLOW_READ = 1 70 FLOW_WRITE = 2 71 FLOW_BOTH = FLOW_READ | FLOW_WRITE 72 73 # These are used by the parser and for nice disply of the directions 74 str_to_dir = { "n" : FLOW_NONE, "r" : FLOW_READ, "w" : FLOW_WRITE, "b" : FLOW_BOTH } 75 dir_to_str = { FLOW_NONE : "n", FLOW_READ : "r", FLOW_WRITE : "w", FLOW_BOTH : "b" } 76 77 class PermMap: 78 """A mapping between a permission and its information flow properties. 79 80 PermMap represents the information flow properties of a single permission 81 including the direction (read, write, etc.) and an abstract representation 82 of the bandwidth of the flow (weight). 83 """ 84 def __init__(self, perm, dir, weight): 85 self.perm = perm 86 self.dir = dir 87 self.weight = weight 88 89 def __repr__(self): 90 return "<sepolgen.objectmodel.PermMap %s %s %d>" % (self.perm, 91 dir_to_str[self.dir], 92 self.weight) 93 94 class PermMappings: 95 """The information flow properties of a set of object classes and permissions. 96 97 PermMappings maps one or more classes and permissions to their PermMap objects 98 describing their information flow charecteristics. 99 """ 100 def __init__(self): 101 self.classes = { } 102 self.default_weight = 5 103 self.default_dir = FLOW_BOTH 104 105 def from_file(self, fd): 106 """Read the permission mappings from a file. This reads the format used 107 by Apol in the setools suite. 108 """ 109 # This parsing is deliberitely picky and bails at the least error. It 110 # is assumed that the permission map file will be shipped as part 111 # of sepolgen and not user modified, so this is a reasonable design 112 # choice. If user supplied permission mappings are needed the parser 113 # should be made a little more robust and give better error messages. 114 cur = None 115 for line in fd: 116 fields = line.split() 117 if len(fields) == 0 or len(fields) == 1 or fields[0] == "#": 118 continue 119 if fields[0] == "class": 120 c = fields[1] 121 if c in self.classes: 122 raise ValueError("duplicate class in perm map") 123 self.classes[c] = { } 124 cur = self.classes[c] 125 else: 126 if len(fields) != 3: 127 raise ValueError("error in object classs permissions") 128 if cur is None: 129 raise ValueError("permission outside of class") 130 pm = PermMap(fields[0], str_to_dir[fields[1]], int(fields[2])) 131 cur[pm.perm] = pm 132 133 def get(self, obj, perm): 134 """Get the permission map for the object permission. 135 136 Returns: 137 PermMap representing the permission 138 Raises: 139 KeyError if the object or permission is not defined 140 """ 141 return self.classes[obj][perm] 142 143 def getdefault(self, obj, perm): 144 """Get the permission map for the object permission or a default. 145 146 getdefault is the same as get except that a default PermMap is 147 returned if the object class or permission is not defined. The 148 default is FLOW_BOTH with a weight of 5. 149 """ 150 try: 151 pm = self.classes[obj][perm] 152 except KeyError: 153 return PermMap(perm, self.default_dir, self.default_weight) 154 return pm 155 156 def getdefault_direction(self, obj, perms): 157 dir = FLOW_NONE 158 for perm in perms: 159 pm = self.getdefault(obj, perm) 160 dir = dir | pm.dir 161 return dir 162 163 def getdefault_distance(self, obj, perms): 164 total = 0 165 for perm in perms: 166 pm = self.getdefault(obj, perm) 167 total += pm.weight 168 169 return total 170 171 172 173