1 // SPDX-License-Identifier: GPL-2.0
3 * Shadow Call Stack support.
5 * Copyright (C) 2019 Google LLC
8 #include <linux/kasan.h>
10 #include <linux/scs.h>
11 #include <linux/slab.h>
12 #include <linux/vmstat.h>
14 static struct kmem_cache
*scs_cache
;
16 static void __scs_account(void *s
, int account
)
18 struct page
*scs_page
= virt_to_page(s
);
20 mod_zone_page_state(page_zone(scs_page
), NR_KERNEL_SCS_KB
,
21 account
* (SCS_SIZE
/ SZ_1K
));
24 static void *scs_alloc(int node
)
26 void *s
= kmem_cache_alloc_node(scs_cache
, GFP_SCS
, node
);
31 *__scs_magic(s
) = SCS_END_MAGIC
;
34 * Poison the allocation to catch unintentional accesses to
35 * the shadow stack when KASAN is enabled.
37 kasan_poison_object_data(scs_cache
, s
);
42 static void scs_free(void *s
)
45 kasan_unpoison_object_data(scs_cache
, s
);
46 kmem_cache_free(scs_cache
, s
);
49 void __init
scs_init(void)
51 scs_cache
= kmem_cache_create("scs_cache", SCS_SIZE
, 0, 0, NULL
);
54 int scs_prepare(struct task_struct
*tsk
, int node
)
56 void *s
= scs_alloc(node
);
61 task_scs(tsk
) = task_scs_sp(tsk
) = s
;
65 static void scs_check_usage(struct task_struct
*tsk
)
67 static unsigned long highest
;
69 unsigned long *p
, prev
, curr
= highest
, used
= 0;
71 if (!IS_ENABLED(CONFIG_DEBUG_STACK_USAGE
))
74 for (p
= task_scs(tsk
); p
< __scs_magic(tsk
); ++p
) {
75 if (!READ_ONCE_NOCHECK(*p
))
81 prev
= cmpxchg_relaxed(&highest
, curr
, used
);
84 pr_info("%s (%d): highest shadow stack usage: %lu bytes\n",
85 tsk
->comm
, task_pid_nr(tsk
), used
);
93 void scs_release(struct task_struct
*tsk
)
95 void *s
= task_scs(tsk
);
100 WARN(task_scs_end_corrupted(tsk
),
101 "corrupted shadow stack detected when freeing task\n");
102 scs_check_usage(tsk
);