Merge branch 'cpufreq-scpi'
[linux-2.6-block.git] / drivers / misc / lkdtm_heap.c
CommitLineData
b2441318 1// SPDX-License-Identifier: GPL-2.0
ffc514f3
KC
2/*
3 * This is for all the tests relating directly to heap memory, including
4 * page allocation and slab allocations.
5 */
ffc514f3 6#include "lkdtm.h"
6d2e91a6 7#include <linux/slab.h>
5b825c3a 8#include <linux/sched.h>
ffc514f3
KC
9
10/*
11 * This tries to stay within the next largest power-of-2 kmalloc cache
12 * to avoid actually overwriting anything important if it's not detected
13 * correctly.
14 */
15void lkdtm_OVERWRITE_ALLOCATION(void)
16{
17 size_t len = 1020;
18 u32 *data = kmalloc(len, GFP_KERNEL);
02543a4e
VG
19 if (!data)
20 return;
ffc514f3
KC
21
22 data[1024 / sizeof(u32)] = 0x12345678;
23 kfree(data);
24}
25
26void lkdtm_WRITE_AFTER_FREE(void)
27{
28 int *base, *again;
29 size_t len = 1024;
30 /*
31 * The slub allocator uses the first word to store the free
32 * pointer in some configurations. Use the middle of the
33 * allocation to avoid running into the freelist
34 */
35 size_t offset = (len / sizeof(*base)) / 2;
36
37 base = kmalloc(len, GFP_KERNEL);
02543a4e
VG
38 if (!base)
39 return;
ffc514f3
KC
40 pr_info("Allocated memory %p-%p\n", base, &base[offset * 2]);
41 pr_info("Attempting bad write to freed memory at %p\n",
42 &base[offset]);
43 kfree(base);
44 base[offset] = 0x0abcdef0;
45 /* Attempt to notice the overwrite. */
46 again = kmalloc(len, GFP_KERNEL);
47 kfree(again);
48 if (again != base)
49 pr_info("Hmm, didn't get the same memory range.\n");
50}
51
52void lkdtm_READ_AFTER_FREE(void)
53{
54 int *base, *val, saw;
55 size_t len = 1024;
56 /*
57 * The slub allocator uses the first word to store the free
58 * pointer in some configurations. Use the middle of the
59 * allocation to avoid running into the freelist
60 */
61 size_t offset = (len / sizeof(*base)) / 2;
62
63 base = kmalloc(len, GFP_KERNEL);
64 if (!base) {
65 pr_info("Unable to allocate base memory.\n");
66 return;
67 }
68
69 val = kmalloc(len, GFP_KERNEL);
70 if (!val) {
71 pr_info("Unable to allocate val memory.\n");
72 kfree(base);
73 return;
74 }
75
76 *val = 0x12345678;
77 base[offset] = *val;
78 pr_info("Value in memory before free: %x\n", base[offset]);
79
80 kfree(base);
81
82 pr_info("Attempting bad read from freed memory\n");
83 saw = base[offset];
84 if (saw != *val) {
85 /* Good! Poisoning happened, so declare a win. */
86 pr_info("Memory correctly poisoned (%x)\n", saw);
87 BUG();
88 }
89 pr_info("Memory was not poisoned\n");
90
91 kfree(val);
92}
93
94void lkdtm_WRITE_BUDDY_AFTER_FREE(void)
95{
96 unsigned long p = __get_free_page(GFP_KERNEL);
97 if (!p) {
98 pr_info("Unable to allocate free page\n");
99 return;
100 }
101
102 pr_info("Writing to the buddy page before free\n");
103 memset((void *)p, 0x3, PAGE_SIZE);
104 free_page(p);
105 schedule();
106 pr_info("Attempting bad write to the buddy page after free\n");
107 memset((void *)p, 0x78, PAGE_SIZE);
108 /* Attempt to notice the overwrite. */
109 p = __get_free_page(GFP_KERNEL);
110 free_page(p);
111 schedule();
112}
113
114void lkdtm_READ_BUDDY_AFTER_FREE(void)
115{
116 unsigned long p = __get_free_page(GFP_KERNEL);
117 int saw, *val;
118 int *base;
119
120 if (!p) {
121 pr_info("Unable to allocate free page\n");
122 return;
123 }
124
125 val = kmalloc(1024, GFP_KERNEL);
126 if (!val) {
127 pr_info("Unable to allocate val memory.\n");
128 free_page(p);
129 return;
130 }
131
132 base = (int *)p;
133
134 *val = 0x12345678;
135 base[0] = *val;
136 pr_info("Value in memory before free: %x\n", base[0]);
137 free_page(p);
138 pr_info("Attempting to read from freed memory\n");
139 saw = base[0];
140 if (saw != *val) {
141 /* Good! Poisoning happened, so declare a win. */
142 pr_info("Memory correctly poisoned (%x)\n", saw);
143 BUG();
144 }
145 pr_info("Buddy page was not poisoned\n");
146
147 kfree(val);
148}