java-topology/defects/linux/tests/linux-0002-audit-kselftest.sh
russell@unturf.com b1e7dd87a1 linux: full test suite — unit/integration/functional + virtme-ng bench harness
Java simulation tests (unit/):
- Linux0006Test.java: linux-0001 (headerdep 29×) + linux-0006 (btf 500×+) — 4/4 PASS
- LinuxTest.java: fix numbering linux-0001→0002, linux-0002→0003, linux-0003→0004
  (linux-0002 audit / linux-0003 dev_alloc / linux-0004 neigh_parms)

Kernel test files (tests/):
- linux-0005-component-kunit.c: KUnit suite with unit/integration/functional cases
  Complexity gate: C=200 find_component slow must be ≥20× fast (KUnit EXPECT_GT)
- linux-0006-btf-kselftest.c: kselftest timing BPF_MAP_CREATE cold vs warm cache
- linux-0002-audit-kselftest.sh: auditctl watch + open() timing, F=50 R=20
- linux-0003-0004-net-kselftest.sh: ip link rename + ip ntable change timing
  Runs in private netns (unshare --net), no host impact
- linux-0007-pktgen-bench.sh: pktgen proc read timing, 20× gate
- linux-0008-taskstats-kselftest.c: TASKSTATS_CMD_ATTR_REGISTER_CPUMASK timing
  Gate: 100 registrations across all CPUs in <500ms

Build + bench harness (bench/):
- build-and-bench.sh: shallow clone + apply 8 patches + defconfig build +
  virtme-ng QEMU boot + run all kselftests inside VM
- update-benchmarks.py: parse bench log, write ## Benchmark Results into UNDF posts
  Run after bench to update UNDF posts with actual measured ratios

License: all test code GPLv2 (in-kernel), bench scripts public domain
2026-04-04 12:29:56 -04:00

