selftests/lkdtm: Add tests for LKDTM targets

This adds a basic framework for running all the "safe" LKDTM tests. This
will allow easy introspection into any selftest logs to examine the
results of most LKDTM tests.

Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
This commit is contained in:
Kees Cook 2020-01-09 21:02:06 -08:00 committed by Shuah Khan
parent 192c197cbc
commit 46d1a0f03d
6 changed files with 178 additions and 0 deletions

View File

@ -9581,6 +9581,7 @@ LINUX KERNEL DUMP TEST MODULE (LKDTM)
M: Kees Cook <keescook@chromium.org>
S: Maintained
F: drivers/misc/lkdtm/*
F: tools/testing/selftests/lkdtm/*
LINUX KERNEL MEMORY CONSISTENCY MODEL (LKMM)
M: Alan Stern <stern@rowland.harvard.edu>

View File

@ -26,6 +26,7 @@ TARGETS += kexec
TARGETS += kvm
TARGETS += lib
TARGETS += livepatch
TARGETS += lkdtm
TARGETS += membarrier
TARGETS += memfd
TARGETS += memory-hotplug

View File

@ -0,0 +1,12 @@
# SPDX-License-Identifier: GPL-2.0
# Makefile for LKDTM regression tests
include ../lib.mk
# NOTE: $(OUTPUT) won't get default value if used before lib.mk
TEST_FILES := tests.txt
TEST_GEN_PROGS = $(patsubst %,$(OUTPUT)/%.sh,$(shell awk '{print $$1}' tests.txt | sed -e 's/\#//'))
all: $(TEST_GEN_PROGS)
$(OUTPUT)/%: run.sh tests.txt
install -m 0744 run.sh $@

View File

@ -0,0 +1 @@
CONFIG_LKDTM=y

View File

@ -0,0 +1,92 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
#
# This reads tests.txt for the list of LKDTM tests to invoke. Any marked
# with a leading "#" are skipped. The rest of the line after the
# test name is either the text to look for in dmesg for a "success",
# or the rationale for why a test is marked to be skipped.
#
set -e
TRIGGER=/sys/kernel/debug/provoke-crash/DIRECT
KSELFTEST_SKIP_TEST=4
# Verify we have LKDTM available in the kernel.
if [ ! -r $TRIGGER ] ; then
/sbin/modprobe -q lkdtm || true
if [ ! -r $TRIGGER ] ; then
echo "Cannot find $TRIGGER (missing CONFIG_LKDTM?)"
else
echo "Cannot write $TRIGGER (need to run as root?)"
fi
# Skip this test
exit $KSELFTEST_SKIP_TEST
fi
# Figure out which test to run from our script name.
test=$(basename $0 .sh)
# Look up details about the test from master list of LKDTM tests.
line=$(egrep '^#?'"$test"'\b' tests.txt)
if [ -z "$line" ]; then
echo "Skipped: missing test '$test' in tests.txt"
exit $KSELFTEST_SKIP_TEST
fi
# Check that the test is known to LKDTM.
if ! egrep -q '^'"$test"'$' "$TRIGGER" ; then
echo "Skipped: test '$test' missing in $TRIGGER!"
exit $KSELFTEST_SKIP_TEST
fi
# Extract notes/expected output from test list.
test=$(echo "$line" | cut -d" " -f1)
if echo "$line" | grep -q ' ' ; then
expect=$(echo "$line" | cut -d" " -f2-)
else
expect=""
fi
# If the test is commented out, report a skip
if echo "$test" | grep -q '^#' ; then
test=$(echo "$test" | cut -c2-)
if [ -z "$expect" ]; then
expect="crashes entire system"
fi
echo "Skipping $test: $expect"
exit $KSELFTEST_SKIP_TEST
fi
# If no expected output given, assume an Oops with back trace is success.
if [ -z "$expect" ]; then
expect="call trace:"
fi
# Clear out dmesg for output reporting
dmesg -c >/dev/null
# Prepare log for report checking
LOG=$(mktemp --tmpdir -t lkdtm-XXXXXX)
cleanup() {
rm -f "$LOG"
}
trap cleanup EXIT
# Most shells yell about signals and we're expecting the "cat" process
# to usually be killed by the kernel. So we have to run it in a sub-shell
# and silence errors.
($SHELL -c 'cat <(echo '"$test"') >'"$TRIGGER" 2>/dev/null) || true
# Record and dump the results
dmesg -c >"$LOG"
cat "$LOG"
# Check for expected output
if egrep -qi "$expect" "$LOG" ; then
echo "$test: saw '$expect': ok"
exit 0
else
if egrep -qi XFAIL: "$LOG" ; then
echo "$test: saw 'XFAIL': [SKIP]"
exit $KSELFTEST_SKIP_TEST
else
echo "$test: missing '$expect': [FAIL]"
exit 1
fi
fi

View File

@ -0,0 +1,71 @@
#PANIC
BUG kernel BUG at
WARNING WARNING:
WARNING_MESSAGE message trigger
EXCEPTION
#LOOP Hangs the system
#EXHAUST_STACK Corrupts memory on failure
#CORRUPT_STACK Crashes entire system on success
#CORRUPT_STACK_STRONG Crashes entire system on success
CORRUPT_LIST_ADD list_add corruption
CORRUPT_LIST_DEL list_del corruption
CORRUPT_USER_DS Invalid address limit on user-mode return
STACK_GUARD_PAGE_LEADING
STACK_GUARD_PAGE_TRAILING
UNSET_SMEP CR4 bits went missing
DOUBLE_FAULT
UNALIGNED_LOAD_STORE_WRITE
#OVERWRITE_ALLOCATION Corrupts memory on failure
#WRITE_AFTER_FREE Corrupts memory on failure
READ_AFTER_FREE
#WRITE_BUDDY_AFTER_FREE Corrupts memory on failure
READ_BUDDY_AFTER_FREE
SLAB_FREE_DOUBLE
SLAB_FREE_CROSS
SLAB_FREE_PAGE
#SOFTLOCKUP Hangs the system
#HARDLOCKUP Hangs the system
#SPINLOCKUP Hangs the system
#HUNG_TASK Hangs the system
EXEC_DATA
EXEC_STACK
EXEC_KMALLOC
EXEC_VMALLOC
EXEC_RODATA
EXEC_USERSPACE
EXEC_NULL
ACCESS_USERSPACE
ACCESS_NULL
WRITE_RO
WRITE_RO_AFTER_INIT
WRITE_KERN
REFCOUNT_INC_OVERFLOW
REFCOUNT_ADD_OVERFLOW
REFCOUNT_INC_NOT_ZERO_OVERFLOW
REFCOUNT_ADD_NOT_ZERO_OVERFLOW
REFCOUNT_DEC_ZERO
REFCOUNT_DEC_NEGATIVE Negative detected: saturated
REFCOUNT_DEC_AND_TEST_NEGATIVE Negative detected: saturated
REFCOUNT_SUB_AND_TEST_NEGATIVE Negative detected: saturated
REFCOUNT_INC_ZERO
REFCOUNT_ADD_ZERO
REFCOUNT_INC_SATURATED Saturation detected: still saturated
REFCOUNT_DEC_SATURATED Saturation detected: still saturated
REFCOUNT_ADD_SATURATED Saturation detected: still saturated
REFCOUNT_INC_NOT_ZERO_SATURATED
REFCOUNT_ADD_NOT_ZERO_SATURATED
REFCOUNT_DEC_AND_TEST_SATURATED Saturation detected: still saturated
REFCOUNT_SUB_AND_TEST_SATURATED Saturation detected: still saturated
#REFCOUNT_TIMING timing only
#ATOMIC_TIMING timing only
USERCOPY_HEAP_SIZE_TO
USERCOPY_HEAP_SIZE_FROM
USERCOPY_HEAP_WHITELIST_TO
USERCOPY_HEAP_WHITELIST_FROM
USERCOPY_STACK_FRAME_TO
USERCOPY_STACK_FRAME_FROM
USERCOPY_STACK_BEYOND
USERCOPY_KERNEL
USERCOPY_KERNEL_DS
STACKLEAK_ERASING OK: the rest of the thread stack is properly erased
CFI_FORWARD_PROTO