scs.c (51189c7a7ed1b4ed4493e27275d466ff60406d3a) scs.c (bee348fab099b0f551caa874663e82a7f3bb64b3)
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Shadow Call Stack support.
4 *
5 * Copyright (C) 2019 Google LLC
6 */
7
8#include <linux/kasan.h>
9#include <linux/mm.h>
10#include <linux/scs.h>
11#include <linux/slab.h>
12#include <linux/vmstat.h>
13#include <asm/scs.h>
14
15static struct kmem_cache *scs_cache;
16
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Shadow Call Stack support.
4 *
5 * Copyright (C) 2019 Google LLC
6 */
7
8#include <linux/kasan.h>
9#include <linux/mm.h>
10#include <linux/scs.h>
11#include <linux/slab.h>
12#include <linux/vmstat.h>
13#include <asm/scs.h>
14
15static struct kmem_cache *scs_cache;
16
17static void __scs_account(void *s, int account)
18{
19 struct page *scs_page = virt_to_page(s);
20
21 mod_zone_page_state(page_zone(scs_page), NR_KERNEL_SCS_KB,
22 account * (SCS_SIZE / SZ_1K));
23}
24
17static void *scs_alloc(int node)
18{
25static void *scs_alloc(int node)
26{
19 void *s;
27 void *s = kmem_cache_alloc_node(scs_cache, GFP_SCS, node);
20
28
21 s = kmem_cache_alloc_node(scs_cache, GFP_SCS, node);
22 if (s) {
23 *__scs_magic(s) = SCS_END_MAGIC;
24 /*
25 * Poison the allocation to catch unintentional accesses to
26 * the shadow stack when KASAN is enabled.
27 */
28 kasan_poison_object_data(scs_cache, s);
29 }
29 if (!s)
30 return NULL;
30
31
32 *__scs_magic(s) = SCS_END_MAGIC;
33
34 /*
35 * Poison the allocation to catch unintentional accesses to
36 * the shadow stack when KASAN is enabled.
37 */
38 kasan_poison_object_data(scs_cache, s);
39 __scs_account(s, 1);
31 return s;
32}
33
34static void scs_free(void *s)
35{
40 return s;
41}
42
43static void scs_free(void *s)
44{
45 __scs_account(s, -1);
36 kasan_unpoison_object_data(scs_cache, s);
37 kmem_cache_free(scs_cache, s);
38}
39
40void __init scs_init(void)
41{
42 scs_cache = kmem_cache_create("scs_cache", SCS_SIZE, 0, 0, NULL);
43}
44
46 kasan_unpoison_object_data(scs_cache, s);
47 kmem_cache_free(scs_cache, s);
48}
49
50void __init scs_init(void)
51{
52 scs_cache = kmem_cache_create("scs_cache", SCS_SIZE, 0, 0, NULL);
53}
54
45static struct page *__scs_page(struct task_struct *tsk)
46{
47 return virt_to_page(task_scs(tsk));
48}
49
50static void scs_account(struct task_struct *tsk, int account)
51{
52 mod_zone_page_state(page_zone(__scs_page(tsk)), NR_KERNEL_SCS_KB,
53 account * (SCS_SIZE / 1024));
54}
55
56int scs_prepare(struct task_struct *tsk, int node)
57{
58 void *s = scs_alloc(node);
59
60 if (!s)
61 return -ENOMEM;
62
63 task_scs(tsk) = task_scs_sp(tsk) = s;
55int scs_prepare(struct task_struct *tsk, int node)
56{
57 void *s = scs_alloc(node);
58
59 if (!s)
60 return -ENOMEM;
61
62 task_scs(tsk) = task_scs_sp(tsk) = s;
64 scs_account(tsk, 1);
65 return 0;
66}
67
68static void scs_check_usage(struct task_struct *tsk)
69{
70 static unsigned long highest;
71
72 unsigned long *p, prev, curr = highest, used = 0;

--- 24 unchanged lines hidden (view full) ---

97{
98 void *s = task_scs(tsk);
99
100 if (!s)
101 return;
102
103 WARN(scs_corrupted(tsk), "corrupted shadow stack detected when freeing task\n");
104 scs_check_usage(tsk);
63 return 0;
64}
65
66static void scs_check_usage(struct task_struct *tsk)
67{
68 static unsigned long highest;
69
70 unsigned long *p, prev, curr = highest, used = 0;

--- 24 unchanged lines hidden (view full) ---

95{
96 void *s = task_scs(tsk);
97
98 if (!s)
99 return;
100
101 WARN(scs_corrupted(tsk), "corrupted shadow stack detected when freeing task\n");
102 scs_check_usage(tsk);
105 scs_account(tsk, -1);
106 scs_free(s);
107}
103 scs_free(s);
104}