Skip to content

Commit

Permalink
policyrep: add prefix/suffix matching to filename type transitions
Browse files Browse the repository at this point in the history
Currently, filename transitions are stored separately from other type
enforcement rules and only support exact name matching. However, in
practice, the names contain variable parts. This leads to many
duplicated rules in the policy that differ only in the part of the name,
or it is even impossible to cover all possible combinations.

This patch reflects changes in libsepol implemented in this patch [1].

The patch adds additional filename transition tables to policydb
structure for prefix and suffix rules and updates the functions that
access them.

[1]: https://lore.kernel.org/selinux/[email protected]/

Reviewed-by: Ondrej Mosnacek <[email protected]>
Signed-off-by: Juraj Marcin <[email protected]>
  • Loading branch information
JurajMarcin committed Dec 14, 2023
1 parent a3281e6 commit e5876ed
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 10 deletions.
6 changes: 6 additions & 0 deletions setools/policyrep.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,7 @@ class FSUseRuletype(PolicyEnum):
class FileNameTERule(BaseTERule):
default: Type = ...
filename: str = ...
match_type: FileNameTERuleMatchType = ...
perms: NoReturn = ...
ruletype: TERuletype = ...
source: TypeOrAttr = ...
Expand Down Expand Up @@ -490,6 +491,11 @@ class FileNameTERuleIterator(HashtabIterator):
def __reduce__(self) -> Any: ...
def __setstate__(self, state) -> Any: ...

class FileNameTERuleMatchType(PolicyEnum):
exact: int = ...
prefix: int = ...
suffix: int = ...

class GenfsFiletype(int):
_filetype_to_text: Any = ...
@classmethod
Expand Down
8 changes: 6 additions & 2 deletions setools/policyrep/selinuxpolicy.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,9 @@ cdef class SELinuxPolicy:
def terules(self):
"""Iterator over all type enforcement rules."""
yield from TERuleIterator.factory(self, &self.handle.p.te_avtab)
yield from FileNameTERuleIterator.factory(self, &self.handle.p.filename_trans)
yield from FileNameTERuleIterator.factory(self, &self.handle.p.filename_trans[sepol.FILENAME_TRANS_MATCH_EXACT], sepol.FILENAME_TRANS_MATCH_EXACT)
yield from FileNameTERuleIterator.factory(self, &self.handle.p.filename_trans[sepol.FILENAME_TRANS_MATCH_PREFIX], sepol.FILENAME_TRANS_MATCH_PREFIX)
yield from FileNameTERuleIterator.factory(self, &self.handle.p.filename_trans[sepol.FILENAME_TRANS_MATCH_SUFFIX], sepol.FILENAME_TRANS_MATCH_SUFFIX)

for c in self.conditionals():
yield from c.true_rules()
Expand Down Expand Up @@ -1064,7 +1066,9 @@ cdef class SELinuxPolicy:
if not self.terule_counts:
self.terule_counts = TERuleIterator.factory(self, &self.handle.p.te_avtab).ruletype_count()
self.terule_counts[TERuletype.type_transition.value] += \
len(FileNameTERuleIterator.factory(self, &self.handle.p.filename_trans))
len(FileNameTERuleIterator.factory(self, &self.handle.p.filename_trans[sepol.FILENAME_TRANS_MATCH_EXACT], sepol.FILENAME_TRANS_MATCH_EXACT)) + \
len(FileNameTERuleIterator.factory(self, &self.handle.p.filename_trans[sepol.FILENAME_TRANS_MATCH_PREFIX], sepol.FILENAME_TRANS_MATCH_PREFIX)) + \
len(FileNameTERuleIterator.factory(self, &self.handle.p.filename_trans[sepol.FILENAME_TRANS_MATCH_SUFFIX], sepol.FILENAME_TRANS_MATCH_SUFFIX))

for c in self.conditionals():
self.terule_counts.update(c.true_rules().ruletype_count())
Expand Down
6 changes: 5 additions & 1 deletion setools/policyrep/sepol.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,10 @@ cdef extern from "<sepol/policydb/policydb.h>":
cdef int SYM_CATS
cdef int SYM_NUM

cdef int FILENAME_TRANS_MATCH_EXACT
cdef int FILENAME_TRANS_MATCH_PREFIX
cdef int FILENAME_TRANS_MATCH_SUFFIX

