OSDN Git Service

NFS: Fix bool initialization/comparison
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / lib / test_kasan.c
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
20 static 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
36 static 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
52 static 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 static noinline void __init kmalloc_large_oob_right(void)
69 {
70         char *ptr;
71         size_t size = KMALLOC_MAX_CACHE_SIZE + 10;
72
73         pr_info("kmalloc large allocation: out-of-bounds to right\n");
74         ptr = kmalloc(size, GFP_KERNEL);
75         if (!ptr) {
76                 pr_err("Allocation failed\n");
77                 return;
78         }
79
80         ptr[size] = 0;
81         kfree(ptr);
82 }
83
84 static noinline void __init kmalloc_oob_krealloc_more(void)
85 {
86         char *ptr1, *ptr2;
87         size_t size1 = 17;
88         size_t size2 = 19;
89
90         pr_info("out-of-bounds after krealloc more\n");
91         ptr1 = kmalloc(size1, GFP_KERNEL);
92         ptr2 = krealloc(ptr1, size2, GFP_KERNEL);
93         if (!ptr1 || !ptr2) {
94                 pr_err("Allocation failed\n");
95                 kfree(ptr1);
96                 kfree(ptr2);
97                 return;
98         }
99
100         ptr2[size2] = 'x';
101         kfree(ptr2);
102 }
103
104 static noinline void __init kmalloc_oob_krealloc_less(void)
105 {
106         char *ptr1, *ptr2;
107         size_t size1 = 17;
108         size_t size2 = 15;
109
110         pr_info("out-of-bounds after krealloc less\n");
111         ptr1 = kmalloc(size1, GFP_KERNEL);
112         ptr2 = krealloc(ptr1, size2, GFP_KERNEL);
113         if (!ptr1 || !ptr2) {
114                 pr_err("Allocation failed\n");
115                 kfree(ptr1);
116                 return;
117         }
118         ptr2[size2] = 'x';
119         kfree(ptr2);
120 }
121
122 static noinline void __init kmalloc_oob_16(void)
123 {
124         struct {
125                 u64 words[2];
126         } *ptr1, *ptr2;
127
128         pr_info("kmalloc out-of-bounds for 16-bytes access\n");
129         ptr1 = kmalloc(sizeof(*ptr1) - 3, GFP_KERNEL);
130         ptr2 = kmalloc(sizeof(*ptr2), GFP_KERNEL);
131         if (!ptr1 || !ptr2) {
132                 pr_err("Allocation failed\n");
133                 kfree(ptr1);
134                 kfree(ptr2);
135                 return;
136         }
137         *ptr1 = *ptr2;
138         kfree(ptr1);
139         kfree(ptr2);
140 }
141
142 static noinline void __init kmalloc_oob_memset_2(void)
143 {
144         char *ptr;
145         size_t size = 8;
146
147         pr_info("out-of-bounds in memset2\n");
148         ptr = kmalloc(size, GFP_KERNEL);
149         if (!ptr) {
150                 pr_err("Allocation failed\n");
151                 return;
152         }
153
154         memset(ptr+7, 0, 2);
155         kfree(ptr);
156 }
157
158 static noinline void __init kmalloc_oob_memset_4(void)
159 {
160         char *ptr;
161         size_t size = 8;
162
163         pr_info("out-of-bounds in memset4\n");
164         ptr = kmalloc(size, GFP_KERNEL);
165         if (!ptr) {
166                 pr_err("Allocation failed\n");
167                 return;
168         }
169
170         memset(ptr+5, 0, 4);
171         kfree(ptr);
172 }
173
174
175 static noinline void __init kmalloc_oob_memset_8(void)
176 {
177         char *ptr;
178         size_t size = 8;
179
180         pr_info("out-of-bounds in memset8\n");
181         ptr = kmalloc(size, GFP_KERNEL);
182         if (!ptr) {
183                 pr_err("Allocation failed\n");
184                 return;
185         }
186
187         memset(ptr+1, 0, 8);
188         kfree(ptr);
189 }
190
191 static noinline void __init kmalloc_oob_memset_16(void)
192 {
193         char *ptr;
194         size_t size = 16;
195
196         pr_info("out-of-bounds in memset16\n");
197         ptr = kmalloc(size, GFP_KERNEL);
198         if (!ptr) {
199                 pr_err("Allocation failed\n");
200                 return;
201         }
202
203         memset(ptr+1, 0, 16);
204         kfree(ptr);
205 }
206
207 static noinline void __init kmalloc_oob_in_memset(void)
208 {
209         char *ptr;
210         size_t size = 666;
211
212         pr_info("out-of-bounds in memset\n");
213         ptr = kmalloc(size, GFP_KERNEL);
214         if (!ptr) {
215                 pr_err("Allocation failed\n");
216                 return;
217         }
218
219         memset(ptr, 0, size+5);
220         kfree(ptr);
221 }
222
223 static noinline void __init kmalloc_uaf(void)
224 {
225         char *ptr;
226         size_t size = 10;
227
228         pr_info("use-after-free\n");
229         ptr = kmalloc(size, GFP_KERNEL);
230         if (!ptr) {
231                 pr_err("Allocation failed\n");
232                 return;
233         }
234
235         kfree(ptr);
236         *(ptr + 8) = 'x';
237 }
238
239 static noinline void __init kmalloc_uaf_memset(void)
240 {
241         char *ptr;
242         size_t size = 33;
243
244         pr_info("use-after-free in memset\n");
245         ptr = kmalloc(size, GFP_KERNEL);
246         if (!ptr) {
247                 pr_err("Allocation failed\n");
248                 return;
249         }
250
251         kfree(ptr);
252         memset(ptr, 0, size);
253 }
254
255 static noinline void __init kmalloc_uaf2(void)
256 {
257         char *ptr1, *ptr2;
258         size_t size = 43;
259
260         pr_info("use-after-free after another kmalloc\n");
261         ptr1 = kmalloc(size, GFP_KERNEL);
262         if (!ptr1) {
263                 pr_err("Allocation failed\n");
264                 return;
265         }
266
267         kfree(ptr1);
268         ptr2 = kmalloc(size, GFP_KERNEL);
269         if (!ptr2) {
270                 pr_err("Allocation failed\n");
271                 return;
272         }
273
274         ptr1[40] = 'x';
275         kfree(ptr2);
276 }
277
278 static noinline void __init kmem_cache_oob(void)
279 {
280         char *p;
281         size_t size = 200;
282         struct kmem_cache *cache = kmem_cache_create("test_cache",
283                                                 size, 0,
284                                                 0, NULL);
285         if (!cache) {
286                 pr_err("Cache allocation failed\n");
287                 return;
288         }
289         pr_info("out-of-bounds in kmem_cache_alloc\n");
290         p = kmem_cache_alloc(cache, GFP_KERNEL);
291         if (!p) {
292                 pr_err("Allocation failed\n");
293                 kmem_cache_destroy(cache);
294                 return;
295         }
296
297         *p = p[size];
298         kmem_cache_free(cache, p);
299         kmem_cache_destroy(cache);
300 }
301
302 static char global_array[10];
303
304 static noinline void __init kasan_global_oob(void)
305 {
306         volatile int i = 3;
307         char *p = &global_array[ARRAY_SIZE(global_array) + i];
308
309         pr_info("out-of-bounds global variable\n");
310         *(volatile char *)p;
311 }
312
313 static noinline void __init kasan_stack_oob(void)
314 {
315         char stack_array[10];
316         volatile int i = 0;
317         char *p = &stack_array[ARRAY_SIZE(stack_array) + i];
318
319         pr_info("out-of-bounds on stack\n");
320         *(volatile char *)p;
321 }
322
323 static int __init kmalloc_tests_init(void)
324 {
325         kmalloc_oob_right();
326         kmalloc_oob_left();
327         kmalloc_node_oob_right();
328         kmalloc_large_oob_right();
329         kmalloc_oob_krealloc_more();
330         kmalloc_oob_krealloc_less();
331         kmalloc_oob_16();
332         kmalloc_oob_in_memset();
333         kmalloc_oob_memset_2();
334         kmalloc_oob_memset_4();
335         kmalloc_oob_memset_8();
336         kmalloc_oob_memset_16();
337         kmalloc_uaf();
338         kmalloc_uaf_memset();
339         kmalloc_uaf2();
340         kmem_cache_oob();
341         kasan_stack_oob();
342         kasan_global_oob();
343         return -EAGAIN;
344 }
345
346 module_init(kmalloc_tests_init);
347 MODULE_LICENSE("GPL");