slub_kunit.c (3455B)
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 9static struct kunit_resource resource; 10static int slab_errors; 11 12static 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 30static 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 75static 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 90static 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 106static 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 123static 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 132static 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 145static struct kunit_suite test_suite = { 146 .name = "slub_test", 147 .init = test_init, 148 .test_cases = test_cases, 149}; 150kunit_test_suite(test_suite); 151 152MODULE_LICENSE("GPL");