1 # Copyright 2014, 2016, Tresys Technology, LLC 2 # 3 # This file is part of SETools. 4 # 5 # SETools is free software: you can redistribute it and/or modify 6 # it under the terms of the GNU Lesser General Public License as 7 # published by the Free Software Foundation, either version 2.1 of 8 # the License, or (at your option) any later version. 9 # 10 # SETools 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 Lesser General Public License for more details. 14 # 15 # You should have received a copy of the GNU Lesser General Public 16 # License along with SETools. If not, see 17 # <http://www.gnu.org/licenses/>. 18 # 19 import stat 20 21 from . import exception 22 from . import qpol 23 from . import symbol 24 from . import context 25 26 27 def validate_ruletype(t): 28 """Validate fs_use_* rule types.""" 29 if t not in ["fs_use_xattr", "fs_use_trans", "fs_use_task"]: 30 raise exception.InvalidFSUseType("{0} is not a valid fs_use_* type.".format(t)) 31 32 return t 33 34 35 def fs_use_factory(policy, name): 36 """Factory function for creating fs_use_* objects.""" 37 38 if not isinstance(name, qpol.qpol_fs_use_t): 39 raise TypeError("fs_use_* cannot be looked-up.") 40 41 return FSUse(policy, name) 42 43 44 def genfscon_factory(policy, name): 45 """Factory function for creating genfscon objects.""" 46 47 if not isinstance(name, qpol.qpol_genfscon_t): 48 raise TypeError("Genfscons cannot be looked-up.") 49 50 return Genfscon(policy, name) 51 52 53 class FSContext(symbol.PolicySymbol): 54 55 """Base class for in-policy labeling rules.""" 56 57 def __str__(self): 58 raise NotImplementedError 59 60 @property 61 def fs(self): 62 """The filesystem type for this statement.""" 63 return self.qpol_symbol.name(self.policy) 64 65 @property 66 def context(self): 67 """The context for this statement.""" 68 return context.context_factory(self.policy, self.qpol_symbol.context(self.policy)) 69 70 def statement(self): 71 return str(self) 72 73 74 class GenfsFiletype(int): 75 76 """ 77 A genfscon file type. 78 79 The possible values are equivalent to file type 80 values in the stat module, e.g. S_IFBLK, but 81 overrides the string representation with the 82 corresponding genfscon file type string 83 (-b, -c, etc.) If the genfscon has no specific 84 file type, this is 0, (empty string). 85 """ 86 87 _filetype_to_text = { 88 0: "", 89 stat.S_IFBLK: "-b", 90 stat.S_IFCHR: "-c", 91 stat.S_IFDIR: "-d", 92 stat.S_IFIFO: "-p", 93 stat.S_IFREG: "--", 94 stat.S_IFLNK: "-l", 95 stat.S_IFSOCK: "-s"} 96 97 def __str__(self): 98 return self._filetype_to_text[self] 99 100 101 class Genfscon(FSContext): 102 103 """A genfscon statement.""" 104 105 def __str__(self): 106 return "genfscon {0.fs} {0.path} {0.filetype} {0.context}".format(self) 107 108 def __hash__(self): 109 return hash("genfscon|{0.fs}|{0.path}|{0.filetype}".format(self)) 110 111 def __eq__(self, other): 112 # Libqpol allocates new C objects in the 113 # genfscons iterator, so pointer comparison 114 # in the PolicySymbol object doesn't work. 115 try: 116 return (self.fs == other.fs and 117 self.path == other.path and 118 self.filetype == other.filetype and 119 self.context == other.context) 120 except AttributeError: 121 return str(self) == str(other) 122 123 @property 124 def filetype(self): 125 """The file type (e.g. stat.S_IFBLK) for this genfscon statement.""" 126 return GenfsFiletype(self.qpol_symbol.object_class(self.policy)) 127 128 @property 129 def path(self): 130 """The path for this genfscon statement.""" 131 return self.qpol_symbol.path(self.policy) 132 133 134 class FSUse(FSContext): 135 136 """A fs_use_* statement.""" 137 138 # there are more rule types, but modern SELinux 139 # only supports these three. 140 _ruletype_to_text = { 141 qpol.QPOL_FS_USE_XATTR: 'fs_use_xattr', 142 qpol.QPOL_FS_USE_TRANS: 'fs_use_trans', 143 qpol.QPOL_FS_USE_TASK: 'fs_use_task'} 144 145 def __str__(self): 146 return "{0.ruletype} {0.fs} {0.context};".format(self) 147 148 def __hash__(self): 149 return hash("{0.ruletype}|{0.fs}".format(self)) 150 151 @property 152 def ruletype(self): 153 """The rule type for this fs_use_* statement.""" 154 return self._ruletype_to_text[self.qpol_symbol.behavior(self.policy)] 155