slub_kunit.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <kunit/test.h>
  3. #include <kunit/test-bug.h>
  4. #include <linux/mm.h>
  5. #include <linux/slab.h>
  6. #include <linux/module.h>
  7. #include <linux/kernel.h>
  8. #include <linux/rcupdate.h>
  9. #include <linux/delay.h>
  10. #include "../mm/slab.h"
  11. static struct kunit_resource resource;
  12. static int slab_errors;
  13. /*
  14. * Wrapper function for kmem_cache_create(), which reduces 2 parameters:
  15. * 'align' and 'ctor', and sets SLAB_SKIP_KFENCE flag to avoid getting an
  16. * object from kfence pool, where the operation could be caught by both
  17. * our test and kfence sanity check.
  18. */
  19. static struct kmem_cache *test_kmem_cache_create(const char *name,
  20. unsigned int size, slab_flags_t flags)
  21. {
  22. struct kmem_cache *s = kmem_cache_create(name, size, 0,
  23. (flags | SLAB_NO_USER_FLAGS), NULL);
  24. s->flags |= SLAB_SKIP_KFENCE;
  25. return s;
  26. }
  27. static void test_clobber_zone(struct kunit *test)
  28. {
  29. struct kmem_cache *s = test_kmem_cache_create("TestSlub_RZ_alloc", 64,
  30. SLAB_RED_ZONE);
  31. u8 *p = kmem_cache_alloc(s, GFP_KERNEL);
  32. kasan_disable_current();
  33. p[64] = 0x12;
  34. validate_slab_cache(s);
  35. KUNIT_EXPECT_EQ(test, 2, slab_errors);
  36. kasan_enable_current();
  37. kmem_cache_free(s, p);
  38. kmem_cache_destroy(s);
  39. }
  40. #ifndef CONFIG_KASAN
  41. static void test_next_pointer(struct kunit *test)
  42. {
  43. struct kmem_cache *s = test_kmem_cache_create("TestSlub_next_ptr_free",
  44. 64, SLAB_POISON);
  45. u8 *p = kmem_cache_alloc(s, GFP_KERNEL);
  46. unsigned long tmp;
  47. unsigned long *ptr_addr;
  48. kmem_cache_free(s, p);
  49. ptr_addr = (unsigned long *)(p + s->offset);
  50. tmp = *ptr_addr;
  51. p[s->offset] = ~p[s->offset];
  52. /*
  53. * Expecting three errors.
  54. * One for the corrupted freechain and the other one for the wrong
  55. * count of objects in use. The third error is fixing broken cache.
  56. */
  57. validate_slab_cache(s);
  58. KUNIT_EXPECT_EQ(test, 3, slab_errors);
  59. /*
  60. * Try to repair corrupted freepointer.
  61. * Still expecting two errors. The first for the wrong count
  62. * of objects in use.
  63. * The second error is for fixing broken cache.
  64. */
  65. *ptr_addr = tmp;
  66. slab_errors = 0;
  67. validate_slab_cache(s);
  68. KUNIT_EXPECT_EQ(test, 2, slab_errors);
  69. /*
  70. * Previous validation repaired the count of objects in use.
  71. * Now expecting no error.
  72. */
  73. slab_errors = 0;
  74. validate_slab_cache(s);
  75. KUNIT_EXPECT_EQ(test, 0, slab_errors);
  76. kmem_cache_destroy(s);
  77. }
  78. static void test_first_word(struct kunit *test)
  79. {
  80. struct kmem_cache *s = test_kmem_cache_create("TestSlub_1th_word_free",
  81. 64, SLAB_POISON);
  82. u8 *p = kmem_cache_alloc(s, GFP_KERNEL);
  83. kmem_cache_free(s, p);
  84. *p = 0x78;
  85. validate_slab_cache(s);
  86. KUNIT_EXPECT_EQ(test, 2, slab_errors);
  87. kmem_cache_destroy(s);
  88. }
  89. static void test_clobber_50th_byte(struct kunit *test)
  90. {
  91. struct kmem_cache *s = test_kmem_cache_create("TestSlub_50th_word_free",
  92. 64, SLAB_POISON);
  93. u8 *p = kmem_cache_alloc(s, GFP_KERNEL);
  94. kmem_cache_free(s, p);
  95. p[50] = 0x9a;
  96. validate_slab_cache(s);
  97. KUNIT_EXPECT_EQ(test, 2, slab_errors);
  98. kmem_cache_destroy(s);
  99. }
  100. #endif
  101. static void test_clobber_redzone_free(struct kunit *test)
  102. {
  103. struct kmem_cache *s = test_kmem_cache_create("TestSlub_RZ_free", 64,
  104. SLAB_RED_ZONE);
  105. u8 *p = kmem_cache_alloc(s, GFP_KERNEL);
  106. kasan_disable_current();
  107. kmem_cache_free(s, p);
  108. p[64] = 0xab;
  109. validate_slab_cache(s);
  110. KUNIT_EXPECT_EQ(test, 2, slab_errors);
  111. kasan_enable_current();
  112. kmem_cache_destroy(s);
  113. }
  114. static void test_kmalloc_redzone_access(struct kunit *test)
  115. {
  116. struct kmem_cache *s = test_kmem_cache_create("TestSlub_RZ_kmalloc", 32,
  117. SLAB_KMALLOC|SLAB_STORE_USER|SLAB_RED_ZONE);
  118. u8 *p = alloc_hooks(__kmalloc_cache_noprof(s, GFP_KERNEL, 18));
  119. kasan_disable_current();
  120. /* Suppress the -Warray-bounds warning */
  121. OPTIMIZER_HIDE_VAR(p);
  122. p[18] = 0xab;
  123. p[19] = 0xab;
  124. validate_slab_cache(s);
  125. KUNIT_EXPECT_EQ(test, 2, slab_errors);
  126. kasan_enable_current();
  127. kmem_cache_free(s, p);
  128. kmem_cache_destroy(s);
  129. }
  130. struct test_kfree_rcu_struct {
  131. struct rcu_head rcu;
  132. };
  133. static void test_kfree_rcu(struct kunit *test)
  134. {
  135. struct kmem_cache *s;
  136. struct test_kfree_rcu_struct *p;
  137. if (IS_BUILTIN(CONFIG_SLUB_KUNIT_TEST))
  138. kunit_skip(test, "can't do kfree_rcu() when test is built-in");
  139. s = test_kmem_cache_create("TestSlub_kfree_rcu",
  140. sizeof(struct test_kfree_rcu_struct),
  141. SLAB_NO_MERGE);
  142. p = kmem_cache_alloc(s, GFP_KERNEL);
  143. kfree_rcu(p, rcu);
  144. kmem_cache_destroy(s);
  145. KUNIT_EXPECT_EQ(test, 0, slab_errors);
  146. }
  147. struct cache_destroy_work {
  148. struct work_struct work;
  149. struct kmem_cache *s;
  150. };
  151. static void cache_destroy_workfn(struct work_struct *w)
  152. {
  153. struct cache_destroy_work *cdw;
  154. cdw = container_of(w, struct cache_destroy_work, work);
  155. kmem_cache_destroy(cdw->s);
  156. }
  157. #define KMEM_CACHE_DESTROY_NR 10
  158. static void test_kfree_rcu_wq_destroy(struct kunit *test)
  159. {
  160. struct test_kfree_rcu_struct *p;
  161. struct cache_destroy_work cdw;
  162. struct workqueue_struct *wq;
  163. struct kmem_cache *s;
  164. unsigned int delay;
  165. int i;
  166. if (IS_BUILTIN(CONFIG_SLUB_KUNIT_TEST))
  167. kunit_skip(test, "can't do kfree_rcu() when test is built-in");
  168. INIT_WORK_ONSTACK(&cdw.work, cache_destroy_workfn);
  169. wq = alloc_workqueue("test_kfree_rcu_destroy_wq",
  170. WQ_HIGHPRI | WQ_UNBOUND | WQ_MEM_RECLAIM, 0);
  171. if (!wq)
  172. kunit_skip(test, "failed to alloc wq");
  173. for (i = 0; i < KMEM_CACHE_DESTROY_NR; i++) {
  174. s = test_kmem_cache_create("TestSlub_kfree_rcu_wq_destroy",
  175. sizeof(struct test_kfree_rcu_struct),
  176. SLAB_NO_MERGE);
  177. if (!s)
  178. kunit_skip(test, "failed to create cache");
  179. delay = get_random_u8();
  180. p = kmem_cache_alloc(s, GFP_KERNEL);
  181. kfree_rcu(p, rcu);
  182. cdw.s = s;
  183. msleep(delay);
  184. queue_work(wq, &cdw.work);
  185. flush_work(&cdw.work);
  186. }
  187. destroy_workqueue(wq);
  188. KUNIT_EXPECT_EQ(test, 0, slab_errors);
  189. }
  190. static void test_leak_destroy(struct kunit *test)
  191. {
  192. struct kmem_cache *s = test_kmem_cache_create("TestSlub_leak_destroy",
  193. 64, SLAB_NO_MERGE);
  194. kmem_cache_alloc(s, GFP_KERNEL);
  195. kmem_cache_destroy(s);
  196. KUNIT_EXPECT_EQ(test, 2, slab_errors);
  197. }
  198. static void test_krealloc_redzone_zeroing(struct kunit *test)
  199. {
  200. u8 *p;
  201. int i;
  202. struct kmem_cache *s = test_kmem_cache_create("TestSlub_krealloc", 64,
  203. SLAB_KMALLOC|SLAB_STORE_USER|SLAB_RED_ZONE);
  204. p = alloc_hooks(__kmalloc_cache_noprof(s, GFP_KERNEL, 48));
  205. memset(p, 0xff, 48);
  206. kasan_disable_current();
  207. OPTIMIZER_HIDE_VAR(p);
  208. /* Test shrink */
  209. p = krealloc(p, 40, GFP_KERNEL | __GFP_ZERO);
  210. for (i = 40; i < 64; i++)
  211. KUNIT_EXPECT_EQ(test, p[i], SLUB_RED_ACTIVE);
  212. /* Test grow within the same 64B kmalloc object */
  213. p = krealloc(p, 56, GFP_KERNEL | __GFP_ZERO);
  214. for (i = 40; i < 56; i++)
  215. KUNIT_EXPECT_EQ(test, p[i], 0);
  216. for (i = 56; i < 64; i++)
  217. KUNIT_EXPECT_EQ(test, p[i], SLUB_RED_ACTIVE);
  218. validate_slab_cache(s);
  219. KUNIT_EXPECT_EQ(test, 0, slab_errors);
  220. memset(p, 0xff, 56);
  221. /* Test grow with allocating a bigger 128B object */
  222. p = krealloc(p, 112, GFP_KERNEL | __GFP_ZERO);
  223. for (i = 0; i < 56; i++)
  224. KUNIT_EXPECT_EQ(test, p[i], 0xff);
  225. for (i = 56; i < 112; i++)
  226. KUNIT_EXPECT_EQ(test, p[i], 0);
  227. kfree(p);
  228. kasan_enable_current();
  229. kmem_cache_destroy(s);
  230. }
  231. static int test_init(struct kunit *test)
  232. {
  233. slab_errors = 0;
  234. kunit_add_named_resource(test, NULL, NULL, &resource,
  235. "slab_errors", &slab_errors);
  236. return 0;
  237. }
  238. static struct kunit_case test_cases[] = {
  239. KUNIT_CASE(test_clobber_zone),
  240. #ifndef CONFIG_KASAN
  241. KUNIT_CASE(test_next_pointer),
  242. KUNIT_CASE(test_first_word),
  243. KUNIT_CASE(test_clobber_50th_byte),
  244. #endif
  245. KUNIT_CASE(test_clobber_redzone_free),
  246. KUNIT_CASE(test_kmalloc_redzone_access),
  247. KUNIT_CASE(test_kfree_rcu),
  248. KUNIT_CASE(test_kfree_rcu_wq_destroy),
  249. KUNIT_CASE(test_leak_destroy),
  250. KUNIT_CASE(test_krealloc_redzone_zeroing),
  251. {}
  252. };
  253. static struct kunit_suite test_suite = {
  254. .name = "slub_test",
  255. .init = test_init,
  256. .test_cases = test_cases,
  257. };
  258. kunit_test_suite(test_suite);
  259. MODULE_DESCRIPTION("Kunit tests for slub allocator");
  260. MODULE_LICENSE("GPL");