]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/misc/lkdtm_heap.c
PCI: PM: Skip devices in D0 for suspend-to-idle
[mirror_ubuntu-bionic-kernel.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);
19
20 data[1024 / sizeof(u32)] = 0x12345678;
21 kfree(data);
22}
23
24void lkdtm_WRITE_AFTER_FREE(void)
25{
26 int *base, *again;
27 size_t len = 1024;
28 /*
29 * The slub allocator uses the first word to store the free
30 * pointer in some configurations. Use the middle of the
31 * allocation to avoid running into the freelist
32 */
33 size_t offset = (len / sizeof(*base)) / 2;
34
35 base = kmalloc(len, GFP_KERNEL);
36 pr_info("Allocated memory %p-%p\n", base, &base[offset * 2]);
37 pr_info("Attempting bad write to freed memory at %p\n",
38 &base[offset]);
39 kfree(base);
40 base[offset] = 0x0abcdef0;
41 /* Attempt to notice the overwrite. */
42 again = kmalloc(len, GFP_KERNEL);
43 kfree(again);
44 if (again != base)
45 pr_info("Hmm, didn't get the same memory range.\n");
46}
47
48void lkdtm_READ_AFTER_FREE(void)
49{
50 int *base, *val, saw;
51 size_t len = 1024;
52 /*
53 * The slub allocator uses the first word to store the free
54 * pointer in some configurations. Use the middle of the
55 * allocation to avoid running into the freelist
56 */
57 size_t offset = (len / sizeof(*base)) / 2;
58
59 base = kmalloc(len, GFP_KERNEL);
60 if (!base) {
61 pr_info("Unable to allocate base memory.\n");
62 return;
63 }
64
65 val = kmalloc(len, GFP_KERNEL);
66 if (!val) {
67 pr_info("Unable to allocate val memory.\n");
68 kfree(base);
69 return;
70 }
71
72 *val = 0x12345678;
73 base[offset] = *val;
74 pr_info("Value in memory before free: %x\n", base[offset]);
75
76 kfree(base);
77
78 pr_info("Attempting bad read from freed memory\n");
79 saw = base[offset];
80 if (saw != *val) {
81 /* Good! Poisoning happened, so declare a win. */
82 pr_info("Memory correctly poisoned (%x)\n", saw);
83 BUG();
84 }
85 pr_info("Memory was not poisoned\n");
86
87 kfree(val);
88}
89
90void lkdtm_WRITE_BUDDY_AFTER_FREE(void)
91{
92 unsigned long p = __get_free_page(GFP_KERNEL);
93 if (!p) {
94 pr_info("Unable to allocate free page\n");
95 return;
96 }
97
98 pr_info("Writing to the buddy page before free\n");
99 memset((void *)p, 0x3, PAGE_SIZE);
100 free_page(p);
101 schedule();
102 pr_info("Attempting bad write to the buddy page after free\n");
103 memset((void *)p, 0x78, PAGE_SIZE);
104 /* Attempt to notice the overwrite. */
105 p = __get_free_page(GFP_KERNEL);
106 free_page(p);
107 schedule();
108}
109
110void lkdtm_READ_BUDDY_AFTER_FREE(void)
111{
112 unsigned long p = __get_free_page(GFP_KERNEL);
113 int saw, *val;
114 int *base;
115
116 if (!p) {
117 pr_info("Unable to allocate free page\n");
118 return;
119 }
120
121 val = kmalloc(1024, GFP_KERNEL);
122 if (!val) {
123 pr_info("Unable to allocate val memory.\n");
124 free_page(p);
125 return;
126 }
127
128 base = (int *)p;
129
130 *val = 0x12345678;
131 base[0] = *val;
132 pr_info("Value in memory before free: %x\n", base[0]);
133 free_page(p);
134 pr_info("Attempting to read from freed memory\n");
135 saw = base[0];
136 if (saw != *val) {
137 /* Good! Poisoning happened, so declare a win. */
138 pr_info("Memory correctly poisoned (%x)\n", saw);
139 BUG();
140 }
141 pr_info("Buddy page was not poisoned\n");
142
143 kfree(val);
144}