cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

stackleak.h (2144B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2#ifndef _LINUX_STACKLEAK_H
      3#define _LINUX_STACKLEAK_H
      4
      5#include <linux/sched.h>
      6#include <linux/sched/task_stack.h>
      7
      8/*
      9 * Check that the poison value points to the unused hole in the
     10 * virtual memory map for your platform.
     11 */
     12#define STACKLEAK_POISON -0xBEEF
     13#define STACKLEAK_SEARCH_DEPTH 128
     14
     15#ifdef CONFIG_GCC_PLUGIN_STACKLEAK
     16#include <asm/stacktrace.h>
     17
     18/*
     19 * The lowest address on tsk's stack which we can plausibly erase.
     20 */
     21static __always_inline unsigned long
     22stackleak_task_low_bound(const struct task_struct *tsk)
     23{
     24	/*
     25	 * The lowest unsigned long on the task stack contains STACK_END_MAGIC,
     26	 * which we must not corrupt.
     27	 */
     28	return (unsigned long)end_of_stack(tsk) + sizeof(unsigned long);
     29}
     30
     31/*
     32 * The address immediately after the highest address on tsk's stack which we
     33 * can plausibly erase.
     34 */
     35static __always_inline unsigned long
     36stackleak_task_high_bound(const struct task_struct *tsk)
     37{
     38	/*
     39	 * The task's pt_regs lives at the top of the task stack and will be
     40	 * overwritten by exception entry, so there's no need to erase them.
     41	 */
     42	return (unsigned long)task_pt_regs(tsk);
     43}
     44
     45/*
     46 * Find the address immediately above the poisoned region of the stack, where
     47 * that region falls between 'low' (inclusive) and 'high' (exclusive).
     48 */
     49static __always_inline unsigned long
     50stackleak_find_top_of_poison(const unsigned long low, const unsigned long high)
     51{
     52	const unsigned int depth = STACKLEAK_SEARCH_DEPTH / sizeof(unsigned long);
     53	unsigned int poison_count = 0;
     54	unsigned long poison_high = high;
     55	unsigned long sp = high;
     56
     57	while (sp > low && poison_count < depth) {
     58		sp -= sizeof(unsigned long);
     59
     60		if (*(unsigned long *)sp == STACKLEAK_POISON) {
     61			poison_count++;
     62		} else {
     63			poison_count = 0;
     64			poison_high = sp;
     65		}
     66	}
     67
     68	return poison_high;
     69}
     70
     71static inline void stackleak_task_init(struct task_struct *t)
     72{
     73	t->lowest_stack = stackleak_task_low_bound(t);
     74# ifdef CONFIG_STACKLEAK_METRICS
     75	t->prev_lowest_stack = t->lowest_stack;
     76# endif
     77}
     78
     79#else /* !CONFIG_GCC_PLUGIN_STACKLEAK */
     80static inline void stackleak_task_init(struct task_struct *t) { }
     81#endif
     82
     83#endif