1*053f45beSAndroid Build Coastguard Worker#!/bin/sh 2*053f45beSAndroid Build Coastguard Worker# SPDX-License-Identifier: GPL-2.0 3*053f45beSAndroid Build Coastguard Worker# 4*053f45beSAndroid Build Coastguard Worker# Measure kernel stack entropy by sampling via LKDTM's REPORT_STACK test. 5*053f45beSAndroid Build Coastguard Workerset -e 6*053f45beSAndroid Build Coastguard Workersamples="${1:-1000}" 7*053f45beSAndroid Build Coastguard WorkerTRIGGER=/sys/kernel/debug/provoke-crash/DIRECT 8*053f45beSAndroid Build Coastguard WorkerKSELFTEST_SKIP_TEST=4 9*053f45beSAndroid Build Coastguard Worker 10*053f45beSAndroid Build Coastguard Worker# Verify we have LKDTM available in the kernel. 11*053f45beSAndroid Build Coastguard Workerif [ ! -r $TRIGGER ] ; then 12*053f45beSAndroid Build Coastguard Worker /sbin/modprobe -q lkdtm || true 13*053f45beSAndroid Build Coastguard Worker if [ ! -r $TRIGGER ] ; then 14*053f45beSAndroid Build Coastguard Worker echo "Cannot find $TRIGGER (missing CONFIG_LKDTM?)" 15*053f45beSAndroid Build Coastguard Worker else 16*053f45beSAndroid Build Coastguard Worker echo "Cannot write $TRIGGER (need to run as root?)" 17*053f45beSAndroid Build Coastguard Worker fi 18*053f45beSAndroid Build Coastguard Worker # Skip this test 19*053f45beSAndroid Build Coastguard Worker exit $KSELFTEST_SKIP_TEST 20*053f45beSAndroid Build Coastguard Workerfi 21*053f45beSAndroid Build Coastguard Worker 22*053f45beSAndroid Build Coastguard Worker# Capture dmesg continuously since it may fill up depending on sample size. 23*053f45beSAndroid Build Coastguard Workerlog=$(mktemp -t stack-entropy-XXXXXX) 24*053f45beSAndroid Build Coastguard Workerdmesg --follow >"$log" & pid=$! 25*053f45beSAndroid Build Coastguard Workerreport=-1 26*053f45beSAndroid Build Coastguard Workerfor i in $(seq 1 $samples); do 27*053f45beSAndroid Build Coastguard Worker echo "REPORT_STACK" > $TRIGGER 28*053f45beSAndroid Build Coastguard Worker if [ -t 1 ]; then 29*053f45beSAndroid Build Coastguard Worker percent=$(( 100 * $i / $samples )) 30*053f45beSAndroid Build Coastguard Worker if [ "$percent" -ne "$report" ]; then 31*053f45beSAndroid Build Coastguard Worker /bin/echo -en "$percent%\r" 32*053f45beSAndroid Build Coastguard Worker report="$percent" 33*053f45beSAndroid Build Coastguard Worker fi 34*053f45beSAndroid Build Coastguard Worker fi 35*053f45beSAndroid Build Coastguard Workerdone 36*053f45beSAndroid Build Coastguard Workerkill "$pid" 37*053f45beSAndroid Build Coastguard Worker 38*053f45beSAndroid Build Coastguard Worker# Count unique offsets since last run. 39*053f45beSAndroid Build Coastguard Workerseen=$(tac "$log" | grep -m1 -B"$samples"0 'Starting stack offset' | \ 40*053f45beSAndroid Build Coastguard Worker grep 'Stack offset' | awk '{print $NF}' | sort | uniq -c | wc -l) 41*053f45beSAndroid Build Coastguard Workerbits=$(echo "obase=2; $seen" | bc | wc -L) 42*053f45beSAndroid Build Coastguard Workerecho "Bits of stack entropy: $bits" 43*053f45beSAndroid Build Coastguard Workerrm -f "$log" 44*053f45beSAndroid Build Coastguard Worker 45*053f45beSAndroid Build Coastguard Worker# We would expect any functional stack randomization to be at least 5 bits. 46*053f45beSAndroid Build Coastguard Workerif [ "$bits" -lt 5 ]; then 47*053f45beSAndroid Build Coastguard Worker echo "Stack entropy is low! Booted without 'randomize_kstack_offset=y'?" 48*053f45beSAndroid Build Coastguard Worker exit 1 49*053f45beSAndroid Build Coastguard Workerelse 50*053f45beSAndroid Build Coastguard Worker exit 0 51*053f45beSAndroid Build Coastguard Workerfi 52