18c2ecf20Sopenharmony_ci#!/bin/sh
28c2ecf20Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0
38c2ecf20Sopenharmony_ci#
48c2ecf20Sopenharmony_ci# This reads tests.txt for the list of LKDTM tests to invoke. Any marked
58c2ecf20Sopenharmony_ci# with a leading "#" are skipped. The rest of the line after the
68c2ecf20Sopenharmony_ci# test name is either the text to look for in dmesg for a "success",
78c2ecf20Sopenharmony_ci# or the rationale for why a test is marked to be skipped.
88c2ecf20Sopenharmony_ci#
98c2ecf20Sopenharmony_ciset -e
108c2ecf20Sopenharmony_ciTRIGGER=/sys/kernel/debug/provoke-crash/DIRECT
118c2ecf20Sopenharmony_ciCLEAR_ONCE=/sys/kernel/debug/clear_warn_once
128c2ecf20Sopenharmony_ciKSELFTEST_SKIP_TEST=4
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci# Verify we have LKDTM available in the kernel.
158c2ecf20Sopenharmony_ciif [ ! -r $TRIGGER ] ; then
168c2ecf20Sopenharmony_ci	/sbin/modprobe -q lkdtm || true
178c2ecf20Sopenharmony_ci	if [ ! -r $TRIGGER ] ; then
188c2ecf20Sopenharmony_ci		echo "Cannot find $TRIGGER (missing CONFIG_LKDTM?)"
198c2ecf20Sopenharmony_ci	else
208c2ecf20Sopenharmony_ci		echo "Cannot write $TRIGGER (need to run as root?)"
218c2ecf20Sopenharmony_ci	fi
228c2ecf20Sopenharmony_ci	# Skip this test
238c2ecf20Sopenharmony_ci	exit $KSELFTEST_SKIP_TEST
248c2ecf20Sopenharmony_cifi
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci# Figure out which test to run from our script name.
278c2ecf20Sopenharmony_citest=$(basename $0 .sh)
288c2ecf20Sopenharmony_ci# Look up details about the test from master list of LKDTM tests.
298c2ecf20Sopenharmony_ciline=$(grep -E '^#?'"$test"'\b' tests.txt)
308c2ecf20Sopenharmony_ciif [ -z "$line" ]; then
318c2ecf20Sopenharmony_ci	echo "Skipped: missing test '$test' in tests.txt"
328c2ecf20Sopenharmony_ci	exit $KSELFTEST_SKIP_TEST
338c2ecf20Sopenharmony_cifi
348c2ecf20Sopenharmony_ci# Check that the test is known to LKDTM.
358c2ecf20Sopenharmony_ciif ! grep -E -q '^'"$test"'$' "$TRIGGER" ; then
368c2ecf20Sopenharmony_ci	echo "Skipped: test '$test' missing in $TRIGGER!"
378c2ecf20Sopenharmony_ci	exit $KSELFTEST_SKIP_TEST
388c2ecf20Sopenharmony_cifi
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci# Extract notes/expected output from test list.
418c2ecf20Sopenharmony_citest=$(echo "$line" | cut -d" " -f1)
428c2ecf20Sopenharmony_ciif echo "$line" | grep -q ' ' ; then
438c2ecf20Sopenharmony_ci	expect=$(echo "$line" | cut -d" " -f2-)
448c2ecf20Sopenharmony_cielse
458c2ecf20Sopenharmony_ci	expect=""
468c2ecf20Sopenharmony_cifi
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci# If the test is commented out, report a skip
498c2ecf20Sopenharmony_ciif echo "$test" | grep -q '^#' ; then
508c2ecf20Sopenharmony_ci	test=$(echo "$test" | cut -c2-)
518c2ecf20Sopenharmony_ci	if [ -z "$expect" ]; then
528c2ecf20Sopenharmony_ci		expect="crashes entire system"
538c2ecf20Sopenharmony_ci	fi
548c2ecf20Sopenharmony_ci	echo "Skipping $test: $expect"
558c2ecf20Sopenharmony_ci	exit $KSELFTEST_SKIP_TEST
568c2ecf20Sopenharmony_cifi
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci# If no expected output given, assume an Oops with back trace is success.
598c2ecf20Sopenharmony_ciif [ -z "$expect" ]; then
608c2ecf20Sopenharmony_ci	expect="call trace:"
618c2ecf20Sopenharmony_cifi
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci# Prepare log for report checking
648c2ecf20Sopenharmony_ciLOG=$(mktemp --tmpdir -t lkdtm-log-XXXXXX)
658c2ecf20Sopenharmony_ciDMESG=$(mktemp --tmpdir -t lkdtm-dmesg-XXXXXX)
668c2ecf20Sopenharmony_cicleanup() {
678c2ecf20Sopenharmony_ci	rm -f "$LOG" "$DMESG"
688c2ecf20Sopenharmony_ci}
698c2ecf20Sopenharmony_citrap cleanup EXIT
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci# Reset WARN_ONCE counters so we trip it each time this runs.
728c2ecf20Sopenharmony_ciif [ -w $CLEAR_ONCE ] ; then
738c2ecf20Sopenharmony_ci	echo 1 > $CLEAR_ONCE
748c2ecf20Sopenharmony_cifi
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci# Save existing dmesg so we can detect new content below
778c2ecf20Sopenharmony_cidmesg > "$DMESG"
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci# Since the kernel is likely killing the process writing to the trigger
808c2ecf20Sopenharmony_ci# file, it must not be the script's shell itself. i.e. we cannot do:
818c2ecf20Sopenharmony_ci#     echo "$test" >"$TRIGGER"
828c2ecf20Sopenharmony_ci# Instead, use "cat" to take the signal. Since the shell will yell about
838c2ecf20Sopenharmony_ci# the signal that killed the subprocess, we must ignore the failure and
848c2ecf20Sopenharmony_ci# continue. However we don't silence stderr since there might be other
858c2ecf20Sopenharmony_ci# useful details reported there in the case of other unexpected conditions.
868c2ecf20Sopenharmony_ciecho "$test" | cat >"$TRIGGER" || true
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci# Record and dump the results
898c2ecf20Sopenharmony_cidmesg | comm --nocheck-order -13 "$DMESG" - > "$LOG" || true
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cicat "$LOG"
928c2ecf20Sopenharmony_ci# Check for expected output
938c2ecf20Sopenharmony_ciif grep -E -qi "$expect" "$LOG" ; then
948c2ecf20Sopenharmony_ci	echo "$test: saw '$expect': ok"
958c2ecf20Sopenharmony_ci	exit 0
968c2ecf20Sopenharmony_cielse
978c2ecf20Sopenharmony_ci	if grep -E -qi XFAIL: "$LOG" ; then
988c2ecf20Sopenharmony_ci		echo "$test: saw 'XFAIL': [SKIP]"
998c2ecf20Sopenharmony_ci		exit $KSELFTEST_SKIP_TEST
1008c2ecf20Sopenharmony_ci	else
1018c2ecf20Sopenharmony_ci		echo "$test: missing '$expect': [FAIL]"
1028c2ecf20Sopenharmony_ci		exit 1
1038c2ecf20Sopenharmony_ci	fi
1048c2ecf20Sopenharmony_cifi
105