Re: [PATCH v2] python/sepolgen: port policygen.py to setools 4 API

Stephen Smalley <[email protected]> Fri, 24 Jul 2026 10:19:21 -0400
Newsgroups org.kernel.vger.selinux
Message-ID <CAEjxPJ6RJQAymiPCF5OTr2cT86PeNbwzs9ZA=+OnEb3AWD=UrQ@mail.gmail.com>
On Mon, Jul 20, 2026 at 3:53 PM Stephen Smalley
<[email protected]> wrote:
>
> policygen.py still called seinfo() and sesearch(), the setools 3
> python bindings that were removed years ago. The calls only survived
> because they sat inside a bare "try/except: pass", so the "source type
> can write to..."  hint in audit2allow output has been silently dead.
>
> Replace them with the setools 4 equivalents:
> - SELinuxPolicy().lookup_typeattr("domain").expand() for the
> domain attribute member set.
> - TERuleQuery(ruletype=[allow], source=..., tclass=[...], perms=...,
> perms_subset=True) for the allow rule search, expanding rule.target
> so attribute targets are resolved to concrete types
>
> While here, cache the loaded policy on the PolicyGenerator instance so
> it is not reparsed for every access vector, drop the wildcard import,
> narrow the bare except to setools exceptions, and dedupe/sort the
> resulting type list for stable output.
>
> Fixes: https://github.com/SELinuxProject/selinux/issues/332
> Signed-off-by: Stephen Smalley <[email protected]>

Merged.

> ---
>  python/sepolgen/src/sepolgen/policygen.py | 41 ++++++++++++++---------
>  1 file changed, 25 insertions(+), 16 deletions(-)
>
> diff --git a/python/sepolgen/src/sepolgen/policygen.py b/python/sepolgen/src/sepolgen/policygen.py
> index 7715bed5..a5af521a 100644
> --- a/python/sepolgen/src/sepolgen/policygen.py
> +++ b/python/sepolgen/src/sepolgen/policygen.py
> @@ -26,9 +26,9 @@ import textwrap
>
>  import selinux.audit2why as audit2why
>  try:
> -    from setools import *
> -except:
> -    pass
> +    import setools
> +except ImportError:
> +    setools = None
>
>  from . import refpolicy
>  from . import objectmodel
> @@ -85,6 +85,7 @@ class PolicyGenerator:
>          self.dontaudit = False
>          self.xperms = False
>
> +        self.policy = None
>          self.domains = None
>          self.gen_cil = False
>          self.comment_start = '#'
> @@ -206,23 +207,31 @@ class PolicyGenerator:
>                  rule.comment += "\n%s" % self.comment_start
>                  rule.comment += "\tPossible cause is the source %s and target %s are different." % reason
>
> -        try:
> -            if ( av.type == audit2why.TERULE and
> -                 "write" in av.perms and
> -                 ( "dir" in av.obj_class or "open" in av.perms )):
> -                if not self.domains:
> -                    self.domains = seinfo(ATTRIBUTE, name="domain")[0]["types"]
> -                types=[]
> -
> -                for i in [x[TCONTEXT] for x in sesearch([ALLOW], {SCONTEXT: av.src_type, CLASS: av.obj_class, PERMS: av.perms})]:
> -                    if i not in self.domains:
> -                        types.append(i)
> +        if ( setools and
> +             av.type == audit2why.TERULE and
> +             "write" in av.perms and
> +             ( "dir" in av.obj_class or "open" in av.perms )):
> +            try:
> +                if not self.policy:
> +                    self.policy = setools.SELinuxPolicy()
> +                    self.domains = set(str(t) for t in
> +                                       self.policy.lookup_typeattr("domain").expand())
> +                q = setools.TERuleQuery(self.policy,
> +                                        ruletype=[setools.TERuletype.allow],
> +                                        source=av.src_type,
> +                                        tclass=[av.obj_class],
> +                                        perms=av.perms, perms_subset=True)
> +                types = set()
> +                for r in q.results():
> +                    types.update(str(t) for t in r.target.expand())
> +                types -= self.domains
> +                types = sorted(types)
>                  if len(types) == 1:
>                      rule.comment += "\n%s!!!! The source type '%s' can write to a '%s' of the following type:\n%s %s\n" % (self.comment_start, av.src_type, av.obj_class, self.comment_start, ", ".join(types))
>                  elif len(types) >= 1:
>                      rule.comment += "\n%s!!!! The source type '%s' can write to a '%s' of the following types:\n%s %s\n" % (self.comment_start, av.src_type, av.obj_class, self.comment_start, ", ".join(types))
> -        except:
> -            pass
> +            except setools.exception.SEToolsException:
> +                pass
>
>          self.module.children.append(rule)
>
> --
> 2.55.0
>