Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.15.
  1/*
  2 *
  3 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
  4 * Author: Andrey Ryabinin <a.ryabinin@samsung.com>
  5 *
  6 * This program is free software; you can redistribute it and/or modify
  7 * it under the terms of the GNU General Public License version 2 as
  8 * published by the Free Software Foundation.
  9 *
 10 */
 11
 12#define pr_fmt(fmt) "kasan test: %s " fmt, __func__
 13
 14#include <linux/kernel.h>
 15#include <linux/printk.h>
 16#include <linux/slab.h>
 17#include <linux/string.h>
 18#include <linux/module.h>
 19
 20static noinline void __init kmalloc_oob_right(void)
 21{
 22	char *ptr;
 23	size_t size = 123;
 24
 25	pr_info("out-of-bounds to right\n");
 26	ptr = kmalloc(size, GFP_KERNEL);
 27	if (!ptr) {
 28		pr_err("Allocation failed\n");
 29		return;
 30	}
 31
 32	ptr[size] = 'x';
 33	kfree(ptr);
 34}
 35
 36static noinline void __init kmalloc_oob_left(void)
 37{
 38	char *ptr;
 39	size_t size = 15;
 40
 41	pr_info("out-of-bounds to left\n");
 42	ptr = kmalloc(size, GFP_KERNEL);
 43	if (!ptr) {
 44		pr_err("Allocation failed\n");
 45		return;
 46	}
 47
 48	*ptr = *(ptr - 1);
 49	kfree(ptr);
 50}
 51
 52static noinline void __init kmalloc_node_oob_right(void)
 53{
 54	char *ptr;
 55	size_t size = 4096;
 56
 57	pr_info("kmalloc_node(): out-of-bounds to right\n");
 58	ptr = kmalloc_node(size, GFP_KERNEL, 0);
 59	if (!ptr) {
 60		pr_err("Allocation failed\n");
 61		return;
 62	}
 63
 64	ptr[size] = 0;
 65	kfree(ptr);
 66}
 67
 68#ifdef CONFIG_SLUB
 69static noinline void __init kmalloc_pagealloc_oob_right(void)
 70{
 71	char *ptr;
 72	size_t size = KMALLOC_MAX_CACHE_SIZE + 10;
 73
 74	/* Allocate a chunk that does not fit into a SLUB cache to trigger
 75	 * the page allocator fallback.
 76	 */
 77	pr_info("kmalloc pagealloc allocation: out-of-bounds to right\n");
 78	ptr = kmalloc(size, GFP_KERNEL);
 79	if (!ptr) {
 80		pr_err("Allocation failed\n");
 81		return;
 82	}
 83
 84	ptr[size] = 0;
 85	kfree(ptr);
 86}
 87#endif
 88
 89static noinline void __init kmalloc_large_oob_right(void)
 90{
 91	char *ptr;
 92	size_t size = KMALLOC_MAX_CACHE_SIZE - 256;
 93	/* Allocate a chunk that is large enough, but still fits into a slab
 94	 * and does not trigger the page allocator fallback in SLUB.
 95	 */
 96	pr_info("kmalloc large allocation: out-of-bounds to right\n");
 97	ptr = kmalloc(size, GFP_KERNEL);
 98	if (!ptr) {
 99		pr_err("Allocation failed\n");
100		return;
101	}
102
103	ptr[size] = 0;
104	kfree(ptr);
105}
106
107static noinline void __init kmalloc_oob_krealloc_more(void)
108{
109	char *ptr1, *ptr2;
110	size_t size1 = 17;
111	size_t size2 = 19;
112
113	pr_info("out-of-bounds after krealloc more\n");
114	ptr1 = kmalloc(size1, GFP_KERNEL);
115	ptr2 = krealloc(ptr1, size2, GFP_KERNEL);
116	if (!ptr1 || !ptr2) {
117		pr_err("Allocation failed\n");
118		kfree(ptr1);
119		return;
120	}
121
122	ptr2[size2] = 'x';
123	kfree(ptr2);
124}
125
126static noinline void __init kmalloc_oob_krealloc_less(void)
127{
128	char *ptr1, *ptr2;
129	size_t size1 = 17;
130	size_t size2 = 15;
131
132	pr_info("out-of-bounds after krealloc less\n");
133	ptr1 = kmalloc(size1, GFP_KERNEL);
134	ptr2 = krealloc(ptr1, size2, GFP_KERNEL);
135	if (!ptr1 || !ptr2) {
136		pr_err("Allocation failed\n");
137		kfree(ptr1);
138		return;
139	}
140	ptr2[size2] = 'x';
141	kfree(ptr2);
142}
143
144static noinline void __init kmalloc_oob_16(void)
145{
146	struct {
147		u64 words[2];
148	} *ptr1, *ptr2;
149
150	pr_info("kmalloc out-of-bounds for 16-bytes access\n");
151	ptr1 = kmalloc(sizeof(*ptr1) - 3, GFP_KERNEL);
152	ptr2 = kmalloc(sizeof(*ptr2), GFP_KERNEL);
153	if (!ptr1 || !ptr2) {
154		pr_err("Allocation failed\n");
155		kfree(ptr1);
156		kfree(ptr2);
157		return;
158	}
159	*ptr1 = *ptr2;
160	kfree(ptr1);
161	kfree(ptr2);
162}
163
164static noinline void __init kmalloc_oob_memset_2(void)
165{
166	char *ptr;
167	size_t size = 8;
168
169	pr_info("out-of-bounds in memset2\n");
170	ptr = kmalloc(size, GFP_KERNEL);
171	if (!ptr) {
172		pr_err("Allocation failed\n");
173		return;
174	}
175
176	memset(ptr+7, 0, 2);
177	kfree(ptr);
178}
179
180static noinline void __init kmalloc_oob_memset_4(void)
181{
182	char *ptr;
183	size_t size = 8;
184
185	pr_info("out-of-bounds in memset4\n");
186	ptr = kmalloc(size, GFP_KERNEL);
187	if (!ptr) {
188		pr_err("Allocation failed\n");
189		return;
190	}
191
192	memset(ptr+5, 0, 4);
193	kfree(ptr);
194}
195
196
197static noinline void __init kmalloc_oob_memset_8(void)
198{
199	char *ptr;
200	size_t size = 8;
201
202	pr_info("out-of-bounds in memset8\n");
203	ptr = kmalloc(size, GFP_KERNEL);
204	if (!ptr) {
205		pr_err("Allocation failed\n");
206		return;
207	}
208
209	memset(ptr+1, 0, 8);
210	kfree(ptr);
211}
212
213static noinline void __init kmalloc_oob_memset_16(void)
214{
215	char *ptr;
216	size_t size = 16;
217
218	pr_info("out-of-bounds in memset16\n");
219	ptr = kmalloc(size, GFP_KERNEL);
220	if (!ptr) {
221		pr_err("Allocation failed\n");
222		return;
223	}
224
225	memset(ptr+1, 0, 16);
226	kfree(ptr);
227}
228
229static noinline void __init kmalloc_oob_in_memset(void)
230{
231	char *ptr;
232	size_t size = 666;
233
234	pr_info("out-of-bounds in memset\n");
235	ptr = kmalloc(size, GFP_KERNEL);
236	if (!ptr) {
237		pr_err("Allocation failed\n");
238		return;
239	}
240
241	memset(ptr, 0, size+5);
242	kfree(ptr);
243}
244
245static noinline void __init kmalloc_uaf(void)
246{
247	char *ptr;
248	size_t size = 10;
249
250	pr_info("use-after-free\n");
251	ptr = kmalloc(size, GFP_KERNEL);
252	if (!ptr) {
253		pr_err("Allocation failed\n");
254		return;
255	}
256
257	kfree(ptr);
258	*(ptr + 8) = 'x';
259}
260
261static noinline void __init kmalloc_uaf_memset(void)
262{
263	char *ptr;
264	size_t size = 33;
265
266	pr_info("use-after-free in memset\n");
267	ptr = kmalloc(size, GFP_KERNEL);
268	if (!ptr) {
269		pr_err("Allocation failed\n");
270		return;
271	}
272
273	kfree(ptr);
274	memset(ptr, 0, size);
275}
276
277static noinline void __init kmalloc_uaf2(void)
278{
279	char *ptr1, *ptr2;
280	size_t size = 43;
281
282	pr_info("use-after-free after another kmalloc\n");
283	ptr1 = kmalloc(size, GFP_KERNEL);
284	if (!ptr1) {
285		pr_err("Allocation failed\n");
286		return;
287	}
288
289	kfree(ptr1);
290	ptr2 = kmalloc(size, GFP_KERNEL);
291	if (!ptr2) {
292		pr_err("Allocation failed\n");
293		return;
294	}
295
296	ptr1[40] = 'x';
297	if (ptr1 == ptr2)
298		pr_err("Could not detect use-after-free: ptr1 == ptr2\n");
299	kfree(ptr2);
300}
301
302static noinline void __init kmem_cache_oob(void)
303{
304	char *p;
305	size_t size = 200;
306	struct kmem_cache *cache = kmem_cache_create("test_cache",
307						size, 0,
308						0, NULL);
309	if (!cache) {
310		pr_err("Cache allocation failed\n");
311		return;
312	}
313	pr_info("out-of-bounds in kmem_cache_alloc\n");
314	p = kmem_cache_alloc(cache, GFP_KERNEL);
315	if (!p) {
316		pr_err("Allocation failed\n");
317		kmem_cache_destroy(cache);
318		return;
319	}
320
321	*p = p[size];
322	kmem_cache_free(cache, p);
323	kmem_cache_destroy(cache);
324}
325
326static char global_array[10];
327
328static noinline void __init kasan_global_oob(void)
329{
330	volatile int i = 3;
331	char *p = &global_array[ARRAY_SIZE(global_array) + i];
332
333	pr_info("out-of-bounds global variable\n");
334	*(volatile char *)p;
335}
336
337static noinline void __init kasan_stack_oob(void)
338{
339	char stack_array[10];
340	volatile int i = 0;
341	char *p = &stack_array[ARRAY_SIZE(stack_array) + i];
342
343	pr_info("out-of-bounds on stack\n");
344	*(volatile char *)p;
345}
346
347static int __init kmalloc_tests_init(void)
348{
349	kmalloc_oob_right();
350	kmalloc_oob_left();
351	kmalloc_node_oob_right();
352#ifdef CONFIG_SLUB
353	kmalloc_pagealloc_oob_right();
354#endif
355	kmalloc_large_oob_right();
356	kmalloc_oob_krealloc_more();
357	kmalloc_oob_krealloc_less();
358	kmalloc_oob_16();
359	kmalloc_oob_in_memset();
360	kmalloc_oob_memset_2();
361	kmalloc_oob_memset_4();
362	kmalloc_oob_memset_8();
363	kmalloc_oob_memset_16();
364	kmalloc_uaf();
365	kmalloc_uaf_memset();
366	kmalloc_uaf2();
367	kmem_cache_oob();
368	kasan_stack_oob();
369	kasan_global_oob();
370	return -EAGAIN;
371}
372
373module_init(kmalloc_tests_init);
374MODULE_LICENSE("GPL");