[PATCH v4 1/2] checkpolicy: extend bad-data tests for type, role, and user errors
Akhil Kohli <[email protected]> Thu, 30 Jul 2026 12:18:39 +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 | 13 +++++++++++ checkpolicy/tests/negative/bad_user.te | 15 +++++++++++++ checkpolicy/tests/negative/dup_attribute.te | 13 +++++++++++ checkpolicy/tests/negative/dup_type.te | 11 ++++++++++ .../tests/negative/invalid_type_name.te | 9 ++++++++ .../tests/negative/type_attr_conflict.te | 10 +++++++++ .../tests/test_checkmodule_negative.sh | 22 ++++++++++++++++++- 8 files changed, 103 insertions(+), 1 deletion(-) 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..90a2c8c6 --- /dev/null +++ b/checkpolicy/tests/negative/bad_role.te @@ -0,0 +1,13 @@ +module bad_role 1.0; + +require { + type foo_t; + class file { read }; +} + +# Empty type list after "types" (fails at ';'). +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..b0ee8648 --- /dev/null +++ b/checkpolicy/tests/negative/bad_user.te @@ -0,0 +1,15 @@ +module bad_user 1.0; + +# Modular .te needs require before decls like user/role; without it +# checkmodule fails at "user" instead of the garbage_token below. +require { + type foo_t; + class file { read }; +} + +# Junk where "roles { ... }" should be. +user bad_user_u garbage_token; + +type foo_t; + +allow foo_t foo_t:file read; 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..dcbb3f04 100755 --- a/checkpolicy/tests/test_checkmodule_negative.sh +++ b/checkpolicy/tests/test_checkmodule_negative.sh @@ -6,8 +6,19 @@ set -eu -BASEDIR=$(CDPATH= cd -- "$(dirname "$0")" && pwd) +# Prefer an absolute script dir, but keep a relative dirname when cd fails. +# Non-root CI inherits the repo as CWD; absolute cd under /home/runner/work +# can fail for bad-data-test even when relative paths work. +BASEDIR=$(dirname -- "$0") +ABS_BASEDIR=$(CDPATH= cd -- "${BASEDIR}" 2>/dev/null && pwd) || ABS_BASEDIR= +if [ -n "${ABS_BASEDIR}" ]; then + BASEDIR="${ABS_BASEDIR}" +fi NEGDIR="${BASEDIR}/negative" +if [ ! -d "${NEGDIR}" ]; then + echo "FAIL: cannot resolve negative fixtures (\$0=$0 BASEDIR=${BASEDIR})" >&2 + exit 1 +fi CHECKMODULE="${BASEDIR}/../checkmodule" OUTDIR=$(mktemp -d "${TMPDIR:-/tmp}/checkmodule-negative.XXXXXX") PASS=0 @@ -159,6 +170,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" "garbage_token" "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