[PATCH v2 1/2] checkpolicy: extend bad-data tests for type, role, and user errors

Akhil Kohli <[email protected]> Tue, 28 Jul 2026 00:32:41 +0200
Newsgroups org.kernel.vger.selinux
Message-ID <[email protected]>
Add negative .te fixtures for duplicate type/attribute declarations,
type/attribute name conflicts, invalid type names, and malformed role
and user stanzas. Run checkmodule negative tests as non-root in CI so
the unreadable .te case is exercised outside root-only skips.

Signed-off-by: Akhil Kohli <[email protected]>
---
 .github/workflows/run_tests.yml                  | 11 +++++++++++
 checkpolicy/tests/negative/bad_role.te           | 12 ++++++++++++
 checkpolicy/tests/negative/bad_user.te           |  3 +++
 checkpolicy/tests/negative/dup_attribute.te      | 13 +++++++++++++
 checkpolicy/tests/negative/dup_type.te           | 11 +++++++++++
 checkpolicy/tests/negative/invalid_type_name.te  |  9 +++++++++
 checkpolicy/tests/negative/type_attr_conflict.te | 10 ++++++++++
 checkpolicy/tests/test_checkmodule_negative.sh   |  9 +++++++++
 8 files changed, 78 insertions(+)
 create mode 100644 checkpolicy/tests/negative/bad_role.te
 create mode 100644 checkpolicy/tests/negative/bad_user.te
 create mode 100644 checkpolicy/tests/negative/dup_attribute.te
 create mode 100644 checkpolicy/tests/negative/dup_type.te
 create mode 100644 checkpolicy/tests/negative/invalid_type_name.te
 create mode 100644 checkpolicy/tests/negative/type_attr_conflict.te

diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml
index 4322ddff..8e9afa10 100644
--- a/.github/workflows/run_tests.yml
+++ b/.github/workflows/run_tests.yml
@@ -95,6 +95,17 @@ jobs:
           echo "::endgroup::"
         fi
 
+        # checkmodule bad-data: unreadable .te needs non-root (root reads mode 000).
+        if [ "${{ matrix.python-ruby-version.other }}" != "sanitizers" ] ; then
+          echo "::group::checkpolicy bad-data (non-root)"
+          sudo useradd -m -s /usr/sbin/nologin bad-data-test 2>/dev/null || true
+          chmod -R a+rX .
+          sudo runuser -u bad-data-test -- env PATH="$PATH" LD_LIBRARY_PATH="$LD_LIBRARY_PATH" \
+            ./checkpolicy/tests/test_checkmodule_negative.sh
+          sudo userdel -r bad-data-test 2>/dev/null || true
+          echo "::endgroup::"
+        fi
+
         if [ "${{ matrix.python-ruby-version.other }}" != "sanitizers" ] ; then
             # Test Python and Ruby wrappers
             echo "::group::Test Python and Ruby wrappers"
diff --git a/checkpolicy/tests/negative/bad_role.te b/checkpolicy/tests/negative/bad_role.te
new file mode 100644
index 00000000..3aae2719
--- /dev/null
+++ b/checkpolicy/tests/negative/bad_role.te
@@ -0,0 +1,12 @@
+module bad_role 1.0;
+
+require {
+	type foo_t;
+	class file { read };
+}
+
+role bad_role_r types ;
+
+type foo_t;
+
+allow foo_t foo_t:file read;
diff --git a/checkpolicy/tests/negative/bad_user.te b/checkpolicy/tests/negative/bad_user.te
new file mode 100644
index 00000000..e7460dd7
--- /dev/null
+++ b/checkpolicy/tests/negative/bad_user.te
@@ -0,0 +1,3 @@
+module bad_user 1.0;
+
+user bad_user_u garbage_token;
diff --git a/checkpolicy/tests/negative/dup_attribute.te b/checkpolicy/tests/negative/dup_attribute.te
new file mode 100644
index 00000000..24014d0b
--- /dev/null
+++ b/checkpolicy/tests/negative/dup_attribute.te
@@ -0,0 +1,13 @@
+module dup_attribute 1.0;
+
+require {
+	type foo_t;
+	class file { read };
+}
+
+attribute bar_attr;
+attribute bar_attr;
+
+type foo_t;
+
+allow foo_t foo_t:file read;
diff --git a/checkpolicy/tests/negative/dup_type.te b/checkpolicy/tests/negative/dup_type.te
new file mode 100644
index 00000000..2961dd0a
--- /dev/null
+++ b/checkpolicy/tests/negative/dup_type.te
@@ -0,0 +1,11 @@
+module dup_type 1.0;
+
+require {
+	type foo_t;
+	class file { read };
+}
+
+type foo_t;
+type foo_t;
+
+allow foo_t foo_t:file read;
diff --git a/checkpolicy/tests/negative/invalid_type_name.te b/checkpolicy/tests/negative/invalid_type_name.te
new file mode 100644
index 00000000..6fe14fbb
--- /dev/null
+++ b/checkpolicy/tests/negative/invalid_type_name.te
@@ -0,0 +1,9 @@
+module invalid_type_name 1.0;
+
+require {
+	class file { read };
+}
+
+type 1bad;
+
+allow 1bad 1bad:file read;
diff --git a/checkpolicy/tests/negative/type_attr_conflict.te b/checkpolicy/tests/negative/type_attr_conflict.te
new file mode 100644
index 00000000..160cd386
--- /dev/null
+++ b/checkpolicy/tests/negative/type_attr_conflict.te
@@ -0,0 +1,10 @@
+module type_attr_conflict 1.0;
+
+require {
+	class file { read };
+}
+
+type shared_id;
+attribute shared_id;
+
+allow shared_id shared_id:file read;
diff --git a/checkpolicy/tests/test_checkmodule_negative.sh b/checkpolicy/tests/test_checkmodule_negative.sh
index a5f49f3b..6d289a4c 100755
--- a/checkpolicy/tests/test_checkmodule_negative.sh
+++ b/checkpolicy/tests/test_checkmodule_negative.sh
@@ -159,6 +159,15 @@ expect_fail "bad_module_line.te" "syntax error" "bad_module_line" "${NEGDIR}/bad
 expect_fail "bad_require.te" "syntax error" "bad_require" "${NEGDIR}/bad_require.te"
 expect_fail "invalid_module_version.te" "syntax error" "invalid_module_version" "${NEGDIR}/invalid_module_version.te"
 expect_fail "dup_module.te" "syntax error" "dup_module" "${NEGDIR}/dup_module.te"
+expect_fail "dup_type.te" "Duplicate declaration of type" "dup_type" "${NEGDIR}/dup_type.te"
+expect_fail "dup_attribute.te" "Duplicate declaration of type" "dup_attribute" \
+	"${NEGDIR}/dup_attribute.te"
+expect_fail "type_attr_conflict.te" "Duplicate declaration of type" "type_attr_conflict" \
+	"${NEGDIR}/type_attr_conflict.te"
+expect_fail "invalid_type_name.te" "syntax error" "invalid_type_name" \
+	"${NEGDIR}/invalid_type_name.te"
+expect_fail "bad_role.te" "syntax error" "bad_role" "${NEGDIR}/bad_role.te"
+expect_fail "bad_user.te" "syntax error" "bad_user" "${NEGDIR}/bad_user.te"
 
 # Missing / bad-path .te inputs (PDF #1).
 expect_fail "missing .te path" "unable to open" "missing_path" "${OUTDIR}/does_not_exist.te"
-- 
2.55.0