162306a36Sopenharmony_ci#!/bin/sh 262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0 362306a36Sopenharmony_ci# 462306a36Sopenharmony_ci# This reads tests.txt for the list of LKDTM tests to invoke. Any marked 562306a36Sopenharmony_ci# with a leading "#" are skipped. The rest of the line after the 662306a36Sopenharmony_ci# test name is either the text to look for in dmesg for a "success", 762306a36Sopenharmony_ci# or the rationale for why a test is marked to be skipped. 862306a36Sopenharmony_ci# 962306a36Sopenharmony_ciset -e 1062306a36Sopenharmony_ciTRIGGER=/sys/kernel/debug/provoke-crash/DIRECT 1162306a36Sopenharmony_ciCLEAR_ONCE=/sys/kernel/debug/clear_warn_once 1262306a36Sopenharmony_ciKSELFTEST_SKIP_TEST=4 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci# Verify we have LKDTM available in the kernel. 1562306a36Sopenharmony_ciif [ ! -r $TRIGGER ] ; then 1662306a36Sopenharmony_ci /sbin/modprobe -q lkdtm || true 1762306a36Sopenharmony_ci if [ ! -r $TRIGGER ] ; then 1862306a36Sopenharmony_ci echo "Cannot find $TRIGGER (missing CONFIG_LKDTM?)" 1962306a36Sopenharmony_ci else 2062306a36Sopenharmony_ci echo "Cannot write $TRIGGER (need to run as root?)" 2162306a36Sopenharmony_ci fi 2262306a36Sopenharmony_ci # Skip this test 2362306a36Sopenharmony_ci exit $KSELFTEST_SKIP_TEST 2462306a36Sopenharmony_cifi 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci# Figure out which test to run from our script name. 2762306a36Sopenharmony_citest=$(basename $0 .sh) 2862306a36Sopenharmony_ci# Look up details about the test from master list of LKDTM tests. 2962306a36Sopenharmony_ciline=$(grep -E '^#?'"$test"'\b' tests.txt) 3062306a36Sopenharmony_ciif [ -z "$line" ]; then 3162306a36Sopenharmony_ci echo "Skipped: missing test '$test' in tests.txt" 3262306a36Sopenharmony_ci exit $KSELFTEST_SKIP_TEST 3362306a36Sopenharmony_cifi 3462306a36Sopenharmony_ci# Check that the test is known to LKDTM. 3562306a36Sopenharmony_ciif ! grep -E -q '^'"$test"'$' "$TRIGGER" ; then 3662306a36Sopenharmony_ci echo "Skipped: test '$test' missing in $TRIGGER!" 3762306a36Sopenharmony_ci exit $KSELFTEST_SKIP_TEST 3862306a36Sopenharmony_cifi 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci# Extract notes/expected output from test list. 4162306a36Sopenharmony_citest=$(echo "$line" | cut -d" " -f1) 4262306a36Sopenharmony_ciif echo "$line" | grep -q ' ' ; then 4362306a36Sopenharmony_ci expect=$(echo "$line" | cut -d" " -f2-) 4462306a36Sopenharmony_cielse 4562306a36Sopenharmony_ci expect="" 4662306a36Sopenharmony_cifi 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci# If the test is commented out, report a skip 4962306a36Sopenharmony_ciif echo "$test" | grep -q '^#' ; then 5062306a36Sopenharmony_ci test=$(echo "$test" | cut -c2-) 5162306a36Sopenharmony_ci if [ -z "$expect" ]; then 5262306a36Sopenharmony_ci expect="crashes entire system" 5362306a36Sopenharmony_ci fi 5462306a36Sopenharmony_ci echo "Skipping $test: $expect" 5562306a36Sopenharmony_ci exit $KSELFTEST_SKIP_TEST 5662306a36Sopenharmony_cifi 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci# If no expected output given, assume an Oops with back trace is success. 5962306a36Sopenharmony_cirepeat=1 6062306a36Sopenharmony_ciif [ -z "$expect" ]; then 6162306a36Sopenharmony_ci expect="call trace:" 6262306a36Sopenharmony_cielse 6362306a36Sopenharmony_ci if echo "$expect" | grep -q '^repeat:' ; then 6462306a36Sopenharmony_ci repeat=$(echo "$expect" | cut -d' ' -f1 | cut -d: -f2) 6562306a36Sopenharmony_ci expect=$(echo "$expect" | cut -d' ' -f2-) 6662306a36Sopenharmony_ci fi 6762306a36Sopenharmony_cifi 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci# Prepare log for report checking 7062306a36Sopenharmony_ciLOG=$(mktemp --tmpdir -t lkdtm-log-XXXXXX) 7162306a36Sopenharmony_ciDMESG=$(mktemp --tmpdir -t lkdtm-dmesg-XXXXXX) 7262306a36Sopenharmony_cicleanup() { 7362306a36Sopenharmony_ci rm -f "$LOG" "$DMESG" 7462306a36Sopenharmony_ci} 7562306a36Sopenharmony_citrap cleanup EXIT 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci# Reset WARN_ONCE counters so we trip it each time this runs. 7862306a36Sopenharmony_ciif [ -w $CLEAR_ONCE ] ; then 7962306a36Sopenharmony_ci echo 1 > $CLEAR_ONCE 8062306a36Sopenharmony_cifi 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci# Save existing dmesg so we can detect new content below 8362306a36Sopenharmony_cidmesg > "$DMESG" 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci# Since the kernel is likely killing the process writing to the trigger 8662306a36Sopenharmony_ci# file, it must not be the script's shell itself. i.e. we cannot do: 8762306a36Sopenharmony_ci# echo "$test" >"$TRIGGER" 8862306a36Sopenharmony_ci# Instead, use "cat" to take the signal. Since the shell will yell about 8962306a36Sopenharmony_ci# the signal that killed the subprocess, we must ignore the failure and 9062306a36Sopenharmony_ci# continue. However we don't silence stderr since there might be other 9162306a36Sopenharmony_ci# useful details reported there in the case of other unexpected conditions. 9262306a36Sopenharmony_cifor i in $(seq 1 $repeat); do 9362306a36Sopenharmony_ci echo "$test" | cat >"$TRIGGER" || true 9462306a36Sopenharmony_cidone 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci# Record and dump the results 9762306a36Sopenharmony_cidmesg | comm --nocheck-order -13 "$DMESG" - > "$LOG" || true 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cicat "$LOG" 10062306a36Sopenharmony_ci# Check for expected output 10162306a36Sopenharmony_ciif grep -E -qi "$expect" "$LOG" ; then 10262306a36Sopenharmony_ci echo "$test: saw '$expect': ok" 10362306a36Sopenharmony_ci exit 0 10462306a36Sopenharmony_cielse 10562306a36Sopenharmony_ci if grep -E -qi XFAIL: "$LOG" ; then 10662306a36Sopenharmony_ci echo "$test: saw 'XFAIL': [SKIP]" 10762306a36Sopenharmony_ci exit $KSELFTEST_SKIP_TEST 10862306a36Sopenharmony_ci else 10962306a36Sopenharmony_ci echo "$test: missing '$expect': [FAIL]" 11062306a36Sopenharmony_ci exit 1 11162306a36Sopenharmony_ci fi 11262306a36Sopenharmony_cifi 113