# Copyright 2014, 2016, Tresys Technology, LLC # # This file is part of SETools. # # SETools is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as # published by the Free Software Foundation, either version 2.1 of # the License, or (at your option) any later version. # # SETools is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with SETools. If not, see # <http://www.gnu.org/licenses/>. # import stat from . import exception from . import qpol from . import symbol from . import context def validate_ruletype(t): """Validate fs_use_* rule types.""" if t not in ["fs_use_xattr", "fs_use_trans", "fs_use_task"]: raise exception.InvalidFSUseType("{0} is not a valid fs_use_* type.".format(t)) return t def fs_use_factory(policy, name): """Factory function for creating fs_use_* objects.""" if not isinstance(name, qpol.qpol_fs_use_t): raise TypeError("fs_use_* cannot be looked-up.") return FSUse(policy, name) def genfscon_factory(policy, name): """Factory function for creating genfscon objects.""" if not isinstance(name, qpol.qpol_genfscon_t): raise TypeError("Genfscons cannot be looked-up.") return Genfscon(policy, name) class FSContext(symbol.PolicySymbol): """Base class for in-policy labeling rules.""" def __str__(self): raise NotImplementedError @property def fs(self): """The filesystem type for this statement.""" return self.qpol_symbol.name(self.policy) @property def context(self): """The context for this statement.""" return context.context_factory(self.policy, self.qpol_symbol.context(self.policy)) def statement(self): return str(self) class GenfsFiletype(int): """ A genfscon file type. The possible values are equivalent to file type values in the stat module, e.g. S_IFBLK, but overrides the string representation with the corresponding genfscon file type string (-b, -c, etc.) If the genfscon has no specific file type, this is 0, (empty string). """ _filetype_to_text = { 0: "", stat.S_IFBLK: "-b", stat.S_IFCHR: "-c", stat.S_IFDIR: "-d", stat.S_IFIFO: "-p", stat.S_IFREG: "--", stat.S_IFLNK: "-l", stat.S_IFSOCK: "-s"} def __str__(self): return self._filetype_to_text[self] class Genfscon(FSContext): """A genfscon statement.""" def __str__(self): return "genfscon {0.fs} {0.path} {0.filetype} {0.context}".format(self) def __hash__(self): return hash("genfscon|{0.fs}|{0.path}|{0.filetype}".format(self)) def __eq__(self, other): # Libqpol allocates new C objects in the # genfscons iterator, so pointer comparison # in the PolicySymbol object doesn't work. try: return (self.fs == other.fs and self.path == other.path and self.filetype == other.filetype and self.context == other.context) except AttributeError: return str(self) == str(other) @property def filetype(self): """The file type (e.g. stat.S_IFBLK) for this genfscon statement.""" return GenfsFiletype(self.qpol_symbol.object_class(self.policy)) @property def path(self): """The path for this genfscon statement.""" return self.qpol_symbol.path(self.policy) class FSUse(FSContext): """A fs_use_* statement.""" # there are more rule types, but modern SELinux # only supports these three. _ruletype_to_text = { qpol.QPOL_FS_USE_XATTR: 'fs_use_xattr', qpol.QPOL_FS_USE_TRANS: 'fs_use_trans', qpol.QPOL_FS_USE_TASK: 'fs_use_task'} def __str__(self): return "{0.ruletype} {0.fs} {0.context};".format(self) def __hash__(self): return hash("{0.ruletype}|{0.fs}".format(self)) @property def ruletype(self): """The rule type for this fs_use_* statement.""" return self._ruletype_to_text[self.qpol_symbol.behavior(self.policy)]