146d1a0f0SKees Cook#!/bin/sh 246d1a0f0SKees Cook# SPDX-License-Identifier: GPL-2.0 346d1a0f0SKees Cook# 446d1a0f0SKees Cook# This reads tests.txt for the list of LKDTM tests to invoke. Any marked 546d1a0f0SKees Cook# with a leading "#" are skipped. The rest of the line after the 646d1a0f0SKees Cook# test name is either the text to look for in dmesg for a "success", 746d1a0f0SKees Cook# or the rationale for why a test is marked to be skipped. 846d1a0f0SKees Cook# 946d1a0f0SKees Cookset -e 1046d1a0f0SKees CookTRIGGER=/sys/kernel/debug/provoke-crash/DIRECT 114fccc8c0SKees CookCLEAR_ONCE=/sys/kernel/debug/clear_warn_once 1246d1a0f0SKees CookKSELFTEST_SKIP_TEST=4 1346d1a0f0SKees Cook 1446d1a0f0SKees Cook# Verify we have LKDTM available in the kernel. 1546d1a0f0SKees Cookif [ ! -r $TRIGGER ] ; then 1646d1a0f0SKees Cook /sbin/modprobe -q lkdtm || true 1746d1a0f0SKees Cook if [ ! -r $TRIGGER ] ; then 1846d1a0f0SKees Cook echo "Cannot find $TRIGGER (missing CONFIG_LKDTM?)" 1946d1a0f0SKees Cook else 2046d1a0f0SKees Cook echo "Cannot write $TRIGGER (need to run as root?)" 2146d1a0f0SKees Cook fi 2246d1a0f0SKees Cook # Skip this test 2346d1a0f0SKees Cook exit $KSELFTEST_SKIP_TEST 2446d1a0f0SKees Cookfi 2546d1a0f0SKees Cook 2646d1a0f0SKees Cook# Figure out which test to run from our script name. 2746d1a0f0SKees Cooktest=$(basename $0 .sh) 2846d1a0f0SKees Cook# Look up details about the test from master list of LKDTM tests. 29851c4df5SMichael Ellermanline=$(grep -E '^#?'"$test"'\b' tests.txt) 3046d1a0f0SKees Cookif [ -z "$line" ]; then 3146d1a0f0SKees Cook echo "Skipped: missing test '$test' in tests.txt" 3246d1a0f0SKees Cook exit $KSELFTEST_SKIP_TEST 3346d1a0f0SKees Cookfi 3446d1a0f0SKees Cook# Check that the test is known to LKDTM. 35851c4df5SMichael Ellermanif ! grep -E -q '^'"$test"'$' "$TRIGGER" ; then 3646d1a0f0SKees Cook echo "Skipped: test '$test' missing in $TRIGGER!" 3746d1a0f0SKees Cook exit $KSELFTEST_SKIP_TEST 3846d1a0f0SKees Cookfi 3946d1a0f0SKees Cook 4046d1a0f0SKees Cook# Extract notes/expected output from test list. 4146d1a0f0SKees Cooktest=$(echo "$line" | cut -d" " -f1) 4246d1a0f0SKees Cookif echo "$line" | grep -q ' ' ; then 4346d1a0f0SKees Cook expect=$(echo "$line" | cut -d" " -f2-) 4446d1a0f0SKees Cookelse 4546d1a0f0SKees Cook expect="" 4646d1a0f0SKees Cookfi 4746d1a0f0SKees Cook 4846d1a0f0SKees Cook# If the test is commented out, report a skip 4946d1a0f0SKees Cookif echo "$test" | grep -q '^#' ; then 5046d1a0f0SKees Cook test=$(echo "$test" | cut -c2-) 5146d1a0f0SKees Cook if [ -z "$expect" ]; then 5246d1a0f0SKees Cook expect="crashes entire system" 5346d1a0f0SKees Cook fi 5446d1a0f0SKees Cook echo "Skipping $test: $expect" 5546d1a0f0SKees Cook exit $KSELFTEST_SKIP_TEST 5646d1a0f0SKees Cookfi 5746d1a0f0SKees Cook 5846d1a0f0SKees Cook# If no expected output given, assume an Oops with back trace is success. 59*149538cdSKees Cookrepeat=1 6046d1a0f0SKees Cookif [ -z "$expect" ]; then 6146d1a0f0SKees Cook expect="call trace:" 62*149538cdSKees Cookelse 63*149538cdSKees Cook if echo "$expect" | grep -q '^repeat:' ; then 64*149538cdSKees Cook repeat=$(echo "$expect" | cut -d' ' -f1 | cut -d: -f2) 65*149538cdSKees Cook expect=$(echo "$expect" | cut -d' ' -f2-) 66*149538cdSKees Cook fi 6746d1a0f0SKees Cookfi 6846d1a0f0SKees Cook 6946d1a0f0SKees Cook# Prepare log for report checking 70f131d9edSMichael EllermanLOG=$(mktemp --tmpdir -t lkdtm-log-XXXXXX) 71f131d9edSMichael EllermanDMESG=$(mktemp --tmpdir -t lkdtm-dmesg-XXXXXX) 7246d1a0f0SKees Cookcleanup() { 73f131d9edSMichael Ellerman rm -f "$LOG" "$DMESG" 7446d1a0f0SKees Cook} 7546d1a0f0SKees Cooktrap cleanup EXIT 7646d1a0f0SKees Cook 774fccc8c0SKees Cook# Reset WARN_ONCE counters so we trip it each time this runs. 784fccc8c0SKees Cookif [ -w $CLEAR_ONCE ] ; then 794fccc8c0SKees Cook echo 1 > $CLEAR_ONCE 804fccc8c0SKees Cookfi 814fccc8c0SKees Cook 82f131d9edSMichael Ellerman# Save existing dmesg so we can detect new content below 83f131d9edSMichael Ellermandmesg > "$DMESG" 84f131d9edSMichael Ellerman 8504831e89SKees Cook# Since the kernel is likely killing the process writing to the trigger 8604831e89SKees Cook# file, it must not be the script's shell itself. i.e. we cannot do: 8704831e89SKees Cook# echo "$test" >"$TRIGGER" 8804831e89SKees Cook# Instead, use "cat" to take the signal. Since the shell will yell about 8904831e89SKees Cook# the signal that killed the subprocess, we must ignore the failure and 9004831e89SKees Cook# continue. However we don't silence stderr since there might be other 9104831e89SKees Cook# useful details reported there in the case of other unexpected conditions. 92*149538cdSKees Cookfor i in $(seq 1 $repeat); do 9304831e89SKees Cook echo "$test" | cat >"$TRIGGER" || true 94*149538cdSKees Cookdone 9546d1a0f0SKees Cook 9646d1a0f0SKees Cook# Record and dump the results 97d00451c8SKees Cookdmesg | comm --nocheck-order -13 "$DMESG" - > "$LOG" || true 98f131d9edSMichael Ellerman 9946d1a0f0SKees Cookcat "$LOG" 10046d1a0f0SKees Cook# Check for expected output 101851c4df5SMichael Ellermanif grep -E -qi "$expect" "$LOG" ; then 10246d1a0f0SKees Cook echo "$test: saw '$expect': ok" 10346d1a0f0SKees Cook exit 0 10446d1a0f0SKees Cookelse 105851c4df5SMichael Ellerman if grep -E -qi XFAIL: "$LOG" ; then 10646d1a0f0SKees Cook echo "$test: saw 'XFAIL': [SKIP]" 10746d1a0f0SKees Cook exit $KSELFTEST_SKIP_TEST 10846d1a0f0SKees Cook else 10946d1a0f0SKees Cook echo "$test: missing '$expect': [FAIL]" 11046d1a0f0SKees Cook exit 1 11146d1a0f0SKees Cook fi 11246d1a0f0SKees Cookfi 113