Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/livepatch: fix and refactor new dmesg message code

The livepatching kselftests rely on comparing expected vs. observed
dmesg output. After each test, new dmesg entries are determined by the
'comm' utility comparing a saved, pre-test copy of dmesg to post-test
dmesg output.

Alexander reports that the 'comm --nocheck-order -13' invocation used by
the tests can be confused when dmesg entry timestamps vary in magnitude
(ie, "[ 98.820331]" vs. "[ 100.031067]"), in which case, additional
messages are reported as new. The unexpected entries then spoil the
test results.

Instead of relying on 'comm' or 'diff' to determine new testing dmesg
entries, refactor the code:

- pre-test : log a unique canary dmesg entry
- test : run tests, log messages
- post-test : filter dmesg starting from pre-test message

Reported-by: Alexander Gordeev <agordeev@linux.ibm.com>
Closes: https://lore.kernel.org/live-patching/ZYAimyPYhxVA9wKg@li-008a6a4c-3549-11b2-a85c-c5cc2836eea2.ibm.com/
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
Acked-by: Alexander Gordeev <agordeev@linux.ibm.com>
Tested-by: Marcos Paulo de Souza <mpdesouza@suse.com>
Reviewed-by: Marcos Paulo de Souza <mpdesouza@suse.com>
Acked-by: Miroslav Benes <mbenes@suse.cz>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>

authored by

Joe Lawrence and committed by
Shuah Khan
f1fea725 d53271c0

+17 -20
+17 -20
tools/testing/selftests/livepatch/functions.sh
··· 42 42 exit 1 43 43 } 44 44 45 - # save existing dmesg so we can detect new content 46 - function save_dmesg() { 47 - SAVED_DMESG=$(mktemp --tmpdir -t klp-dmesg-XXXXXX) 48 - dmesg > "$SAVED_DMESG" 49 - } 50 - 51 - # cleanup temporary dmesg file from save_dmesg() 52 - function cleanup_dmesg_file() { 53 - rm -f "$SAVED_DMESG" 54 - } 55 - 56 45 function push_config() { 57 46 DYNAMIC_DEBUG=$(grep '^kernel/livepatch' /sys/kernel/debug/dynamic_debug/control | \ 58 47 awk -F'[: ]' '{print "file " $1 " line " $2 " " $4}') ··· 88 99 89 100 function cleanup() { 90 101 pop_config 91 - cleanup_dmesg_file 92 102 } 93 103 94 104 # setup_config - save the current config and set a script exit trap that ··· 268 280 function start_test { 269 281 local test="$1" 270 282 271 - save_dmesg 283 + # Dump something unique into the dmesg log, then stash the entry 284 + # in LAST_DMESG. The check_result() function will use it to 285 + # find new kernel messages since the test started. 286 + local last_dmesg_msg="livepatch kselftest timestamp: $(date --rfc-3339=ns)" 287 + log "$last_dmesg_msg" 288 + loop_until 'dmesg | grep -q "$last_dmesg_msg"' || 289 + die "buffer busy? can't find canary dmesg message: $last_dmesg_msg" 290 + LAST_DMESG=$(dmesg | grep "$last_dmesg_msg") 291 + 272 292 echo -n "TEST: $test ... " 273 293 log "===== TEST: $test =====" 274 294 } ··· 287 291 local expect="$*" 288 292 local result 289 293 290 - # Note: when comparing dmesg output, the kernel log timestamps 291 - # help differentiate repeated testing runs. Remove them with a 292 - # post-comparison sed filter. 293 - 294 - result=$(dmesg | comm --nocheck-order -13 "$SAVED_DMESG" - | \ 294 + # Test results include any new dmesg entry since LAST_DMESG, then: 295 + # - include lines matching keywords 296 + # - exclude lines matching keywords 297 + # - filter out dmesg timestamp prefixes 298 + result=$(dmesg | awk -v last_dmesg="$LAST_DMESG" 'p; $0 == last_dmesg { p=1 }' | \ 295 299 grep -e 'livepatch:' -e 'test_klp' | \ 296 300 grep -v '\(tainting\|taints\) kernel' | \ 297 301 sed 's/^\[[ 0-9.]*\] //') 298 302 299 303 if [[ "$expect" == "$result" ]] ; then 300 304 echo "ok" 305 + elif [[ "$result" == "" ]] ; then 306 + echo -e "not ok\n\nbuffer overrun? can't find canary dmesg entry: $LAST_DMESG\n" 307 + die "livepatch kselftest(s) failed" 301 308 else 302 309 echo -e "not ok\n\n$(diff -upr --label expected --label result <(echo "$expect") <(echo "$result"))\n" 303 310 die "livepatch kselftest(s) failed" 304 311 fi 305 - 306 - cleanup_dmesg_file 307 312 } 308 313 309 314 # check_sysfs_rights(modname, rel_path, expected_rights) - check sysfs