Skip to content

Commit

Permalink
Merge pull request #145 from cgzones/role_types
Browse files Browse the repository at this point in the history
Add option to see roles allowed for single type
  • Loading branch information
pebenito authored Jan 8, 2025
2 parents 69a22ed + 349dcff commit d31e634
Show file tree
Hide file tree
Showing 5 changed files with 227 additions and 0 deletions.
8 changes: 8 additions & 0 deletions seinfo
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ queries.add_argument("--polcap", help="Print policy capabilities.", dest="polcap
nargs='?', const=True, metavar="NAME")
queries.add_argument("--portcon", help="Print portcon statements.", dest="portconquery",
nargs='?', const=True, metavar="PORTNUM[-PORTNUM]")
queries.add_argument("--role_types", help="Print all roles associated with the given type.",
dest="roletypesquery", nargs=1, metavar="TYPE")
queries.add_argument("--sensitivity", help="Print MLS sensitivities.", dest="mlssensquery",
nargs='?', const=True, metavar="SENS")
queries.add_argument("--typebounds", help="Print typebounds statements.", dest="typeboundsquery",
Expand Down Expand Up @@ -263,6 +265,12 @@ try:

components.append(("Roles", rq, lambda x: x.statement()))

if args.roletypesquery:
q = setools.RoleTypesQuery(p)
q.name = args.roletypesquery[0]

components.append(("Roles", q, lambda x: x.statement()))

if args.mlssensquery or args.all:
msq = setools.SensitivityQuery(p, alias_deref=True)
if isinstance(args.mlssensquery, str):
Expand Down
1 change: 1 addition & 0 deletions setools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
from .objclassquery import ObjClassQuery
from .polcapquery import PolCapQuery
from .rolequery import RoleQuery
from .roletypesquery import RoleTypesQuery
from .sensitivityquery import SensitivityQuery
from .typequery import TypeQuery
from .typeattrquery import TypeAttributeQuery
Expand Down
36 changes: 36 additions & 0 deletions setools/roletypesquery.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Copyright 2025, Christian Göttsche
#
# SPDX-License-Identifier: LGPL-2.1-only
#
from collections.abc import Iterable
import typing

from . import mixins, policyrep, query

__all__: typing.Final[tuple[str, ...]] = ("RoleTypesQuery",)


class RoleTypesQuery(mixins.MatchName, query.PolicyQuery):

"""
Query SELinux policy roles.
Parameter:
policy The policy to query.
Keyword Parameters/Class attributes:
name The type name to match.
name_regex If true, regular expression matching
will be used on the type names.
"""

def results(self) -> Iterable[policyrep.Role]:
"""Generator which yields all matching roles."""
self.log.info(f"Generating role-types results from {self.policy}")
self._match_name_debug(self.log)

for r in self.policy.roles():
for t in r.types():
if self._match_name(t):
yield r
break
144 changes: 144 additions & 0 deletions tests/library/roletypesquery.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
class infoflow
class infoflow2
class infoflow3
class infoflow4
class infoflow5
class infoflow6
class infoflow7

sid kernel
sid security

common infoflow
{
low_w
med_w
hi_w
low_r
med_r
hi_r
}

class infoflow
inherits infoflow

class infoflow2
inherits infoflow
{
super_w
super_r
}

class infoflow3
{
null
}

class infoflow4
inherits infoflow

class infoflow5
inherits infoflow

class infoflow6
inherits infoflow

class infoflow7
inherits infoflow
{
super_w
super_r
super_none
super_both
super_unmapped
}

sensitivity low_s;
sensitivity medium_s alias med;
sensitivity high_s;

dominance { low_s med high_s }

category here;
category there;
category elsewhere alias lost;

#level decl
level low_s:here.there;
level med:here, elsewhere;
level high_s:here.lost;

#some constraints
mlsconstrain infoflow hi_r ((l1 dom l2) or (t1 == mls_exempt));

attribute mls_exempt;

type system;
role system;
role system types system;

################################################################################
# Type enforcement declarations and rules

allow system system:infoflow3 null;

########################################
#
# Role Query
#

# test 1
type test1;

# test 2
role test2ra;
role test2rb;
type test2a;
type test2b;
role test2ra types { test2a test2b };
role test2rb types test2b;

# test 3

role test3ra;
role test3rb;
role test3rc;
role test3rd;
type test3a;
type test3b;
type test3c;
type test3d;
role test3ra types { test3b test3c test3d };
role test3rb types { test3a test3c test3d };
role test3rc types { test3a test3b test3d };
role test3rd types { test3a test3b test3c };

################################################################################

#users
user system roles system level med range low_s - high_s:here.lost;

#normal constraints
constrain infoflow hi_w (u1 == u2);

#isids
sid kernel system:system:system:medium_s:here
sid security system:system:system:high_s:lost

#fs_use
fs_use_trans devpts system:object_r:system:low_s;
fs_use_xattr ext3 system:object_r:system:low_s;
fs_use_task pipefs system:object_r:system:low_s;

#genfscon
genfscon proc / system:object_r:system:med
genfscon proc /sys system:object_r:system:low_s
genfscon selinuxfs / system:object_r:system:high_s:here.there

portcon tcp 80 system:object_r:system:low_s

netifcon eth0 system:object_r:system:low_s system:object_r:system:low_s

nodecon 127.0.0.1 255.255.255.255 system:object_r:system:low_s:here
nodecon ::1 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff system:object_r:system:low_s:here

38 changes: 38 additions & 0 deletions tests/library/test_roletypesquery.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Copyright 2025, Christian Göttsche
#
# SPDX-License-Identifier: GPL-2.0-only
#
import pytest
import setools


@pytest.mark.obj_args("tests/library/roletypesquery.conf")
class TestRoleTypesQuery:

def test_name_nomatch(self, compiled_policy: setools.SELinuxPolicy) -> None:
"""Type with no associated role."""
q = setools.RoleTypesQuery(compiled_policy, name="test1")

roles = sorted(str(r) for r in q.results())
assert [] == roles

def test_name_onematch(self, compiled_policy: setools.SELinuxPolicy) -> None:
"""Type with one associated role."""
q = setools.RoleTypesQuery(compiled_policy, name="test2a")

roles = sorted(str(r) for r in q.results())
assert ["test2ra"] == roles

def test_name_multiplematches(self, compiled_policy: setools.SELinuxPolicy) -> None:
"""Type with multiple associated roles."""
q = setools.RoleTypesQuery(compiled_policy, name="test3a")

roles = sorted(str(r) for r in q.results())
assert ["test3rb", "test3rc", "test3rd"] == roles

def test_name_multiplematches_regex(self, compiled_policy: setools.SELinuxPolicy) -> None:
"""Multiple types with multiple associated roles."""
q = setools.RoleTypesQuery(compiled_policy, name="test3", name_regex=True)

roles = sorted(str(r) for r in q.results())
assert ["test3ra", "test3rb", "test3rc", "test3rd"] == roles

0 comments on commit d31e634

Please sign in to comment.