1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * This code tests that the current task stack is properly erased (filled 4 * with STACKLEAK_POISON). 5 * 6 * Authors: 7 * Alexander Popov <alex.popov@linux.com> 8 * Tycho Andersen <tycho@tycho.ws> 9 */ 10 11 #include "lkdtm.h" 12 #include <linux/stackleak.h> 13 14 void lkdtm_STACKLEAK_ERASING(void) 15 { 16 unsigned long *sp, left, found, i; 17 const unsigned long check_depth = 18 STACKLEAK_SEARCH_DEPTH / sizeof(unsigned long); 19 20 /* 21 * For the details about the alignment of the poison values, see 22 * the comment in stackleak_track_stack(). 23 */ 24 sp = PTR_ALIGN(&i, sizeof(unsigned long)); 25 26 left = ((unsigned long)sp & (THREAD_SIZE - 1)) / sizeof(unsigned long); 27 sp--; 28 29 /* 30 * One 'long int' at the bottom of the thread stack is reserved 31 * and not poisoned. 32 */ 33 if (left > 1) { 34 left--; 35 } else { 36 pr_err("FAIL: not enough stack space for the test\n"); 37 return; 38 } 39 40 pr_info("checking unused part of the thread stack (%lu bytes)...\n", 41 left * sizeof(unsigned long)); 42 43 /* 44 * Search for 'check_depth' poison values in a row (just like 45 * stackleak_erase() does). 46 */ 47 for (i = 0, found = 0; i < left && found <= check_depth; i++) { 48 if (*(sp - i) == STACKLEAK_POISON) 49 found++; 50 else 51 found = 0; 52 } 53 54 if (found <= check_depth) { 55 pr_err("FAIL: thread stack is not erased (checked %lu bytes)\n", 56 i * sizeof(unsigned long)); 57 return; 58 } 59 60 pr_info("first %lu bytes are unpoisoned\n", 61 (i - found) * sizeof(unsigned long)); 62 63 /* The rest of thread stack should be erased */ 64 for (; i < left; i++) { 65 if (*(sp - i) != STACKLEAK_POISON) { 66 pr_err("FAIL: thread stack is NOT properly erased\n"); 67 return; 68 } 69 } 70 71 pr_info("OK: the rest of the thread stack is properly erased\n"); 72 return; 73 } 74