test_kasan.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  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. #define pr_fmt(fmt) "kasan test: %s " fmt, __func__
  12. #include <linux/kernel.h>
  13. #include <linux/printk.h>
  14. #include <linux/slab.h>
  15. #include <linux/string.h>
  16. #include <linux/module.h>
  17. static noinline void __init kmalloc_oob_right(void)
  18. {
  19. char *ptr;
  20. size_t size = 123;
  21. pr_info("out-of-bounds to right\n");
  22. ptr = kmalloc(size, GFP_KERNEL);
  23. if (!ptr) {
  24. pr_err("Allocation failed\n");
  25. return;
  26. }
  27. ptr[size] = 'x';
  28. kfree(ptr);
  29. }
  30. static noinline void __init kmalloc_oob_left(void)
  31. {
  32. char *ptr;
  33. size_t size = 15;
  34. pr_info("out-of-bounds to left\n");
  35. ptr = kmalloc(size, GFP_KERNEL);
  36. if (!ptr) {
  37. pr_err("Allocation failed\n");
  38. return;
  39. }
  40. *ptr = *(ptr - 1);
  41. kfree(ptr);
  42. }
  43. static noinline void __init kmalloc_node_oob_right(void)
  44. {
  45. char *ptr;
  46. size_t size = 4096;
  47. pr_info("kmalloc_node(): out-of-bounds to right\n");
  48. ptr = kmalloc_node(size, GFP_KERNEL, 0);
  49. if (!ptr) {
  50. pr_err("Allocation failed\n");
  51. return;
  52. }
  53. ptr[size] = 0;
  54. kfree(ptr);
  55. }
  56. static noinline void __init kmalloc_large_oob_rigth(void)
  57. {
  58. char *ptr;
  59. size_t size = KMALLOC_MAX_CACHE_SIZE + 10;
  60. pr_info("kmalloc large allocation: out-of-bounds to right\n");
  61. ptr = kmalloc(size, GFP_KERNEL);
  62. if (!ptr) {
  63. pr_err("Allocation failed\n");
  64. return;
  65. }
  66. ptr[size] = 0;
  67. kfree(ptr);
  68. }
  69. static noinline void __init kmalloc_oob_krealloc_more(void)
  70. {
  71. char *ptr1, *ptr2;
  72. size_t size1 = 17;
  73. size_t size2 = 19;
  74. pr_info("out-of-bounds after krealloc more\n");
  75. ptr1 = kmalloc(size1, GFP_KERNEL);
  76. ptr2 = krealloc(ptr1, size2, GFP_KERNEL);
  77. if (!ptr1 || !ptr2) {
  78. pr_err("Allocation failed\n");
  79. kfree(ptr1);
  80. return;
  81. }
  82. ptr2[size2] = 'x';
  83. kfree(ptr2);
  84. }
  85. static noinline void __init kmalloc_oob_krealloc_less(void)
  86. {
  87. char *ptr1, *ptr2;
  88. size_t size1 = 17;
  89. size_t size2 = 15;
  90. pr_info("out-of-bounds after krealloc less\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. return;
  97. }
  98. ptr2[size1] = 'x';
  99. kfree(ptr2);
  100. }
  101. static noinline void __init kmalloc_oob_16(void)
  102. {
  103. struct {
  104. u64 words[2];
  105. } *ptr1, *ptr2;
  106. pr_info("kmalloc out-of-bounds for 16-bytes access\n");
  107. ptr1 = kmalloc(sizeof(*ptr1) - 3, GFP_KERNEL);
  108. ptr2 = kmalloc(sizeof(*ptr2), GFP_KERNEL);
  109. if (!ptr1 || !ptr2) {
  110. pr_err("Allocation failed\n");
  111. kfree(ptr1);
  112. kfree(ptr2);
  113. return;
  114. }
  115. *ptr1 = *ptr2;
  116. kfree(ptr1);
  117. kfree(ptr2);
  118. }
  119. static noinline void __init kmalloc_oob_in_memset(void)
  120. {
  121. char *ptr;
  122. size_t size = 666;
  123. pr_info("out-of-bounds in memset\n");
  124. ptr = kmalloc(size, GFP_KERNEL);
  125. if (!ptr) {
  126. pr_err("Allocation failed\n");
  127. return;
  128. }
  129. memset(ptr, 0, size+5);
  130. kfree(ptr);
  131. }
  132. static noinline void __init kmalloc_uaf(void)
  133. {
  134. char *ptr;
  135. size_t size = 10;
  136. pr_info("use-after-free\n");
  137. ptr = kmalloc(size, GFP_KERNEL);
  138. if (!ptr) {
  139. pr_err("Allocation failed\n");
  140. return;
  141. }
  142. kfree(ptr);
  143. *(ptr + 8) = 'x';
  144. }
  145. static noinline void __init kmalloc_uaf_memset(void)
  146. {
  147. char *ptr;
  148. size_t size = 33;
  149. pr_info("use-after-free in memset\n");
  150. ptr = kmalloc(size, GFP_KERNEL);
  151. if (!ptr) {
  152. pr_err("Allocation failed\n");
  153. return;
  154. }
  155. kfree(ptr);
  156. memset(ptr, 0, size);
  157. }
  158. static noinline void __init kmalloc_uaf2(void)
  159. {
  160. char *ptr1, *ptr2;
  161. size_t size = 43;
  162. pr_info("use-after-free after another kmalloc\n");
  163. ptr1 = kmalloc(size, GFP_KERNEL);
  164. if (!ptr1) {
  165. pr_err("Allocation failed\n");
  166. return;
  167. }
  168. kfree(ptr1);
  169. ptr2 = kmalloc(size, GFP_KERNEL);
  170. if (!ptr2) {
  171. pr_err("Allocation failed\n");
  172. return;
  173. }
  174. ptr1[40] = 'x';
  175. kfree(ptr2);
  176. }
  177. static noinline void __init kmem_cache_oob(void)
  178. {
  179. char *p;
  180. size_t size = 200;
  181. struct kmem_cache *cache = kmem_cache_create("test_cache",
  182. size, 0,
  183. 0, NULL);
  184. if (!cache) {
  185. pr_err("Cache allocation failed\n");
  186. return;
  187. }
  188. pr_info("out-of-bounds in kmem_cache_alloc\n");
  189. p = kmem_cache_alloc(cache, GFP_KERNEL);
  190. if (!p) {
  191. pr_err("Allocation failed\n");
  192. kmem_cache_destroy(cache);
  193. return;
  194. }
  195. *p = p[size];
  196. kmem_cache_free(cache, p);
  197. kmem_cache_destroy(cache);
  198. }
  199. static char global_array[10];
  200. static noinline void __init kasan_global_oob(void)
  201. {
  202. volatile int i = 3;
  203. char *p = &global_array[ARRAY_SIZE(global_array) + i];
  204. pr_info("out-of-bounds global variable\n");
  205. *(volatile char *)p;
  206. }
  207. static noinline void __init kasan_stack_oob(void)
  208. {
  209. char stack_array[10];
  210. volatile int i = 0;
  211. char *p = &stack_array[ARRAY_SIZE(stack_array) + i];
  212. pr_info("out-of-bounds on stack\n");
  213. *(volatile char *)p;
  214. }
  215. static int __init kmalloc_tests_init(void)
  216. {
  217. kmalloc_oob_right();
  218. kmalloc_oob_left();
  219. kmalloc_node_oob_right();
  220. kmalloc_large_oob_rigth();
  221. kmalloc_oob_krealloc_more();
  222. kmalloc_oob_krealloc_less();
  223. kmalloc_oob_16();
  224. kmalloc_oob_in_memset();
  225. kmalloc_uaf();
  226. kmalloc_uaf_memset();
  227. kmalloc_uaf2();
  228. kmem_cache_oob();
  229. kasan_stack_oob();
  230. kasan_global_oob();
  231. return -EAGAIN;
  232. }
  233. module_init(kmalloc_tests_init);
  234. MODULE_LICENSE("GPL");