File Index
Files and directories
Sign in
FILE

sysctl.sh

File preview with syntax highlighting.

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