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

lkdtm: Add REPORT_STACK for checking stack offsets

For validating the stack offset behavior, report the offset from a given
process's first seen stack address. Add s script to calculate the results
to the LKDTM kselftests.

Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/20210401232347.2791257-7-keescook@chromium.org

authored by

Kees Cook and committed by
Thomas Gleixner
68ef8735 fe950f60

+57
+17
drivers/misc/lkdtm/bugs.c
··· 134 134 __lkdtm_CORRUPT_STACK((void *)&data); 135 135 } 136 136 137 + static pid_t stack_pid; 138 + static unsigned long stack_addr; 139 + 140 + void lkdtm_REPORT_STACK(void) 141 + { 142 + volatile uintptr_t magic; 143 + pid_t pid = task_pid_nr(current); 144 + 145 + if (pid != stack_pid) { 146 + pr_info("Starting stack offset tracking for pid %d\n", pid); 147 + stack_pid = pid; 148 + stack_addr = (uintptr_t)&magic; 149 + } 150 + 151 + pr_info("Stack offset: %d\n", (int)(stack_addr - (uintptr_t)&magic)); 152 + } 153 + 137 154 void lkdtm_UNALIGNED_LOAD_STORE_WRITE(void) 138 155 { 139 156 static u8 data[5] __attribute__((aligned(4))) = {1, 2, 3, 4, 5};
+1
drivers/misc/lkdtm/core.c
··· 110 110 CRASHTYPE(EXHAUST_STACK), 111 111 CRASHTYPE(CORRUPT_STACK), 112 112 CRASHTYPE(CORRUPT_STACK_STRONG), 113 + CRASHTYPE(REPORT_STACK), 113 114 CRASHTYPE(CORRUPT_LIST_ADD), 114 115 CRASHTYPE(CORRUPT_LIST_DEL), 115 116 CRASHTYPE(STACK_GUARD_PAGE_LEADING),
+1
drivers/misc/lkdtm/lkdtm.h
··· 17 17 void lkdtm_EXHAUST_STACK(void); 18 18 void lkdtm_CORRUPT_STACK(void); 19 19 void lkdtm_CORRUPT_STACK_STRONG(void); 20 + void lkdtm_REPORT_STACK(void); 20 21 void lkdtm_UNALIGNED_LOAD_STORE_WRITE(void); 21 22 void lkdtm_SOFTLOCKUP(void); 22 23 void lkdtm_HARDLOCKUP(void);
+1
tools/testing/selftests/lkdtm/.gitignore
··· 1 1 *.sh 2 2 !run.sh 3 + !stack-entropy.sh
+1
tools/testing/selftests/lkdtm/Makefile
··· 5 5 6 6 # NOTE: $(OUTPUT) won't get default value if used before lib.mk 7 7 TEST_FILES := tests.txt 8 + TEST_PROGS := stack-entropy.sh 8 9 TEST_GEN_PROGS = $(patsubst %,$(OUTPUT)/%.sh,$(shell awk '{print $$1}' tests.txt | sed -e 's/\#//')) 9 10 all: $(TEST_GEN_PROGS) 10 11
+36
tools/testing/selftests/lkdtm/stack-entropy.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0 3 + # 4 + # Measure kernel stack entropy by sampling via LKDTM's REPORT_STACK test. 5 + set -e 6 + samples="${1:-1000}" 7 + 8 + # Capture dmesg continuously since it may fill up depending on sample size. 9 + log=$(mktemp -t stack-entropy-XXXXXX) 10 + dmesg --follow >"$log" & pid=$! 11 + report=-1 12 + for i in $(seq 1 $samples); do 13 + echo "REPORT_STACK" >/sys/kernel/debug/provoke-crash/DIRECT 14 + if [ -t 1 ]; then 15 + percent=$(( 100 * $i / $samples )) 16 + if [ "$percent" -ne "$report" ]; then 17 + /bin/echo -en "$percent%\r" 18 + report="$percent" 19 + fi 20 + fi 21 + done 22 + kill "$pid" 23 + 24 + # Count unique offsets since last run. 25 + seen=$(tac "$log" | grep -m1 -B"$samples"0 'Starting stack offset' | \ 26 + grep 'Stack offset' | awk '{print $NF}' | sort | uniq -c | wc -l) 27 + bits=$(echo "obase=2; $seen" | bc | wc -L) 28 + echo "Bits of stack entropy: $bits" 29 + rm -f "$log" 30 + 31 + # We would expect any functional stack randomization to be at least 5 bits. 32 + if [ "$bits" -lt 5 ]; then 33 + exit 1 34 + else 35 + exit 0 36 + fi