| #!/bin/sh |
| # SPDX-License-Identifier: GPL-2.0 |
| # |
| # Measure kernel stack entropy by sampling via LKDTM's REPORT_STACK test. |
| set -e |
| samples="${1:-1000}" |
| TRIGGER=/sys/kernel/debug/provoke-crash/DIRECT |
| KSELFTEST_SKIP_TEST=4 |
| |
| # Verify we have LKDTM available in the kernel. |
| if [ ! -r $TRIGGER ] ; then |
| /sbin/modprobe -q lkdtm || true |
| if [ ! -r $TRIGGER ] ; then |
| echo "Cannot find $TRIGGER (missing CONFIG_LKDTM?)" |
| else |
| echo "Cannot write $TRIGGER (need to run as root?)" |
| fi |
| # Skip this test |
| exit $KSELFTEST_SKIP_TEST |
| fi |
| |
| # Capture dmesg continuously since it may fill up depending on sample size. |
| log=$(mktemp -t stack-entropy-XXXXXX) |
| dmesg --follow >"$log" & pid=$! |
| report=-1 |
| for i in $(seq 1 $samples); do |
| echo "REPORT_STACK" > $TRIGGER |
| if [ -t 1 ]; then |
| percent=$(( 100 * $i / $samples )) |
| if [ "$percent" -ne "$report" ]; then |
| /bin/echo -en "$percent%\r" |
| report="$percent" |
| fi |
| fi |
| done |
| kill "$pid" |
| |
| # Count unique offsets since last run. |
| seen=$(tac "$log" | grep -m1 -B"$samples"0 'Starting stack offset' | \ |
| grep 'Stack offset' | awk '{print $NF}' | sort | uniq -c | wc -l) |
| bits=$(echo "obase=2; $seen" | bc | wc -L) |
| echo "Bits of stack entropy: $bits" |
| rm -f "$log" |
| |
| # We would expect any functional stack randomization to be at least 5 bits. |
| if [ "$bits" -lt 5 ]; then |
| echo "Stack entropy is low! Booted without 'randomize_kstack_offset=y'?" |
| exit 1 |
| else |
| exit 0 |
| fi |