Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider: - [High] Time-of-Check to Time-of-Use (TOCTOU) vulnerability due to deleting and appending to securely created temporary files. - [Medium] The test script swallows the actual command error output and prints an undefined variable. - [Medium] Cryptographic hash verification of core kernel files makes the selftest overly brittle. - [Medium] The silent soft-pass mode (`K=2`) does not exit successfully as documented, falling through to a failure. - [Medium] The `LACK_DD_BUILTIN` filter in `GOLDEN_RECORDS` is broken because it queries a non-existent 4th column. - [Low] The strict-mode environment variable `K` is used in arithmetic evaluations without sanitization. - [Low] The `ifrmmod` function is identically defined twice in the script. --
commit 21ef8019906e22cad30ff587de97850e4985eee2 Author: Jim Cromie <[email protected]> selftests/dyndbg: Add kselftest script to verify dynamic-debug Adds a kselftest script to attempt full validation of dynamic-debug behavior. The script tests query grammar as documented, responses to bad input, and proper/expected effects on both the control-file display of current state, and on pr_debug logging behavior using a hash-based verification mechanism. > diff --git a/tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh > b/tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh > new file mode 100755 > index 0000000000000..67b568730acc6 > --- /dev/null > +++ b/tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh > @@ -0,0 +1,770 @@ > +#!/bin/bash > +# SPDX-License-Identifier: GPL-2.0-only > + > +# Standard kselftest exit codes > +ksft_pass=0 > +ksft_fail=1 > +ksft_skip=4 > + > +ESC=$'\033' > +RED="${ESC}[0;31m" > +GREEN="${ESC}[0;32m" > +YELLOW="${ESC}[0;33m" > +BLUE="${ESC}[0;34m" > +MAGENTA="${ESC}[0;35m" > +CYAN="${ESC}[0;36m" > +NC="${ESC}[0;0m" > +# Environment Controls: > +# V=0,1,2 : Verbosity (0=concise summary, 1=verified assertions, 2=full > captured outputs) > +# K=0 : Strict mode (fails with exit 1 on checksum drift or stale > records) > +# K=1 : Soft-pass mode (prints DRIFT/STALE diffs, exits 0 with 'fake > success') > +# K=2 : Silent soft-pass mode (suppresses DRIFT/STALE diffs, exits 0 > with 'fake success') > +V=${V:=0} > +K=${K:=0} > + > +# Sanitize V to ensure it is a valid integer > +if [[ ! "$V" =~ ^[0-9]+$ ]]; then [Severity: Low] Is there a reason the K variable is not sanitized here similarly to V? If a non-numeric string is provided for K, bash will throw an "integer expression expected" error when it evaluates K in arithmetic conditions later in the script. [ ... ] > +function ifrmmod { > + [ "${LACK_TMOD:-0}" -eq 1 ] && return > + grep -q "^$1 " /proc/modules 2>/dev/null && rmmod $1 > +} > + > +# Clean up any leftover loaded test modules at initialization > +ifrmmod test_dynamic_debug_submod > +ifrmmod test_dynamic_debug [ ... ] > +function ifrmmod { > + [ "${LACK_TMOD:-0}" -eq 1 ] && return > + grep -q "^$1 " /proc/modules 2>/dev/null && rmmod $1 > +} [Severity: Low] Does this function need to be re-declared here? It appears to be an exact duplicate of the ifrmmod definition from earlier in the script. [ ... ] > +function ddcmd () { > + # ddcmd <query_args> [range_pattern] [pass|fail|log] > + local args="$1" > + local range="$2" > + local action="${3:-pass}" > + local exp_exit=0 > + > + [ "$action" = "fail" ] && exp_exit=1 > + log_ddcmd "$args" > + > + # Update cumulative state-machine lineage > + if [[ "$args" == *"=_"* ]]; then > + CUMULATIVE_DDCMDS="$args" > + else > + CUMULATIVE_DDCMDS="${CUMULATIVE_DDCMDS}; $args" > + fi > + > + [ "$action" != "pass" ] && log_start > + [ -n "$range" ] && capture_before "$range" > + > + output=$( (echo "$args" > /proc/dynamic_debug/control) 2>&1 ) > + handle_exit_code $BASH_LINENO $FUNCNAME $? $exp_exit [ ... ] > +function handle_exit_code() { > + local exp_exit_code=0 > + [ $# == 4 ] && exp_exit_code=$4 > + if [ "$3" -ne $exp_exit_code ]; then > + echo -e "${RED}: $BASH_SOURCE:$1 $2() " \ > + "expected to exit with code $exp_exit_code, got $3${NC}" > + [ "$3" == 1 ] && echo "Error: '$error_msg'" [Severity: Medium] Is error_msg defined anywhere? It seems ddcmd captures the command output and errors into the "output" variable, but handle_exit_code tries to print an undeclared error_msg variable. This causes the script to print "Error: ''", swallowing the actual error context needed for debugging test failures. [ ... ] > +function FT_basic_queries { > + v_echo "${GREEN}# BASIC_TESTS ${NC}" > + if [ $LACK_DD_BUILTIN -eq 1 ]; then > + echo "SKIP - test requires params, which is a builtin module" > + return > + fi > + ddcmd =_ # zero everything > + > + ddcmd "module params +mf" 'kernel/params.c' > + ddcmd "module params +l" 'kernel/params.c' [Severity: Medium] Does hashing the exact output string representations of pr_debug statements in core files make the test unnecessarily brittle? Any routine upstream modification to the format strings or logic in kernel/params.c will unconditionally invalidate the static hash baselines here, causing CI failures even if the dynamic debug subsystem is functioning perfectly. [ ... ] > +function GOLDEN_RECORDS { > + cat << 'EOF' | { [ ... ] > +#K= de950a3e60669fdd58d0a8c2867a056d FT_basic_queries.5 > +#K= 2ff49f0c4d18ec99bcb1c30840fe8afc FT_basic_queries.6 > +#K= 9a1b13c32a15363dcf93913308edeea5 FT_basic_queries.7 > +EOF > + # Read the K-recs and skip those for tests that can't run > + while read -r line; do > + # Filter built-in if needed > + if [ "${LACK_DD_BUILTIN:-0}" -eq 1 ]; then > + # Extract pattern (4th field) from #K= line > + local pattern=$(echo "$line" | awk '{print $4}') > + if [[ "$pattern" == *params* || "$pattern" == *main* ]]; then [Severity: Medium] Is this correctly filtering the built-in test records? The lines mapped in GOLDEN_RECORDS only contain 3 columns (e.g., "#K= <hash> <label>"). Because there is no 4th column, the pattern variable will always be empty, causing the filter to fail and allowing built-in tests to incorrectly execute on unsupported configurations. [ ... ] > +# Clear any stale seen/unregistered/drifted hashes from previous runs > +rm -f "$SEEN_HASHES_FILE" "$UNREG_HASHES_FILE" "$DRIFT_HASHES_FILE" [Severity: High] Could removing these temporary files introduce a local privilege escalation or arbitrary file overwrite vulnerability? These files are securely created by mktemp earlier, but explicitly removing them before the test runs means that when the script appends to them later (e.g., echo "$fingerprint" >> "$SEEN_HASHES_FILE"), bash will implicitly recreate them without O_EXCL protection. An attacker monitoring the temporary directory could create a symlink with the deleted file's name before the script runs the append redirection, allowing them to overwrite arbitrary files when the test executes as root. [ ... ] > +if [ -s "$DRIFT_HASHES_FILE" ]; then > + echo -e "${RED}\n# --- Drifted Baselines ---" > + cat "$DRIFT_HASHES_FILE" > + echo -e "# -------------------------${NC}" > + rm -f "$DRIFT_HASHES_FILE" > + failed=1 > +fi > + > +# Cleanup > +rm -f "$UNREG_HASHES_FILE" "$DRIFT_HASHES_FILE" > + > +if [ $failed -eq 1 ]; then > + [ "$K" -eq 1 ] && echo "fake success" && exit $ksft_pass > + exit $ksft_fail > +fi [Severity: Medium] Does this logic correctly handle the silent soft-pass mode (K=2)? If "failed" is 1 and K is 2, the check for K=1 fails and the script falls through to exit with $ksft_fail. This causes the test to fail instead of returning success as documented for K=2. -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=1
