#!/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 CLEAR_ONCE=/sys/kernel/debug/clear_warn_once 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=$(grep -E '^#?'"$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 ! grep -E -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. repeat=1 if [ -z "$expect" ]; then expect="call trace:" else if echo "$expect" | grep -q '^repeat:' ; then repeat=$(echo "$expect" | cut -d' ' -f1 | cut -d: -f2) expect=$(echo "$expect" | cut -d' ' -f2-) fi fi # Prepare log for report checking LOG=$(mktemp --tmpdir -t lkdtm-log-XXXXXX) DMESG=$(mktemp --tmpdir -t lkdtm-dmesg-XXXXXX) cleanup() { rm -f "$LOG" "$DMESG" } trap cleanup EXIT # Reset WARN_ONCE counters so we trip it each time this runs. if [ -w $CLEAR_ONCE ] ; then echo 1 > $CLEAR_ONCE fi # Save existing dmesg so we can detect new content below dmesg > "$DMESG" # Since the kernel is likely killing the process writing to the trigger # file, it must not be the script's shell itself. i.e. we cannot do: # echo "$test" >"$TRIGGER" # Instead, use "cat" to take the signal. Since the shell will yell about # the signal that killed the subprocess, we must ignore the failure and # continue. However we don't silence stderr since there might be other # useful details reported there in the case of other unexpected conditions. for i in $(seq 1 $repeat); do echo "$test" | cat >"$TRIGGER" || true done # Record and dump the results dmesg | comm --nocheck-order -13 "$DMESG" - > "$LOG" || true cat "$LOG" # Check for expected output if grep -E -qi "$expect" "$LOG" ; then echo "$test: saw '$expect': ok" exit 0 else if grep -E -qi XFAIL: "$LOG" ; then echo "$test: saw 'XFAIL': [SKIP]" exit $KSELFTEST_SKIP_TEST else echo "$test: missing '$expect': [FAIL]" exit 1 fi fi