xref: /linux/tools/testing/selftests/lkdtm/run.sh (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
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