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