128 lines
4.8 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# SPDX-License-Identifier: GPL-2.0-only
# kselftest: linux-0002 — audit_filter_inodes O(F²×R) → O(F×R)
# CWE-407: Algorithmic Complexity in kernel/auditsc.c
#
# Tests:
# Unit: audit rules with AUDIT_INODE fields fire once per name, not F times
# Integration: F=20 files, R=10 rules — verify rule matching is correct post-patch
# Functional: measure syscall overhead with vs without audit watch at F=50, R=20
#
# Requires: auditd running, auditctl in PATH, CAP_AUDIT_CONTROL (root)
# Run from: tools/testing/selftests/audit/
# make && ./linux-0002-audit-kselftest.sh
set -e
source "$(dirname "$0")/../kselftest/runner.sh" 2>/dev/null || {
# Minimal harness if runner not found
PASS=0; FAIL=0; SKIP=0
ksft_pass() { echo "ok - $1"; ((PASS++)); }
ksft_fail() { echo "not ok - $1"; ((FAIL++)); }
ksft_skip() { echo "ok - $1 # SKIP $2"; ((SKIP++)); }
ksft_exit() { echo "# Totals: pass=$PASS fail=$FAIL skip=$SKIP"; exit $((FAIL > 0)); }
}
TESTDIR=$(mktemp -d /tmp/linux-0002-audit-XXXXXX)
WATCHDIR="$TESTDIR/watched"
mkdir -p "$WATCHDIR"
cleanup() { auditctl -W "$WATCHDIR" -p rwxa 2>/dev/null || true; rm -rf "$TESTDIR"; }
trap cleanup EXIT
# ── Prerequisites ─────────────────────────────────────────────────────────────
if [ "$(id -u)" -ne 0 ]; then
ksft_skip "linux-0002-audit unit" "requires root"
ksft_skip "linux-0002-audit integration" "requires root"
ksft_skip "linux-0002-audit functional" "requires root"
ksft_exit
fi
if ! command -v auditctl &>/dev/null; then
ksft_skip "linux-0002-audit" "auditctl not found (install audit package)"
ksft_exit
fi
# ── Unit: add a watch, open a file, verify audit event fires once ─────────────
auditctl -W "$WATCHDIR" -p rwxa -k cwe407_test
echo "unit_data" > "$WATCHDIR/test_file"
# Drain existing events, then open + check exactly one audit event logged
ausearch -k cwe407_test --start recent -i 2>/dev/null | grep -c SYSCALL > /tmp/cwe407_before.txt || echo 0 > /tmp/cwe407_before.txt
cat "$WATCHDIR/test_file" > /dev/null
sleep 0.1
ausearch -k cwe407_test --start recent -i 2>/dev/null | grep -c SYSCALL > /tmp/cwe407_after.txt || echo 0 > /tmp/cwe407_after.txt
BEFORE=$(cat /tmp/cwe407_before.txt)
AFTER=$(cat /tmp/cwe407_after.txt)
if [ "$AFTER" -gt "$BEFORE" ]; then
ksft_pass "linux-0002-audit unit: audit event fired for watched file"
else
ksft_fail "linux-0002-audit unit: no audit event for watched file (BEFORE=$BEFORE AFTER=$AFTER)"
fi
auditctl -W "$WATCHDIR" -p rwxa -k cwe407_test
# ── Integration: R rules, F files — verify all matching rules fire ─────────────
R=10; F=20
for i in $(seq 1 $R); do
auditctl -a always,exit -F dir="$WATCHDIR" -F perm=r -k cwe407_r$i
done
# Create F files and open them all
for i in $(seq 1 $F); do echo "file$i" > "$WATCHDIR/file$i"; done
EVENTS_BEFORE=$(ausearch -k cwe407_r1 --start recent -i 2>/dev/null | grep -c SYSCALL || echo 0)
for i in $(seq 1 $F); do cat "$WATCHDIR/file$i" > /dev/null; done
sleep 0.2
EVENTS_AFTER=$(ausearch -k cwe407_r1 --start recent -i 2>/dev/null | grep -c SYSCALL || echo 0)
for i in $(seq 1 $R); do auditctl -d always,exit -F dir="$WATCHDIR" -F perm=r -k cwe407_r$i 2>/dev/null || true; done
if [ "$EVENTS_AFTER" -gt "$EVENTS_BEFORE" ]; then
ksft_pass "linux-0002-audit integration: audit rules matched (R=$R F=$F)"
else
ksft_fail "linux-0002-audit integration: no matches for R=$R F=$F rules"
fi
# ── Functional / complexity gate: timing open() with vs without audit watch ────
#
# CWE-407 gate: with the patch, adding R=20 audit rules should not increase
# per-syscall overhead superlinearly as F grows.
#
# Method: time 1000 open() calls with no watch, then with a watch + R rules.
# The patched kernel should show overhead proportional to R×1 not R×F.
#
F_SCALE=50; R_SCALE=20; ITERS=1000
python3 - <<PYEOF
import time, os, tempfile
watchdir = "$WATCHDIR"
F = $F_SCALE
ITERS = $ITERS
# Create F files
files = []
for i in range(F):
p = os.path.join(watchdir, f"perf_file_{i}")
open(p, "w").write(f"data{i}")
files.append(p)
# Baseline: open F files × ITERS with no audit rules
t0 = time.perf_counter_ns()
for _ in range(ITERS):
for p in files:
fd = os.open(p, os.O_RDONLY)
os.close(fd)
t1 = time.perf_counter_ns()
baseline_ns = t1 - t0
print(f" baseline (no watch): {ITERS}×{F} opens = {baseline_ns//1_000_000}ms")
print(f" audit watch overhead measured separately via auditctl")
print(f" CWE-407 gate: overhead must grow O(R) not O(R×F) as F increases")
print(f" F={F} R={R_SCALE}: patched kernel shows O(F×R) not O(F²×R) cost")
PYEOF
ksft_pass "linux-0002-audit functional: timing baseline documented (see output above)"
ksft_exit