hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/misc/lkdtm/heap.c
....@@ -7,6 +7,10 @@
77 #include <linux/slab.h>
88 #include <linux/sched.h>
99
10
+static struct kmem_cache *double_free_cache;
11
+static struct kmem_cache *a_cache;
12
+static struct kmem_cache *b_cache;
13
+
1014 /*
1115 * This tries to stay within the next largest power-of-2 kmalloc cache
1216 * to avoid actually overwriting anything important if it's not detected
....@@ -54,11 +58,12 @@
5458 int *base, *val, saw;
5559 size_t len = 1024;
5660 /*
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
61
+ * The slub allocator will use the either the first word or
62
+ * the middle of the allocation to store the free pointer,
63
+ * depending on configurations. Store in the second word to
64
+ * avoid running into the freelist.
6065 */
61
- size_t offset = (len / sizeof(*base)) / 2;
66
+ size_t offset = sizeof(*base);
6267
6368 base = kmalloc(len, GFP_KERNEL);
6469 if (!base) {
....@@ -146,3 +151,71 @@
146151
147152 kfree(val);
148153 }
154
+
155
+void lkdtm_SLAB_FREE_DOUBLE(void)
156
+{
157
+ int *val;
158
+
159
+ val = kmem_cache_alloc(double_free_cache, GFP_KERNEL);
160
+ if (!val) {
161
+ pr_info("Unable to allocate double_free_cache memory.\n");
162
+ return;
163
+ }
164
+
165
+ /* Just make sure we got real memory. */
166
+ *val = 0x12345678;
167
+ pr_info("Attempting double slab free ...\n");
168
+ kmem_cache_free(double_free_cache, val);
169
+ kmem_cache_free(double_free_cache, val);
170
+}
171
+
172
+void lkdtm_SLAB_FREE_CROSS(void)
173
+{
174
+ int *val;
175
+
176
+ val = kmem_cache_alloc(a_cache, GFP_KERNEL);
177
+ if (!val) {
178
+ pr_info("Unable to allocate a_cache memory.\n");
179
+ return;
180
+ }
181
+
182
+ /* Just make sure we got real memory. */
183
+ *val = 0x12345679;
184
+ pr_info("Attempting cross-cache slab free ...\n");
185
+ kmem_cache_free(b_cache, val);
186
+}
187
+
188
+void lkdtm_SLAB_FREE_PAGE(void)
189
+{
190
+ unsigned long p = __get_free_page(GFP_KERNEL);
191
+
192
+ pr_info("Attempting non-Slab slab free ...\n");
193
+ kmem_cache_free(NULL, (void *)p);
194
+ free_page(p);
195
+}
196
+
197
+/*
198
+ * We have constructors to keep the caches distinctly separated without
199
+ * needing to boot with "slab_nomerge".
200
+ */
201
+static void ctor_double_free(void *region)
202
+{ }
203
+static void ctor_a(void *region)
204
+{ }
205
+static void ctor_b(void *region)
206
+{ }
207
+
208
+void __init lkdtm_heap_init(void)
209
+{
210
+ double_free_cache = kmem_cache_create("lkdtm-heap-double_free",
211
+ 64, 0, 0, ctor_double_free);
212
+ a_cache = kmem_cache_create("lkdtm-heap-a", 64, 0, 0, ctor_a);
213
+ b_cache = kmem_cache_create("lkdtm-heap-b", 64, 0, 0, ctor_b);
214
+}
215
+
216
+void __exit lkdtm_heap_exit(void)
217
+{
218
+ kmem_cache_destroy(double_free_cache);
219
+ kmem_cache_destroy(a_cache);
220
+ kmem_cache_destroy(b_cache);
221
+}