// SPDX-License-Identifier: GPL-2.0 /* * This code tests that the current task stack is properly erased (filled * with KSTACK_ERASE_POISON). * * Authors: * Alexander Popov <alex.popov@linux.com> * Tycho Andersen <tycho@tycho.ws>
*/
#include"lkdtm.h" #include <linux/kstack_erase.h>
#ifdefined(CONFIG_KSTACK_ERASE) /* * Check that stackleak tracks the lowest stack pointer and erases the stack * below this as expected. * * To prevent the lowest stack pointer changing during the test, IRQs are * masked and instrumentation of this function is disabled. We assume that the * compiler will create a fixed-size stack frame for this function. * * Any non-inlined function may make further use of the stack, altering the * lowest stack pointer and/or clobbering poison values. To avoid spurious * failures we must avoid printing until the end of the test or have already * encountered a failure condition.
*/ staticvoid noinstr check_stackleak_irqoff(void)
{ constunsignedlong task_stack_base = (unsignedlong)task_stack_page(current); constunsignedlong task_stack_low = stackleak_task_low_bound(current); constunsignedlong task_stack_high = stackleak_task_high_bound(current); constunsignedlong current_sp = current_stack_pointer; constunsignedlong lowest_sp = current->lowest_stack; unsignedlong untracked_high; unsignedlong poison_high, poison_low; bool test_failed = false;
/* * Check that the current and lowest recorded stack pointer values fall * within the expected task stack boundaries. These tests should never * fail unless the boundaries are incorrect or we're clobbering the * STACK_END_MAGIC, and in either casee something is seriously wrong.
*/ if (current_sp < task_stack_low || current_sp >= task_stack_high) {
instrumentation_begin();
pr_err("FAIL: current_stack_pointer (0x%lx) outside of task stack bounds [0x%lx..0x%lx]\n",
current_sp, task_stack_low, task_stack_high - 1);
test_failed = true; goto out;
} if (lowest_sp < task_stack_low || lowest_sp >= task_stack_high) {
instrumentation_begin();
pr_err("FAIL: current->lowest_stack (0x%lx) outside of task stack bounds [0x%lx..0x%lx]\n",
lowest_sp, task_stack_low, task_stack_high - 1);
test_failed = true; goto out;
}
/* * Depending on what has run prior to this test, the lowest recorded * stack pointer could be above or below the current stack pointer. * Start from the lowest of the two. * * Poison values are naturally-aligned unsigned longs. As the current * stack pointer might not be sufficiently aligned, we must align * downwards to find the lowest known stack pointer value. This is the * high boundary for a portion of the stack which may have been used * without being tracked, and has to be scanned for poison.
*/
untracked_high = min(current_sp, lowest_sp);
untracked_high = ALIGN_DOWN(untracked_high, sizeof(unsignedlong));
/* * Find the top of the poison in the same way as the erasing code.
*/
poison_high = stackleak_find_top_of_poison(task_stack_low, untracked_high);
/* * Check whether the poisoned portion of the stack (if any) consists * entirely of poison. This verifies the entries that * stackleak_find_top_of_poison() should have checked.
*/
poison_low = poison_high; while (poison_low > task_stack_low) {
poison_low -= sizeof(unsignedlong);
if (*(unsignedlong *)poison_low == KSTACK_ERASE_POISON) continue;
out: if (test_failed) {
pr_err("FAIL: the thread stack is NOT properly erased!\n");
} else {
pr_info("OK: the rest of the thread stack is properly erased\n");
}
instrumentation_end();
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.