cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sysctl.sh (20596B)


      1#!/bin/bash
      2# Copyright (C) 2017 Luis R. Rodriguez <mcgrof@kernel.org>
      3#
      4# This program is free software; you can redistribute it and/or modify it
      5# under the terms of the GNU General Public License as published by the Free
      6# Software Foundation; either version 2 of the License, or at your option any
      7# later version; or, when distributed separately from the Linux kernel or
      8# when incorporated into other software packages, subject to the following
      9# license:
     10#
     11# This program is free software; you can redistribute it and/or modify it
     12# under the terms of copyleft-next (version 0.3.1 or later) as published
     13# at http://copyleft-next.org/.
     14
     15# This performs a series tests against the proc sysctl interface.
     16
     17# Kselftest framework requirement - SKIP code is 4.
     18ksft_skip=4
     19
     20TEST_NAME="sysctl"
     21TEST_DRIVER="test_${TEST_NAME}"
     22TEST_DIR=$(dirname $0)
     23TEST_FILE=$(mktemp)
     24
     25# This represents
     26#
     27# TEST_ID:TEST_COUNT:ENABLED:TARGET
     28#
     29# TEST_ID: is the test id number
     30# TEST_COUNT: number of times we should run the test
     31# ENABLED: 1 if enabled, 0 otherwise
     32# TARGET: test target file required on the test_sysctl module
     33#
     34# Once these are enabled please leave them as-is. Write your own test,
     35# we have tons of space.
     36ALL_TESTS="0001:1:1:int_0001"
     37ALL_TESTS="$ALL_TESTS 0002:1:1:string_0001"
     38ALL_TESTS="$ALL_TESTS 0003:1:1:int_0002"
     39ALL_TESTS="$ALL_TESTS 0004:1:1:uint_0001"
     40ALL_TESTS="$ALL_TESTS 0005:3:1:int_0003"
     41ALL_TESTS="$ALL_TESTS 0006:50:1:bitmap_0001"
     42ALL_TESTS="$ALL_TESTS 0007:1:1:boot_int"
     43ALL_TESTS="$ALL_TESTS 0008:1:1:match_int"
     44
     45function allow_user_defaults()
     46{
     47	if [ -z $DIR ]; then
     48		DIR="/sys/module/test_sysctl/"
     49	fi
     50	if [ -z $DEFAULT_NUM_TESTS ]; then
     51		DEFAULT_NUM_TESTS=50
     52	fi
     53	if [ -z $SYSCTL ]; then
     54		SYSCTL="/proc/sys/debug/test_sysctl"
     55	fi
     56	if [ -z $PROD_SYSCTL ]; then
     57		PROD_SYSCTL="/proc/sys"
     58	fi
     59	if [ -z $WRITES_STRICT ]; then
     60		WRITES_STRICT="${PROD_SYSCTL}/kernel/sysctl_writes_strict"
     61	fi
     62}
     63
     64function check_production_sysctl_writes_strict()
     65{
     66	echo -n "Checking production write strict setting ... "
     67	if [ ! -e ${WRITES_STRICT} ]; then
     68		echo "FAIL, but skip in case of old kernel" >&2
     69	else
     70		old_strict=$(cat ${WRITES_STRICT})
     71		if [ "$old_strict" = "1" ]; then
     72			echo "ok"
     73		else
     74			echo "FAIL, strict value is 0 but force to 1 to continue" >&2
     75			echo "1" > ${WRITES_STRICT}
     76		fi
     77	fi
     78
     79	if [ -z $PAGE_SIZE ]; then
     80		PAGE_SIZE=$(getconf PAGESIZE)
     81	fi
     82	if [ -z $MAX_DIGITS ]; then
     83		MAX_DIGITS=$(($PAGE_SIZE/8))
     84	fi
     85	if [ -z $INT_MAX ]; then
     86		INT_MAX=$(getconf INT_MAX)
     87	fi
     88	if [ -z $UINT_MAX ]; then
     89		UINT_MAX=$(getconf UINT_MAX)
     90	fi
     91}
     92
     93test_reqs()
     94{
     95	uid=$(id -u)
     96	if [ $uid -ne 0 ]; then
     97		echo $msg must be run as root >&2
     98		exit $ksft_skip
     99	fi
    100
    101	if ! which perl 2> /dev/null > /dev/null; then
    102		echo "$0: You need perl installed"
    103		exit $ksft_skip
    104	fi
    105	if ! which getconf 2> /dev/null > /dev/null; then
    106		echo "$0: You need getconf installed"
    107		exit $ksft_skip
    108	fi
    109	if ! which diff 2> /dev/null > /dev/null; then
    110		echo "$0: You need diff installed"
    111		exit $ksft_skip
    112	fi
    113}
    114
    115function load_req_mod()
    116{
    117	if [ ! -d $SYSCTL ]; then
    118		if ! modprobe -q -n $TEST_DRIVER; then
    119			echo "$0: module $TEST_DRIVER not found [SKIP]"
    120			echo "You must set CONFIG_TEST_SYSCTL=m in your kernel" >&2
    121			exit $ksft_skip
    122		fi
    123		modprobe $TEST_DRIVER
    124		if [ $? -ne 0 ]; then
    125			echo "$0: modprobe $TEST_DRIVER failed."
    126			exit
    127		fi
    128	fi
    129}
    130
    131reset_vals()
    132{
    133	VAL=""
    134	TRIGGER=$(basename ${TARGET})
    135	case "$TRIGGER" in
    136		int_0001)
    137			VAL="60"
    138			;;
    139		int_0002)
    140			VAL="1"
    141			;;
    142		uint_0001)
    143			VAL="314"
    144			;;
    145		string_0001)
    146			VAL="(none)"
    147			;;
    148		bitmap_0001)
    149			VAL=""
    150			;;
    151		*)
    152			;;
    153	esac
    154	echo -n $VAL > $TARGET
    155}
    156
    157set_orig()
    158{
    159	if [ ! -z $TARGET ] && [ ! -z $ORIG ]; then
    160		if [ -f ${TARGET} ]; then
    161			echo "${ORIG}" > "${TARGET}"
    162		fi
    163	fi
    164}
    165
    166set_test()
    167{
    168	echo "${TEST_STR}" > "${TARGET}"
    169}
    170
    171verify()
    172{
    173	local seen
    174	seen=$(cat "$1")
    175	if [ "${seen}" != "${TEST_STR}" ]; then
    176		return 1
    177	fi
    178	return 0
    179}
    180
    181# proc files get read a page at a time, which can confuse diff,
    182# and get you incorrect results on proc files with long data. To use
    183# diff against them you must first extract the output to a file, and
    184# then compare against that file.
    185verify_diff_proc_file()
    186{
    187	TMP_DUMP_FILE=$(mktemp)
    188	cat $1 > $TMP_DUMP_FILE
    189
    190	if ! diff -w -q $TMP_DUMP_FILE $2; then
    191		return 1
    192	else
    193		return 0
    194	fi
    195}
    196
    197verify_diff_w()
    198{
    199	echo "$TEST_STR" | diff -q -w -u - $1 > /dev/null
    200	return $?
    201}
    202
    203test_rc()
    204{
    205	if [[ $rc != 0 ]]; then
    206		echo "Failed test, return value: $rc" >&2
    207		exit $rc
    208	fi
    209}
    210
    211test_finish()
    212{
    213	set_orig
    214	rm -f "${TEST_FILE}"
    215
    216	if [ ! -z ${old_strict} ]; then
    217		echo ${old_strict} > ${WRITES_STRICT}
    218	fi
    219	exit $rc
    220}
    221
    222run_numerictests()
    223{
    224	echo "== Testing sysctl behavior against ${TARGET} =="
    225
    226	rc=0
    227
    228	echo -n "Writing test file ... "
    229	echo "${TEST_STR}" > "${TEST_FILE}"
    230	if ! verify "${TEST_FILE}"; then
    231		echo "FAIL" >&2
    232		exit 1
    233	else
    234		echo "ok"
    235	fi
    236
    237	echo -n "Checking sysctl is not set to test value ... "
    238	if verify "${TARGET}"; then
    239		echo "FAIL" >&2
    240		exit 1
    241	else
    242		echo "ok"
    243	fi
    244
    245	echo -n "Writing sysctl from shell ... "
    246	set_test
    247	if ! verify "${TARGET}"; then
    248		echo "FAIL" >&2
    249		exit 1
    250	else
    251		echo "ok"
    252	fi
    253
    254	echo -n "Resetting sysctl to original value ... "
    255	set_orig
    256	if verify "${TARGET}"; then
    257		echo "FAIL" >&2
    258		exit 1
    259	else
    260		echo "ok"
    261	fi
    262
    263	# Now that we've validated the sanity of "set_test" and "set_orig",
    264	# we can use those functions to set starting states before running
    265	# specific behavioral tests.
    266
    267	echo -n "Writing entire sysctl in single write ... "
    268	set_orig
    269	dd if="${TEST_FILE}" of="${TARGET}" bs=4096 2>/dev/null
    270	if ! verify "${TARGET}"; then
    271		echo "FAIL" >&2
    272		rc=1
    273	else
    274		echo "ok"
    275	fi
    276
    277	echo -n "Writing middle of sysctl after synchronized seek ... "
    278	set_test
    279	dd if="${TEST_FILE}" of="${TARGET}" bs=1 seek=1 skip=1 2>/dev/null
    280	if ! verify "${TARGET}"; then
    281		echo "FAIL" >&2
    282		rc=1
    283	else
    284		echo "ok"
    285	fi
    286
    287	echo -n "Writing beyond end of sysctl ... "
    288	set_orig
    289	dd if="${TEST_FILE}" of="${TARGET}" bs=20 seek=2 2>/dev/null
    290	if verify "${TARGET}"; then
    291		echo "FAIL" >&2
    292		rc=1
    293	else
    294		echo "ok"
    295	fi
    296
    297	echo -n "Writing sysctl with multiple long writes ... "
    298	set_orig
    299	(perl -e 'print "A" x 50;'; echo "${TEST_STR}") | \
    300		dd of="${TARGET}" bs=50 2>/dev/null
    301	if verify "${TARGET}"; then
    302		echo "FAIL" >&2
    303		rc=1
    304	else
    305		echo "ok"
    306	fi
    307	test_rc
    308}
    309
    310check_failure()
    311{
    312	echo -n "Testing that $1 fails as expected..."
    313	reset_vals
    314	TEST_STR="$1"
    315	orig="$(cat $TARGET)"
    316	echo -n "$TEST_STR" > $TARGET 2> /dev/null
    317
    318	# write should fail and $TARGET should retain its original value
    319	if [ $? = 0 ] || [ "$(cat $TARGET)" != "$orig" ]; then
    320		echo "FAIL" >&2
    321		rc=1
    322	else
    323		echo "ok"
    324	fi
    325	test_rc
    326}
    327
    328run_wideint_tests()
    329{
    330	# sysctl conversion functions receive a boolean sign and ulong
    331	# magnitude; here we list the magnitudes we want to test (each of
    332	# which will be tested in both positive and negative forms).  Since
    333	# none of these values fit in 32 bits, writing them to an int- or
    334	# uint-typed sysctl should fail.
    335	local magnitudes=(
    336		# common boundary-condition values (zero, +1, -1, INT_MIN,
    337		# and INT_MAX respectively) if truncated to lower 32 bits
    338		# (potential for being falsely deemed in range)
    339		0x0000000100000000
    340		0x0000000100000001
    341		0x00000001ffffffff
    342		0x0000000180000000
    343		0x000000017fffffff
    344
    345		# these look like negatives, but without a leading '-' are
    346		# actually large positives (should be rejected as above
    347		# despite being zero/+1/-1/INT_MIN/INT_MAX in the lower 32)
    348		0xffffffff00000000
    349		0xffffffff00000001
    350		0xffffffffffffffff
    351		0xffffffff80000000
    352		0xffffffff7fffffff
    353	)
    354
    355	for sign in '' '-'; do
    356		for mag in "${magnitudes[@]}"; do
    357			check_failure "${sign}${mag}"
    358		done
    359	done
    360}
    361
    362# Your test must accept digits 3 and 4 to use this
    363run_limit_digit()
    364{
    365	echo -n "Checking ignoring spaces up to PAGE_SIZE works on write ..."
    366	reset_vals
    367
    368	LIMIT=$((MAX_DIGITS -1))
    369	TEST_STR="3"
    370	(perl -e 'print " " x '$LIMIT';'; echo "${TEST_STR}") | \
    371		dd of="${TARGET}" 2>/dev/null
    372
    373	if ! verify "${TARGET}"; then
    374		echo "FAIL" >&2
    375		rc=1
    376	else
    377		echo "ok"
    378	fi
    379	test_rc
    380
    381	echo -n "Checking passing PAGE_SIZE of spaces fails on write ..."
    382	reset_vals
    383
    384	LIMIT=$((MAX_DIGITS))
    385	TEST_STR="4"
    386	(perl -e 'print " " x '$LIMIT';'; echo "${TEST_STR}") | \
    387		dd of="${TARGET}" 2>/dev/null
    388
    389	if verify "${TARGET}"; then
    390		echo "FAIL" >&2
    391		rc=1
    392	else
    393		echo "ok"
    394	fi
    395	test_rc
    396}
    397
    398# You are using an int
    399run_limit_digit_int()
    400{
    401	echo -n "Testing INT_MAX works ..."
    402	reset_vals
    403	TEST_STR="$INT_MAX"
    404	echo -n $TEST_STR > $TARGET
    405
    406	if ! verify "${TARGET}"; then
    407		echo "FAIL" >&2
    408		rc=1
    409	else
    410		echo "ok"
    411	fi
    412	test_rc
    413
    414	echo -n "Testing INT_MAX + 1 will fail as expected..."
    415	reset_vals
    416	let TEST_STR=$INT_MAX+1
    417	echo -n $TEST_STR > $TARGET 2> /dev/null
    418
    419	if verify "${TARGET}"; then
    420		echo "FAIL" >&2
    421		rc=1
    422	else
    423		echo "ok"
    424	fi
    425	test_rc
    426
    427	echo -n "Testing negative values will work as expected..."
    428	reset_vals
    429	TEST_STR="-3"
    430	echo -n $TEST_STR > $TARGET 2> /dev/null
    431	if ! verify "${TARGET}"; then
    432		echo "FAIL" >&2
    433		rc=1
    434	else
    435		echo "ok"
    436	fi
    437	test_rc
    438}
    439
    440# You used an int array
    441run_limit_digit_int_array()
    442{
    443	echo -n "Testing array works as expected ... "
    444	TEST_STR="4 3 2 1"
    445	echo -n $TEST_STR > $TARGET
    446
    447	if ! verify_diff_w "${TARGET}"; then
    448		echo "FAIL" >&2
    449		rc=1
    450	else
    451		echo "ok"
    452	fi
    453	test_rc
    454
    455	echo -n "Testing skipping trailing array elements works ... "
    456	# Do not reset_vals, carry on the values from the last test.
    457	# If we only echo in two digits the last two are left intact
    458	TEST_STR="100 101"
    459	echo -n $TEST_STR > $TARGET
    460	# After we echo in, to help diff we need to set on TEST_STR what
    461	# we expect the result to be.
    462	TEST_STR="100 101 2 1"
    463
    464	if ! verify_diff_w "${TARGET}"; then
    465		echo "FAIL" >&2
    466		rc=1
    467	else
    468		echo "ok"
    469	fi
    470	test_rc
    471
    472	echo -n "Testing PAGE_SIZE limit on array works ... "
    473	# Do not reset_vals, carry on the values from the last test.
    474	# Even if you use an int array, you are still restricted to
    475	# MAX_DIGITS, this is a known limitation. Test limit works.
    476	LIMIT=$((MAX_DIGITS -1))
    477	TEST_STR="9"
    478	(perl -e 'print " " x '$LIMIT';'; echo "${TEST_STR}") | \
    479		dd of="${TARGET}" 2>/dev/null
    480
    481	TEST_STR="9 101 2 1"
    482	if ! verify_diff_w "${TARGET}"; then
    483		echo "FAIL" >&2
    484		rc=1
    485	else
    486		echo "ok"
    487	fi
    488	test_rc
    489
    490	echo -n "Testing exceeding PAGE_SIZE limit fails as expected ... "
    491	# Do not reset_vals, carry on the values from the last test.
    492	# Now go over limit.
    493	LIMIT=$((MAX_DIGITS))
    494	TEST_STR="7"
    495	(perl -e 'print " " x '$LIMIT';'; echo "${TEST_STR}") | \
    496		dd of="${TARGET}" 2>/dev/null
    497
    498	TEST_STR="7 101 2 1"
    499	if verify_diff_w "${TARGET}"; then
    500		echo "FAIL" >&2
    501		rc=1
    502	else
    503		echo "ok"
    504	fi
    505	test_rc
    506}
    507
    508# You are using an unsigned int
    509run_limit_digit_uint()
    510{
    511	echo -n "Testing UINT_MAX works ..."
    512	reset_vals
    513	TEST_STR="$UINT_MAX"
    514	echo -n $TEST_STR > $TARGET
    515
    516	if ! verify "${TARGET}"; then
    517		echo "FAIL" >&2
    518		rc=1
    519	else
    520		echo "ok"
    521	fi
    522	test_rc
    523
    524	echo -n "Testing UINT_MAX + 1 will fail as expected..."
    525	reset_vals
    526	TEST_STR=$(($UINT_MAX+1))
    527	echo -n $TEST_STR > $TARGET 2> /dev/null
    528
    529	if verify "${TARGET}"; then
    530		echo "FAIL" >&2
    531		rc=1
    532	else
    533		echo "ok"
    534	fi
    535	test_rc
    536
    537	echo -n "Testing negative values will not work as expected ..."
    538	reset_vals
    539	TEST_STR="-3"
    540	echo -n $TEST_STR > $TARGET 2> /dev/null
    541
    542	if verify "${TARGET}"; then
    543		echo "FAIL" >&2
    544		rc=1
    545	else
    546		echo "ok"
    547	fi
    548	test_rc
    549}
    550
    551run_stringtests()
    552{
    553	echo -n "Writing entire sysctl in short writes ... "
    554	set_orig
    555	dd if="${TEST_FILE}" of="${TARGET}" bs=1 2>/dev/null
    556	if ! verify "${TARGET}"; then
    557		echo "FAIL" >&2
    558		rc=1
    559	else
    560		echo "ok"
    561	fi
    562
    563	echo -n "Writing middle of sysctl after unsynchronized seek ... "
    564	set_test
    565	dd if="${TEST_FILE}" of="${TARGET}" bs=1 seek=1 2>/dev/null
    566	if verify "${TARGET}"; then
    567		echo "FAIL" >&2
    568		rc=1
    569	else
    570		echo "ok"
    571	fi
    572
    573	echo -n "Checking sysctl maxlen is at least $MAXLEN ... "
    574	set_orig
    575	perl -e 'print "A" x ('"${MAXLEN}"'-2), "B";' | \
    576		dd of="${TARGET}" bs="${MAXLEN}" 2>/dev/null
    577	if ! grep -q B "${TARGET}"; then
    578		echo "FAIL" >&2
    579		rc=1
    580	else
    581		echo "ok"
    582	fi
    583
    584	echo -n "Checking sysctl keeps original string on overflow append ... "
    585	set_orig
    586	perl -e 'print "A" x ('"${MAXLEN}"'-1), "B";' | \
    587		dd of="${TARGET}" bs=$(( MAXLEN - 1 )) 2>/dev/null
    588	if grep -q B "${TARGET}"; then
    589		echo "FAIL" >&2
    590		rc=1
    591	else
    592		echo "ok"
    593	fi
    594
    595	echo -n "Checking sysctl stays NULL terminated on write ... "
    596	set_orig
    597	perl -e 'print "A" x ('"${MAXLEN}"'-1), "B";' | \
    598		dd of="${TARGET}" bs="${MAXLEN}" 2>/dev/null
    599	if grep -q B "${TARGET}"; then
    600		echo "FAIL" >&2
    601		rc=1
    602	else
    603		echo "ok"
    604	fi
    605
    606	echo -n "Checking sysctl stays NULL terminated on overwrite ... "
    607	set_orig
    608	perl -e 'print "A" x ('"${MAXLEN}"'-1), "BB";' | \
    609		dd of="${TARGET}" bs=$(( $MAXLEN + 1 )) 2>/dev/null
    610	if grep -q B "${TARGET}"; then
    611		echo "FAIL" >&2
    612		rc=1
    613	else
    614		echo "ok"
    615	fi
    616
    617	test_rc
    618}
    619
    620target_exists()
    621{
    622	TARGET="${SYSCTL}/$1"
    623	TEST_ID="$2"
    624
    625	if [ ! -f ${TARGET} ] ; then
    626		echo "Target for test $TEST_ID: $TARGET not exist, skipping test ..."
    627		return 0
    628	fi
    629	return 1
    630}
    631
    632run_bitmaptest() {
    633	# Total length of bitmaps string to use, a bit under
    634	# the maximum input size of the test node
    635	LENGTH=$((RANDOM % 65000))
    636
    637	# First bit to set
    638	BIT=$((RANDOM % 1024))
    639
    640	# String containing our list of bits to set
    641	TEST_STR=$BIT
    642
    643	# build up the string
    644	while [ "${#TEST_STR}" -le "$LENGTH" ]; do
    645		# Make sure next entry is discontiguous,
    646		# skip ahead at least 2
    647		BIT=$((BIT + $((2 + RANDOM % 10))))
    648
    649		# Add new bit to the list
    650		TEST_STR="${TEST_STR},${BIT}"
    651
    652		# Randomly make it a range
    653		if [ "$((RANDOM % 2))" -eq "1" ]; then
    654			RANGE_END=$((BIT + $((1 + RANDOM % 10))))
    655			TEST_STR="${TEST_STR}-${RANGE_END}"
    656			BIT=$RANGE_END
    657		fi
    658	done
    659
    660	echo -n "Checking bitmap handler... "
    661	TEST_FILE=$(mktemp)
    662	echo -n "$TEST_STR" > $TEST_FILE
    663
    664	cat $TEST_FILE > $TARGET 2> /dev/null
    665	if [ $? -ne 0 ]; then
    666		echo "FAIL" >&2
    667		rc=1
    668		test_rc
    669	fi
    670
    671	if ! verify_diff_proc_file "$TARGET" "$TEST_FILE"; then
    672		echo "FAIL" >&2
    673		rc=1
    674	else
    675		echo "ok"
    676		rc=0
    677	fi
    678	test_rc
    679}
    680
    681sysctl_test_0001()
    682{
    683	TARGET="${SYSCTL}/$(get_test_target 0001)"
    684	reset_vals
    685	ORIG=$(cat "${TARGET}")
    686	TEST_STR=$(( $ORIG + 1 ))
    687
    688	run_numerictests
    689	run_wideint_tests
    690	run_limit_digit
    691}
    692
    693sysctl_test_0002()
    694{
    695	TARGET="${SYSCTL}/$(get_test_target 0002)"
    696	reset_vals
    697	ORIG=$(cat "${TARGET}")
    698	TEST_STR="Testing sysctl"
    699	# Only string sysctls support seeking/appending.
    700	MAXLEN=65
    701
    702	run_numerictests
    703	run_stringtests
    704}
    705
    706sysctl_test_0003()
    707{
    708	TARGET="${SYSCTL}/$(get_test_target 0003)"
    709	reset_vals
    710	ORIG=$(cat "${TARGET}")
    711	TEST_STR=$(( $ORIG + 1 ))
    712
    713	run_numerictests
    714	run_wideint_tests
    715	run_limit_digit
    716	run_limit_digit_int
    717}
    718
    719sysctl_test_0004()
    720{
    721	TARGET="${SYSCTL}/$(get_test_target 0004)"
    722	reset_vals
    723	ORIG=$(cat "${TARGET}")
    724	TEST_STR=$(( $ORIG + 1 ))
    725
    726	run_numerictests
    727	run_wideint_tests
    728	run_limit_digit
    729	run_limit_digit_uint
    730}
    731
    732sysctl_test_0005()
    733{
    734	TARGET="${SYSCTL}/$(get_test_target 0005)"
    735	reset_vals
    736	ORIG=$(cat "${TARGET}")
    737
    738	run_limit_digit_int_array
    739}
    740
    741sysctl_test_0006()
    742{
    743	TARGET="${SYSCTL}/bitmap_0001"
    744	reset_vals
    745	ORIG=""
    746	run_bitmaptest
    747}
    748
    749sysctl_test_0007()
    750{
    751	TARGET="${SYSCTL}/boot_int"
    752	if [ ! -f $TARGET ]; then
    753		echo "Skipping test for $TARGET as it is not present ..."
    754		return $ksft_skip
    755	fi
    756
    757	if [ -d $DIR ]; then
    758		echo "Boot param test only possible sysctl_test is built-in, not module:"
    759		cat $TEST_DIR/config >&2
    760		return $ksft_skip
    761	fi
    762
    763	echo -n "Testing if $TARGET is set to 1 ..."
    764	ORIG=$(cat "${TARGET}")
    765
    766	if [ x$ORIG = "x1" ]; then
    767		echo "ok"
    768		return 0
    769	fi
    770	echo "FAIL"
    771	echo "Checking if /proc/cmdline contains setting of the expected parameter ..."
    772	if [ ! -f /proc/cmdline ]; then
    773		echo "/proc/cmdline does not exist, test inconclusive"
    774		return 0
    775	fi
    776
    777	FOUND=$(grep -c "sysctl[./]debug[./]test_sysctl[./]boot_int=1" /proc/cmdline)
    778	if [ $FOUND = "1" ]; then
    779		echo "Kernel param found but $TARGET is not 1, TEST FAILED"
    780		rc=1
    781		test_rc
    782	fi
    783
    784	echo "Skipping test, expected kernel parameter missing."
    785	echo "To perform this test, make sure kernel is booted with parameter: sysctl.debug.test_sysctl.boot_int=1"
    786	return $ksft_skip
    787}
    788
    789sysctl_test_0008()
    790{
    791	TARGET="${SYSCTL}/match_int"
    792	if [ ! -f $TARGET ]; then
    793		echo "Skipping test for $TARGET as it is not present ..."
    794		return $ksft_skip
    795	fi
    796
    797	echo -n "Testing if $TARGET is matched in kernel"
    798	ORIG_VALUE=$(cat "${TARGET}")
    799
    800	if [ $ORIG_VALUE -ne 1 ]; then
    801		echo "TEST FAILED"
    802		rc=1
    803		test_rc
    804	fi
    805
    806	echo "ok"
    807	return 0
    808}
    809
    810list_tests()
    811{
    812	echo "Test ID list:"
    813	echo
    814	echo "TEST_ID x NUM_TEST"
    815	echo "TEST_ID:   Test ID"
    816	echo "NUM_TESTS: Number of recommended times to run the test"
    817	echo
    818	echo "0001 x $(get_test_count 0001) - tests proc_dointvec_minmax()"
    819	echo "0002 x $(get_test_count 0002) - tests proc_dostring()"
    820	echo "0003 x $(get_test_count 0003) - tests proc_dointvec()"
    821	echo "0004 x $(get_test_count 0004) - tests proc_douintvec()"
    822	echo "0005 x $(get_test_count 0005) - tests proc_douintvec() array"
    823	echo "0006 x $(get_test_count 0006) - tests proc_do_large_bitmap()"
    824	echo "0007 x $(get_test_count 0007) - tests setting sysctl from kernel boot param"
    825	echo "0008 x $(get_test_count 0008) - tests sysctl macro values match"
    826}
    827
    828usage()
    829{
    830	NUM_TESTS=$(grep -o ' ' <<<"$ALL_TESTS" | grep -c .)
    831	let NUM_TESTS=$NUM_TESTS+1
    832	MAX_TEST=$(printf "%04d\n" $NUM_TESTS)
    833	echo "Usage: $0 [ -t <4-number-digit> ] | [ -w <4-number-digit> ] |"
    834	echo "		 [ -s <4-number-digit> ] | [ -c <4-number-digit> <test- count>"
    835	echo "           [ all ] [ -h | --help ] [ -l ]"
    836	echo ""
    837	echo "Valid tests: 0001-$MAX_TEST"
    838	echo ""
    839	echo "    all     Runs all tests (default)"
    840	echo "    -t      Run test ID the number amount of times is recommended"
    841	echo "    -w      Watch test ID run until it runs into an error"
    842	echo "    -c      Run test ID once"
    843	echo "    -s      Run test ID x test-count number of times"
    844	echo "    -l      List all test ID list"
    845	echo " -h|--help  Help"
    846	echo
    847	echo "If an error every occurs execution will immediately terminate."
    848	echo "If you are adding a new test try using -w <test-ID> first to"
    849	echo "make sure the test passes a series of tests."
    850	echo
    851	echo Example uses:
    852	echo
    853	echo "$TEST_NAME.sh            -- executes all tests"
    854	echo "$TEST_NAME.sh -t 0002    -- Executes test ID 0002 number of times is recomended"
    855	echo "$TEST_NAME.sh -w 0002    -- Watch test ID 0002 run until an error occurs"
    856	echo "$TEST_NAME.sh -s 0002    -- Run test ID 0002 once"
    857	echo "$TEST_NAME.sh -c 0002 3  -- Run test ID 0002 three times"
    858	echo
    859	list_tests
    860	exit 1
    861}
    862
    863function test_num()
    864{
    865	re='^[0-9]+$'
    866	if ! [[ $1 =~ $re ]]; then
    867		usage
    868	fi
    869}
    870
    871function get_test_count()
    872{
    873	test_num $1
    874	TEST_DATA=$(echo $ALL_TESTS | awk '{print $'$1'}')
    875	echo ${TEST_DATA} | awk -F":" '{print $2}'
    876}
    877
    878function get_test_enabled()
    879{
    880	test_num $1
    881	TEST_DATA=$(echo $ALL_TESTS | awk '{print $'$1'}')
    882	echo ${TEST_DATA} | awk -F":" '{print $3}'
    883}
    884
    885function get_test_target()
    886{
    887	test_num $1
    888	TEST_DATA=$(echo $ALL_TESTS | awk '{print $'$1'}')
    889	echo ${TEST_DATA} | awk -F":" '{print $4}'
    890}
    891
    892function run_all_tests()
    893{
    894	for i in $ALL_TESTS ; do
    895		TEST_ID=${i%:*:*:*}
    896		ENABLED=$(get_test_enabled $TEST_ID)
    897		TEST_COUNT=$(get_test_count $TEST_ID)
    898		TEST_TARGET=$(get_test_target $TEST_ID)
    899		if target_exists $TEST_TARGET $TEST_ID; then
    900			continue
    901		fi
    902		if [[ $ENABLED -eq "1" ]]; then
    903			test_case $TEST_ID $TEST_COUNT $TEST_TARGET
    904		fi
    905	done
    906}
    907
    908function watch_log()
    909{
    910	if [ $# -ne 3 ]; then
    911		clear
    912	fi
    913	date
    914	echo "Running test: $2 - run #$1"
    915}
    916
    917function watch_case()
    918{
    919	i=0
    920	while [ 1 ]; do
    921
    922		if [ $# -eq 1 ]; then
    923			test_num $1
    924			watch_log $i ${TEST_NAME}_test_$1
    925			${TEST_NAME}_test_$1
    926		else
    927			watch_log $i all
    928			run_all_tests
    929		fi
    930		let i=$i+1
    931	done
    932}
    933
    934function test_case()
    935{
    936	NUM_TESTS=$2
    937
    938	i=0
    939
    940	if target_exists $3 $1; then
    941		continue
    942	fi
    943
    944	while [ $i -lt $NUM_TESTS ]; do
    945		test_num $1
    946		watch_log $i ${TEST_NAME}_test_$1 noclear
    947		RUN_TEST=${TEST_NAME}_test_$1
    948		$RUN_TEST
    949		let i=$i+1
    950	done
    951}
    952
    953function parse_args()
    954{
    955	if [ $# -eq 0 ]; then
    956		run_all_tests
    957	else
    958		if [[ "$1" = "all" ]]; then
    959			run_all_tests
    960		elif [[ "$1" = "-w" ]]; then
    961			shift
    962			watch_case $@
    963		elif [[ "$1" = "-t" ]]; then
    964			shift
    965			test_num $1
    966			test_case $1 $(get_test_count $1) $(get_test_target $1)
    967		elif [[ "$1" = "-c" ]]; then
    968			shift
    969			test_num $1
    970			test_num $2
    971			test_case $1 $2 $(get_test_target $1)
    972		elif [[ "$1" = "-s" ]]; then
    973			shift
    974			test_case $1 1 $(get_test_target $1)
    975		elif [[ "$1" = "-l" ]]; then
    976			list_tests
    977		elif [[ "$1" = "-h" || "$1" = "--help" ]]; then
    978			usage
    979		else
    980			usage
    981		fi
    982	fi
    983}
    984
    985test_reqs
    986allow_user_defaults
    987check_production_sysctl_writes_strict
    988load_req_mod
    989
    990trap "test_finish" EXIT
    991
    992parse_args $@
    993
    994exit 0