Re: [PATCH] checkpolicy: add bad data protection tests

James Carter <[email protected]>
Newsgroups org.kernel.vger.selinux
Message-ID <CAP+JOzRkxLrcDi2NkEPE8vdudaX_PWyy9FBCNwzoHe=rGg7EQQ@mail.gmail.com>
On Tue, Jul 14, 2026 at 10:23 AM James Carter <[email protected]> wrote:
>
> On Fri, Jul 10, 2026 at 7:03 AM Akhil Kohli <[email protected]> wrote:
> >
> > Add test_checkmodule_negative.sh and .te fixtures for  bad-data protection (missing/bad-path and corrupted .te inputs).
> >
> > Signed-off-by: Akhil Kohli <[email protected]>
>
> Acked-by: James Carter <[email protected]>

Merged.
Thanks,
Jim

>
> > ---
> >  checkpolicy/Makefile                          |   3 +-
> >  checkpolicy/tests/negative/bad_module_line.te |   5 +
> >  checkpolicy/tests/negative/bad_require.te     |   5 +
> >  checkpolicy/tests/negative/bad_syntax.te      |   8 +
> >  checkpolicy/tests/negative/dup_module.te      |   6 +
> >  checkpolicy/tests/negative/good_module.te     |   8 +
> >  .../tests/negative/invalid_module_version.te  |   5 +
> >  checkpolicy/tests/negative/unknown_class.te   |   7 +
> >  checkpolicy/tests/negative/unknown_perm.te    |   8 +
> >  checkpolicy/tests/negative/unknown_type.te    |   8 +
> >  .../tests/test_checkmodule_negative.sh        | 178 ++++++++++++++++++
> >  11 files changed, 240 insertions(+), 1 deletion(-)
> >  create mode 100644 checkpolicy/tests/negative/bad_module_line.te
> >  create mode 100644 checkpolicy/tests/negative/bad_require.te
> >  create mode 100644 checkpolicy/tests/negative/bad_syntax.te
> >  create mode 100644 checkpolicy/tests/negative/dup_module.te
> >  create mode 100644 checkpolicy/tests/negative/good_module.te
> >  create mode 100644 checkpolicy/tests/negative/invalid_module_version.te
> >  create mode 100644 checkpolicy/tests/negative/unknown_class.te
> >  create mode 100644 checkpolicy/tests/negative/unknown_perm.te
> >  create mode 100644 checkpolicy/tests/negative/unknown_type.te
> >  create mode 100755 checkpolicy/tests/test_checkmodule_negative.sh
> >
> > diff --git a/checkpolicy/Makefile b/checkpolicy/Makefile
> > index 0055f495..e59ad63a 100644
> > --- a/checkpolicy/Makefile
> > +++ b/checkpolicy/Makefile
> > @@ -51,8 +51,9 @@ lex.yy.c: policy_scan.l y.tab.c
> >         $(LEX) policy_scan.l
> >
> >  .PHONY: test
> > -test: checkpolicy
> > +test: checkpolicy checkmodule
> >         ./tests/test_roundtrip.sh
> > +       ./tests/test_checkmodule_negative.sh
> >
> >  # helper target for fuzzing
> >  checkobjects: $(CHECKOBJS)
> > diff --git a/checkpolicy/tests/negative/bad_module_line.te b/checkpolicy/tests/negative/bad_module_line.te
> > new file mode 100644
> > index 00000000..587df2e1
> > --- /dev/null
> > +++ b/checkpolicy/tests/negative/bad_module_line.te
> > @@ -0,0 +1,5 @@
> > +module bad module name 1.0 garbage;
> > +
> > +require {
> > +       type foo_t;
> > +}
> > diff --git a/checkpolicy/tests/negative/bad_require.te b/checkpolicy/tests/negative/bad_require.te
> > new file mode 100644
> > index 00000000..a45df4f4
> > --- /dev/null
> > +++ b/checkpolicy/tests/negative/bad_require.te
> > @@ -0,0 +1,5 @@
> > +module bad_require 1.0;
> > +
> > +require {
> > +       garbage_token foo_t;
> > +}
> > diff --git a/checkpolicy/tests/negative/bad_syntax.te b/checkpolicy/tests/negative/bad_syntax.te
> > new file mode 100644
> > index 00000000..20605201
> > --- /dev/null
> > +++ b/checkpolicy/tests/negative/bad_syntax.te
> > @@ -0,0 +1,8 @@
> > +module bad_syntax 1.0;
> > +
> > +require {
> > +       type foo_t;
> > +       class file { read };
> > +}
> > +
> > +allow foo_t foo_t:file {
> > diff --git a/checkpolicy/tests/negative/dup_module.te b/checkpolicy/tests/negative/dup_module.te
> > new file mode 100644
> > index 00000000..beefff72
> > --- /dev/null
> > +++ b/checkpolicy/tests/negative/dup_module.te
> > @@ -0,0 +1,6 @@
> > +module dup_module 1.0;
> > +module dup_module 1.0;
> > +
> > +require {
> > +       type foo_t;
> > +}
> > diff --git a/checkpolicy/tests/negative/good_module.te b/checkpolicy/tests/negative/good_module.te
> > new file mode 100644
> > index 00000000..b9c9982f
> > --- /dev/null
> > +++ b/checkpolicy/tests/negative/good_module.te
> > @@ -0,0 +1,8 @@
> > +module good_module 1.0;
> > +
> > +require {
> > +       type foo_t, bar_t;
> > +       class file { read write };
> > +}
> > +
> > +allow foo_t bar_t:file read;
> > diff --git a/checkpolicy/tests/negative/invalid_module_version.te b/checkpolicy/tests/negative/invalid_module_version.te
> > new file mode 100644
> > index 00000000..d18b7639
> > --- /dev/null
> > +++ b/checkpolicy/tests/negative/invalid_module_version.te
> > @@ -0,0 +1,5 @@
> > +module invalid_module_version;
> > +
> > +require {
> > +       type foo_t;
> > +}
> > diff --git a/checkpolicy/tests/negative/unknown_class.te b/checkpolicy/tests/negative/unknown_class.te
> > new file mode 100644
> > index 00000000..825e0413
> > --- /dev/null
> > +++ b/checkpolicy/tests/negative/unknown_class.te
> > @@ -0,0 +1,7 @@
> > +module unknown_class 1.0;
> > +
> > +require {
> > +       type foo_t;
> > +}
> > +
> > +allow foo_t self:not_a_class read;
> > diff --git a/checkpolicy/tests/negative/unknown_perm.te b/checkpolicy/tests/negative/unknown_perm.te
> > new file mode 100644
> > index 00000000..f4efbb54
> > --- /dev/null
> > +++ b/checkpolicy/tests/negative/unknown_perm.te
> > @@ -0,0 +1,8 @@
> > +module unknown_perm 1.0;
> > +
> > +require {
> > +       type foo_t, bar_t;
> > +       class file { read };
> > +}
> > +
> > +allow foo_t bar_t:file circular_ref;
> > diff --git a/checkpolicy/tests/negative/unknown_type.te b/checkpolicy/tests/negative/unknown_type.te
> > new file mode 100644
> > index 00000000..62360e04
> > --- /dev/null
> > +++ b/checkpolicy/tests/negative/unknown_type.te
> > @@ -0,0 +1,8 @@
> > +module unknown_type 1.0;
> > +
> > +require {
> > +       type foo_t;
> > +       class file { read };
> > +}
> > +
> > +allow foo_t undeclared_t:file read;
> > diff --git a/checkpolicy/tests/test_checkmodule_negative.sh b/checkpolicy/tests/test_checkmodule_negative.sh
> > new file mode 100755
> > index 00000000..a5f49f3b
> > --- /dev/null
> > +++ b/checkpolicy/tests/test_checkmodule_negative.sh
> > @@ -0,0 +1,178 @@
> > +#!/bin/sh
> > +#
> > +# Negative / bad-data tests for checkmodule on module (.te) inputs.
> > +# Matches the modular policy compile path: checkmodule -M -m <input> -o <module>.mod
> > +#
> > +
> > +set -eu
> > +
> > +BASEDIR=$(CDPATH= cd -- "$(dirname "$0")" && pwd)
> > +NEGDIR="${BASEDIR}/negative"
> > +CHECKMODULE="${BASEDIR}/../checkmodule"
> > +OUTDIR=$(mktemp -d "${TMPDIR:-/tmp}/checkmodule-negative.XXXXXX")
> > +PASS=0
> > +FAIL=0
> > +
> > +cleanup() {
> > +       rm -rf "${OUTDIR}"
> > +}
> > +trap cleanup EXIT
> > +
> > +mod_name_from_fixture() {
> > +       basename "$1" .te
> > +}
> > +
> > +expect_pass() {
> > +       desc="$1"
> > +       fixture="$2"
> > +       modname=$(mod_name_from_fixture "${fixture}")
> > +       outmod="${OUTDIR}/${modname}.mod"
> > +       stderr="${OUTDIR}/${modname}.err"
> > +
> > +       echo "==== POSITIVE (expect checkmodule success): ${desc}"
> > +       rm -f "${outmod}"
> > +
> > +       set +e
> > +       "${CHECKMODULE}" -M -m -o "${outmod}" "${NEGDIR}/${fixture}" 2>"${stderr}"
> > +       rc=$?
> > +       set -e
> > +
> > +       if [ "${rc}" -ne 0 ]; then
> > +               echo "FAIL: expected success (rc=0), got rc=${rc}" >&2
> > +               cat "${stderr}" >&2
> > +               FAIL=$((FAIL + 1))
> > +               return 1
> > +       fi
> > +       if [ ! -s "${outmod}" ]; then
> > +               echo "FAIL: expected non-empty ${outmod}" >&2
> > +               FAIL=$((FAIL + 1))
> > +               return 1
> > +       fi
> > +
> > +       echo "==== ${desc} success"
> > +       PASS=$((PASS + 1))
> > +       echo ""
> > +}
> > +
> > +expect_fail() {
> > +       desc="$1"
> > +       pattern="$2"
> > +       outname="${3:-fail}"
> > +       shift 3
> > +
> > +       outmod="${OUTDIR}/${outname}.mod"
> > +       stderr="${OUTDIR}/${outname}.err"
> > +
> > +       echo "==== NEGATIVE (expect checkmodule error): ${desc}"
> > +       rm -f "${outmod}"
> > +
> > +       set +e
> > +       "${CHECKMODULE}" -M -m "$@" -o "${outmod}" 2>"${stderr}"
> > +       rc=$?
> > +       set -e
> > +
> > +       if [ "${rc}" -eq 0 ]; then
> > +               echo "FAIL: expected non-zero exit, got rc=0" >&2
> > +               FAIL=$((FAIL + 1))
> > +               return 1
> > +       fi
> > +       if [ -f "${outmod}" ]; then
> > +               echo "FAIL: did not expect output module ${outmod}" >&2
> > +               FAIL=$((FAIL + 1))
> > +               return 1
> > +       fi
> > +       if ! grep -Eq "${pattern}" "${stderr}"; then
> > +               echo "FAIL: stderr did not match /${pattern}/" >&2
> > +               cat "${stderr}" >&2
> > +               FAIL=$((FAIL + 1))
> > +               return 1
> > +       fi
> > +
> > +       echo "==== ${desc}: rejected as expected"
> > +       PASS=$((PASS + 1))
> > +       echo ""
> > +}
> > +
> > +expect_fail_unreadable() {
> > +       desc="unreadable .te file"
> > +       fixture="${OUTDIR}/unreadable.te"
> > +       outmod="${OUTDIR}/unreadable.mod"
> > +       stderr="${OUTDIR}/unreadable.err"
> > +
> > +       echo "==== NEGATIVE (expect checkmodule error): ${desc}"
> > +       if [ "$(id -u)" -eq 0 ]; then
> > +               echo "SKIP: root can read mode 000 files; unreadable check is non-root only"
> > +               PASS=$((PASS + 1))
> > +               echo ""
> > +               return 0
> > +       fi
> > +
> > +       rm -f "${outmod}"
> > +
> > +       set +e
> > +       "${CHECKMODULE}" -M -m -o "${outmod}" "${fixture}" 2>"${stderr}"
> > +       rc=$?
> > +       set -e
> > +
> > +       if [ "${rc}" -eq 0 ]; then
> > +               echo "FAIL: expected non-zero exit, got rc=0" >&2
> > +               FAIL=$((FAIL + 1))
> > +               return 1
> > +       fi
> > +       if [ -f "${outmod}" ]; then
> > +               echo "FAIL: did not expect output module ${outmod}" >&2
> > +               FAIL=$((FAIL + 1))
> > +               return 1
> > +       fi
> > +       if ! grep -Eq 'unable to open|Permission denied' "${stderr}"; then
> > +               echo "FAIL: stderr did not mention unable to open or Permission denied" >&2
> > +               cat "${stderr}" >&2
> > +               FAIL=$((FAIL + 1))
> > +               return 1
> > +       fi
> > +
> > +       echo "==== ${desc}: rejected as expected"
> > +       PASS=$((PASS + 1))
> > +       echo ""
> > +}
> > +
> > +# Ephemeral fixtures for path-based cases.
> > +ln -sf /nonexistent/path "${OUTDIR}/broken_symlink.te"
> > +cat > "${OUTDIR}/unreadable.te" <<'EOF'
> > +module unreadable 1.0;
> > +
> > +require {
> > +       type foo_t;
> > +}
> > +EOF
> > +chmod 000 "${OUTDIR}/unreadable.te"
> > +
> > +# Control fixture: valid module compiles and produces .mod output.
> > +expect_pass "good_module.te" "good_module.te"
> > +
> > +# Corrupted .te sections (PDF #2).
> > +expect_fail "bad_syntax.te" "syntax error" "bad_syntax" "${NEGDIR}/bad_syntax.te"
> > +expect_fail "unknown_perm.te" "permission circular_ref is not defined" "unknown_perm" "${NEGDIR}/unknown_perm.te"
> > +expect_fail "unknown_type.te" "unknown type undeclared_t" "unknown_type" "${NEGDIR}/unknown_type.te"
> > +expect_fail "unknown_class.te" "unknown class not_a_class" "unknown_class" "${NEGDIR}/unknown_class.te"
> > +expect_fail "bad_module_line.te" "syntax error" "bad_module_line" "${NEGDIR}/bad_module_line.te"
> > +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"
> > +
> > +# Missing / bad-path .te inputs (PDF #1).
> > +expect_fail "missing .te path" "unable to open" "missing_path" "${OUTDIR}/does_not_exist.te"
> > +expect_fail "directory instead of .te file" "input in flex scanner failed" "directory_input" "${NEGDIR}"
> > +expect_fail "broken symlink to .te" "unable to open" "broken_symlink" "${OUTDIR}/broken_symlink.te"
> > +expect_fail_unreadable
> > +expect_fail "empty .te path argument" "unable to open" "empty_path" ""
> > +
> > +# CLI edge cases.
> > +expect_fail "checkmodule with no input file" "unable to open policy.conf" "no_input"
> > +expect_fail "checkmodule -o name mismatch" "Module name good_module is different" "name_mismatch" \
> > +       -o "${OUTDIR}/wrong_name.mod" "${NEGDIR}/good_module.te"
> > +
> > +echo "checkmodule negative tests: ${PASS} passed, ${FAIL} failed"
> > +if [ "${FAIL}" -ne 0 ]; then
> > +       exit 1
> > +fi
> > --
> > 2.55.0
> >
> >
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.