This adds several behavioral tests to sysctl string and number writing
to detect unexpected cases that behaved differently when the sysctl
kernel.sysctl_writes_strict != 1.
[ original ]
root@localhost:~# make test_num
== Testing sysctl behavior against /proc/sys/kernel/domainname ==
Writing test file ... ok
Checking sysctl is not set to test value ... ok
Writing sysctl from shell ... ok
Resetting sysctl to original value ... ok
Writing entire sysctl in single write ... ok
Writing middle of sysctl after synchronized seek ... FAIL
Writing beyond end of sysctl ... FAIL
Writing sysctl with multiple long writes ... FAIL
Writing entire sysctl in short writes ... FAIL
Writing middle of sysctl after unsynchronized seek ... ok
Checking sysctl maxlen is at least 65 ... ok
Checking sysctl keeps original string on overflow append ... FAIL
Checking sysctl stays NULL terminated on write ... ok
Checking sysctl stays NULL terminated on overwrite ... ok
make: *** [test_num] Error 1
root@localhost:~# make test_string
== Testing sysctl behavior against /proc/sys/vm/swappiness ==
Writing test file ... ok
Checking sysctl is not set to test value ... ok
Writing sysctl from shell ... ok
Resetting sysctl to original value ... ok
Writing entire sysctl in single write ... ok
Writing middle of sysctl after synchronized seek ... FAIL
Writing beyond end of sysctl ... FAIL
Writing sysctl with multiple long writes ... ok
make: *** [test_string] Error 1
[ with CONFIG_PROC_SYSCTL_STRICT_WRITES ]
root@localhost:~# make run_tests
== Testing sysctl behavior against /proc/sys/kernel/domainname ==
Writing test file ... ok
Checking sysctl is not set to test value ... ok
Writing sysctl from shell ... ok
Resetting sysctl to original value ... ok
Writing entire sysctl in single write ... ok
Writing middle of sysctl after synchronized seek ... ok
Writing beyond end of sysctl ... ok
Writing sysctl with multiple long writes ... ok
Writing entire sysctl in short writes ... ok
Writing middle of sysctl after unsynchronized seek ... ok
Checking sysctl maxlen is at least 65 ... ok
Checking sysctl keeps original string on overflow append ... ok
Checking sysctl stays NULL terminated on write ... ok
Checking sysctl stays NULL terminated on overwrite ... ok
== Testing sysctl behavior against /proc/sys/vm/swappiness ==
Writing test file ... ok
Checking sysctl is not set to test value ... ok
Writing sysctl from shell ... ok
Resetting sysctl to original value ... ok
Writing entire sysctl in single write ... ok
Writing middle of sysctl after synchronized seek ... ok
Writing beyond end of sysctl ... ok
Writing sysctl with multiple long writes ... ok
Signed-off-by: Kees Cook <keescook@chromium.org>
Cc: Randy Dunlap <rdunlap@infradead.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1.8 KiB
#!/bin/sh
TEST_FILE=$(mktemp)
echo "== Testing sysctl behavior against ${TARGET} =="
set_orig() { echo "${ORIG}" > "${TARGET}" }
set_test() { echo "${TEST_STR}" > "${TARGET}" }
verify() { local seen seen=$(cat "$1") if [ "${seen}" != "${TEST_STR}" ]; then return 1 fi return 0 }
trap 'set_orig; rm -f "${TEST_FILE}"' EXIT
rc=0
echo -n "Writing test file ... " echo "${TEST_STR}" > "${TEST_FILE}" if ! verify "${TEST_FILE}"; then echo "FAIL" >&2 exit 1 else echo "ok" fi
echo -n "Checking sysctl is not set to test value ... " if verify "${TARGET}"; then echo "FAIL" >&2 exit 1 else echo "ok" fi
echo -n "Writing sysctl from shell ... " set_test if ! verify "${TARGET}"; then echo "FAIL" >&2 exit 1 else echo "ok" fi
echo -n "Resetting sysctl to original value ... " set_orig if verify "${TARGET}"; then echo "FAIL" >&2 exit 1 else echo "ok" fi
Now that we've validated the sanity of "set_test" and "set_orig",
we can use those functions to set starting states before running
specific behavioral tests.
echo -n "Writing entire sysctl in single write ... " set_orig dd if="${TEST_FILE}" of="${TARGET}" bs=4096 2>/dev/null if ! verify "${TARGET}"; then echo "FAIL" >&2 rc=1 else echo "ok" fi
echo -n "Writing middle of sysctl after synchronized seek ... " set_test dd if="${TEST_FILE}" of="${TARGET}" bs=1 seek=1 skip=1 2>/dev/null if ! verify "${TARGET}"; then echo "FAIL" >&2 rc=1 else echo "ok" fi
echo -n "Writing beyond end of sysctl ... " set_orig dd if="${TEST_FILE}" of="${TARGET}" bs=20 seek=2 2>/dev/null if verify "${TARGET}"; then echo "FAIL" >&2 rc=1 else echo "ok" fi
echo -n "Writing sysctl with multiple long writes ... "
set_orig
(perl -e 'print "A" x 50;'; echo "${TEST_STR}") |
dd of="${TARGET}" bs=50 2>/dev/null
if verify "${TARGET}"; then
echo "FAIL" >&2
rc=1
else
echo "ok"
fi