1 // SPDX-License-Identifier: GPL-2.0 2 #include <kunit/test.h> 3 #include <linux/mm.h> 4 #include <linux/slab.h> 5 #include <linux/module.h> 6 #include <linux/kernel.h> 7 #include "../mm/slab.h" 8 9 static struct kunit_resource resource; 10 static int slab_errors; 11 12 static void test_clobber_zone(struct kunit *test) 13 { 14 struct kmem_cache *s = kmem_cache_create("TestSlub_RZ_alloc", 64, 0, 15 SLAB_RED_ZONE|SLAB_NO_USER_FLAGS, NULL); 16 u8 *p = kmem_cache_alloc(s, GFP_KERNEL); 17 18 kasan_disable_current(); 19 p[64] = 0x12; 20 21 validate_slab_cache(s); 22 KUNIT_EXPECT_EQ(test, 2, slab_errors); 23 24 kasan_enable_current(); 25 kmem_cache_free(s, p); 26 kmem_cache_destroy(s); 27 } 28 29 #ifndef CONFIG_KASAN 30 static void test_next_pointer(struct kunit *test) 31 { 32 struct kmem_cache *s = kmem_cache_create("TestSlub_next_ptr_free", 64, 0, 33 SLAB_POISON|SLAB_NO_USER_FLAGS, NULL); 34 u8 *p = kmem_cache_alloc(s, GFP_KERNEL); 35 unsigned long tmp; 36 unsigned long *ptr_addr; 37 38 kmem_cache_free(s, p); 39 40 ptr_addr = (unsigned long *)(p + s->offset); 41 tmp = *ptr_addr; 42 p[s->offset] = 0x12; 43 44 /* 45 * Expecting three errors. 46 * One for the corrupted freechain and the other one for the wrong 47 * count of objects in use. The third error is fixing broken cache. 48 */ 49 validate_slab_cache(s); 50 KUNIT_EXPECT_EQ(test, 3, slab_errors); 51 52 /* 53 * Try to repair corrupted freepointer. 54 * Still expecting two errors. The first for the wrong count 55 * of objects in use. 56 * The second error is for fixing broken cache. 57 */ 58 *ptr_addr = tmp; 59 slab_errors = 0; 60 61 validate_slab_cache(s); 62 KUNIT_EXPECT_EQ(test, 2, slab_errors); 63 64 /* 65 * Previous validation repaired the count of objects in use. 66 * Now expecting no error. 67 */ 68 slab_errors = 0; 69 validate_slab_cache(s); 70 KUNIT_EXPECT_EQ(test, 0, slab_errors); 71 72 kmem_cache_destroy(s); 73 } 74 75 static void test_first_word(struct kunit *test) 76 { 77 struct kmem_cache *s = kmem_cache_create("TestSlub_1th_word_free", 64, 0, 78 SLAB_POISON|SLAB_NO_USER_FLAGS, NULL); 79 u8 *p = kmem_cache_alloc(s, GFP_KERNEL); 80 81 kmem_cache_free(s, p); 82 *p = 0x78; 83 84 validate_slab_cache(s); 85 KUNIT_EXPECT_EQ(test, 2, slab_errors); 86 87 kmem_cache_destroy(s); 88 } 89 90 static void test_clobber_50th_byte(struct kunit *test) 91 { 92 struct kmem_cache *s = kmem_cache_create("TestSlub_50th_word_free", 64, 0, 93 SLAB_POISON|SLAB_NO_USER_FLAGS, NULL); 94 u8 *p = kmem_cache_alloc(s, GFP_KERNEL); 95 96 kmem_cache_free(s, p); 97 p[50] = 0x9a; 98 99 validate_slab_cache(s); 100 KUNIT_EXPECT_EQ(test, 2, slab_errors); 101 102 kmem_cache_destroy(s); 103 } 104 #endif 105 106 static void test_clobber_redzone_free(struct kunit *test) 107 { 108 struct kmem_cache *s = kmem_cache_create("TestSlub_RZ_free", 64, 0, 109 SLAB_RED_ZONE|SLAB_NO_USER_FLAGS, NULL); 110 u8 *p = kmem_cache_alloc(s, GFP_KERNEL); 111 112 kasan_disable_current(); 113 kmem_cache_free(s, p); 114 p[64] = 0xab; 115 116 validate_slab_cache(s); 117 KUNIT_EXPECT_EQ(test, 2, slab_errors); 118 119 kasan_enable_current(); 120 kmem_cache_destroy(s); 121 } 122 123 static int test_init(struct kunit *test) 124 { 125 slab_errors = 0; 126 127 kunit_add_named_resource(test, NULL, NULL, &resource, 128 "slab_errors", &slab_errors); 129 return 0; 130 } 131 132 static struct kunit_case test_cases[] = { 133 KUNIT_CASE(test_clobber_zone), 134 135 #ifndef CONFIG_KASAN 136 KUNIT_CASE(test_next_pointer), 137 KUNIT_CASE(test_first_word), 138 KUNIT_CASE(test_clobber_50th_byte), 139 #endif 140 141 KUNIT_CASE(test_clobber_redzone_free), 142 {} 143 }; 144 145 static struct kunit_suite test_suite = { 146 .name = "slub_test", 147 .init = test_init, 148 .test_cases = test_cases, 149 }; 150 kunit_test_suite(test_suite); 151 152 MODULE_LICENSE("GPL"); 153