1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
3#
4# This reads tests.txt for the list of LKDTM tests to invoke. Any marked
5# with a leading "#" are skipped. The rest of the line after the
6# test name is either the text to look for in dmesg for a "success",
7# or the rationale for why a test is marked to be skipped.
8#
9set -e
10TRIGGER=/sys/kernel/debug/provoke-crash/DIRECT
11CLEAR_ONCE=/sys/kernel/debug/clear_warn_once
12KSELFTEST_SKIP_TEST=4
13
14# Verify we have LKDTM available in the kernel.
15if [ ! -r $TRIGGER ] ; then
16	/sbin/modprobe -q lkdtm || true
17	if [ ! -r $TRIGGER ] ; then
18		echo "Cannot find $TRIGGER (missing CONFIG_LKDTM?)"
19	else
20		echo "Cannot write $TRIGGER (need to run as root?)"
21	fi
22	# Skip this test
23	exit $KSELFTEST_SKIP_TEST
24fi
25
26# Figure out which test to run from our script name.
27test=$(basename $0 .sh)
28# Look up details about the test from master list of LKDTM tests.
29line=$(grep -E '^#?'"$test"'\b' tests.txt)
30if [ -z "$line" ]; then
31	echo "Skipped: missing test '$test' in tests.txt"
32	exit $KSELFTEST_SKIP_TEST
33fi
34# Check that the test is known to LKDTM.
35if ! grep -E -q '^'"$test"'$' "$TRIGGER" ; then
36	echo "Skipped: test '$test' missing in $TRIGGER!"
37	exit $KSELFTEST_SKIP_TEST
38fi
39
40# Extract notes/expected output from test list.
41test=$(echo "$line" | cut -d" " -f1)
42if echo "$line" | grep -q ' ' ; then
43	expect=$(echo "$line" | cut -d" " -f2-)
44else
45	expect=""
46fi
47
48# If the test is commented out, report a skip
49if echo "$test" | grep -q '^#' ; then
50	test=$(echo "$test" | cut -c2-)
51	if [ -z "$expect" ]; then
52		expect="crashes entire system"
53	fi
54	echo "Skipping $test: $expect"
55	exit $KSELFTEST_SKIP_TEST
56fi
57
58# If no expected output given, assume an Oops with back trace is success.
59if [ -z "$expect" ]; then
60	expect="call trace:"
61fi
62
63# Prepare log for report checking
64LOG=$(mktemp --tmpdir -t lkdtm-log-XXXXXX)
65DMESG=$(mktemp --tmpdir -t lkdtm-dmesg-XXXXXX)
66cleanup() {
67	rm -f "$LOG" "$DMESG"
68}
69trap cleanup EXIT
70
71# Reset WARN_ONCE counters so we trip it each time this runs.
72if [ -w $CLEAR_ONCE ] ; then
73	echo 1 > $CLEAR_ONCE
74fi
75
76# Save existing dmesg so we can detect new content below
77dmesg > "$DMESG"
78
79# Since the kernel is likely killing the process writing to the trigger
80# file, it must not be the script's shell itself. i.e. we cannot do:
81#     echo "$test" >"$TRIGGER"
82# Instead, use "cat" to take the signal. Since the shell will yell about
83# the signal that killed the subprocess, we must ignore the failure and
84# continue. However we don't silence stderr since there might be other
85# useful details reported there in the case of other unexpected conditions.
86echo "$test" | cat >"$TRIGGER" || true
87
88# Record and dump the results
89dmesg | comm --nocheck-order -13 "$DMESG" - > "$LOG" || true
90
91cat "$LOG"
92# Check for expected output
93if grep -E -qi "$expect" "$LOG" ; then
94	echo "$test: saw '$expect': ok"
95	exit 0
96else
97	if grep -E -qi XFAIL: "$LOG" ; then
98		echo "$test: saw 'XFAIL': [SKIP]"
99		exit $KSELFTEST_SKIP_TEST
100	else
101		echo "$test: missing '$expect': [FAIL]"
102		exit 1
103	fi
104fi
105