Merge branch 'akpm' (patches from Andrew)
[linux-block.git] / drivers / misc / lkdtm_heap.c
CommitLineData
ffc514f3
KC
1/*
2 * This is for all the tests relating directly to heap memory, including
3 * page allocation and slab allocations.
4 */
ffc514f3 5#include "lkdtm.h"
6d2e91a6 6#include <linux/slab.h>
5b825c3a 7#include <linux/sched.h>
ffc514f3
KC
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 */
14void 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
23void 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
47void 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
89void 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
109void 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}