cdef struct policydb:
uint32_t policy_type
char *name
Expand All @@ -819,7 +823,7 @@ cdef extern from "<sepol/policydb/policydb.h>":
ocontext_t *ocontexts[9] # TODO: OCON_NUM=9
genfs_t *genfs
hashtab_t range_tr
hashtab_t filename_trans
hashtab_t filename_trans[3]
ebitmap_t *type_attr_map
ebitmap_t *attr_type_map # not saved in the binary policy
ebitmap_t policycaps
Expand Down
37 changes: 30 additions & 7 deletions setools/policyrep/terule.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -469,18 +469,29 @@ cdef class TERule(BaseTERule):
return self.rule_string


class FileNameTERuleMatchType(PolicyEnum):

"""Enumeration of name match type of FileName TE rules."""

exact = sepol.FILENAME_TRANS_MATCH_EXACT
prefix = sepol.FILENAME_TRANS_MATCH_PREFIX
suffix = sepol.FILENAME_TRANS_MATCH_SUFFIX


cdef class FileNameTERule(BaseTERule):

"""A type_transition type enforcement rule with filename."""

cdef:
Type dft
readonly str filename
readonly object match_type

@staticmethod
cdef inline FileNameTERule factory(SELinuxPolicy policy,
sepol.filename_trans_key_t *key,
Type stype, size_t otype):
Type stype, uint32_t match_type,
size_t otype):
"""Factory function for creating FileNameTERule objects."""
cdef FileNameTERule r = FileNameTERule.__new__(FileNameTERule)
r.policy = policy
Expand All @@ -491,11 +502,12 @@ cdef class FileNameTERule(BaseTERule):
r.tclass = ObjClass.factory(policy, policy.class_value_to_datum(key.tclass - 1))
r.dft = Type.factory(policy, policy.type_value_to_datum(otype - 1))
r.filename = intern(key.name)
r.match_type = FileNameTERuleMatchType(match_type)
r.origin = None
return r

def __hash__(self):
return hash("{0.ruletype}|{0.source}|{0.target}|{0.tclass}|{0.filename}|{1}|{2}".format(
return hash("{0.ruletype}|{0.source}|{0.target}|{0.tclass}|{0.filename}|{0.match_type}|{1}|{2}".format(
self, None, None))

def __lt__(self, other):
Expand Down Expand Up @@ -525,6 +537,7 @@ cdef class FileNameTERule(BaseTERule):
r.tclass = self.tclass
r.dft = self.dft
r.filename = self.filename
r.match_type = self.match_type
r.origin = None
r._conditional = self._conditional
r._conditional_block = self._conditional_block
Expand All @@ -536,8 +549,16 @@ cdef class FileNameTERule(BaseTERule):
yield self

def statement(self):
return "{0.ruletype} {0.source} {0.target}:{0.tclass} {0.default} {0.filename};". \
format(self)
if self.match_type == FileNameTERuleMatchType.exact:
match_type_str = ""
elif self.match_type == FileNameTERuleMatchType.prefix:
match_type_str = " prefix"
elif self.match_type == FileNameTERuleMatchType.suffix:
match_type_str = " suffix"
else:
raise ValueError("Invalid filename trans match type")
return "{0.ruletype} {0.source} {0.target}:{0.tclass} {0.default} {0.filename}{1};". \
format(self, match_type_str)


#
Expand Down Expand Up @@ -720,13 +741,15 @@ cdef class FileNameTERuleIterator(HashtabIterator):
cdef:
sepol.filename_trans_datum_t *datum
TypeEbitmapIterator stypei
uint32_t match_type

@staticmethod
cdef factory(SELinuxPolicy policy, sepol.hashtab_t *table):
cdef factory(SELinuxPolicy policy, sepol.hashtab_t *table, uint32_t match_type):
"""Factory function for creating FileNameTERule iterators."""
i = FileNameTERuleIterator()
i.policy = policy
i.table = table
i.match_type = match_type
i.reset()
return i

Expand All @@ -748,10 +771,10 @@ cdef class FileNameTERuleIterator(HashtabIterator):
stype = self._next_stype()
return FileNameTERule.factory(self.policy,
<sepol.filename_trans_key_t *>self.curr.key,
stype, self.datum.otype)
stype, self.match_type, self.datum.otype)

def __len__(self):
return sum(1 for r in FileNameTERuleIterator.factory(self.policy, self.table))
return sum(1 for r in FileNameTERuleIterator.factory(self.policy, self.table, self.match_type))

def reset(self):
super().reset()
Expand Down

0 comments on commit e5876ed

Please sign in to comment.