forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 23
/
test_slub.c
124 lines (98 loc) · 2.83 KB
/
test_slub.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// SPDX-License-Identifier: GPL-2.0
#include <kunit/test.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include "../mm/slab.h"
static void test_clobber_zone(struct kunit *test)
{
struct kmem_cache *s = kmem_cache_create("TestSlub_RZ_alloc", 64, 0,
SLAB_RED_ZONE | SLAB_SILENT_ERRORS, NULL);
u8 *p = kmem_cache_alloc(s, GFP_KERNEL);
p[64] = 0x12;
validate_slab_cache(s);
KUNIT_EXPECT_EQ(test, 1, s->errors);
kmem_cache_free(s, p);
kmem_cache_destroy(s);
}
static void test_next_pointer(struct kunit *test)
{
struct kmem_cache *s = kmem_cache_create("TestSlub_next_ptr_free", 64, 0,
SLAB_POISON | SLAB_SILENT_ERRORS, NULL);
u8 *p = kmem_cache_alloc(s, GFP_KERNEL);
unsigned long tmp;
unsigned long *ptr_addr;
kmem_cache_free(s, p);
ptr_addr = (unsigned long *)(p + s->offset);
tmp = *ptr_addr;
p[s->offset] = 0x12;
/*
* Expecting two errors.
* One for the corrupted freechain and the other one for the wrong
* count of objects in use.
*/
validate_slab_cache(s);
KUNIT_EXPECT_EQ(test, 2, s->errors);
/*
* Try to repair corrupted freepointer.
* Still expecting one error for the wrong count of objects in use.
*/
*ptr_addr = tmp;
validate_slab_cache(s);
KUNIT_EXPECT_EQ(test, 1, s->errors);
/*
* Previous validation repaired the count of objects in use.
* Now expecting no error.
*/
validate_slab_cache(s);
KUNIT_EXPECT_EQ(test, 0, s->errors);
kmem_cache_destroy(s);
}
static void test_first_word(struct kunit *test)
{
struct kmem_cache *s = kmem_cache_create("TestSlub_1th_word_free", 64, 0,
SLAB_POISON | SLAB_SILENT_ERRORS, NULL);
u8 *p = kmem_cache_alloc(s, GFP_KERNEL);
kmem_cache_free(s, p);
*p = 0x78;
validate_slab_cache(s);
KUNIT_EXPECT_EQ(test, 1, s->errors);
kmem_cache_destroy(s);
}
static void test_clobber_50th_byte(struct kunit *test)
{
struct kmem_cache *s = kmem_cache_create("TestSlub_50th_word_free", 64, 0,
SLAB_POISON | SLAB_SILENT_ERRORS, NULL);
u8 *p = kmem_cache_alloc(s, GFP_KERNEL);
kmem_cache_free(s, p);
p[50] = 0x9a;
validate_slab_cache(s);
KUNIT_EXPECT_EQ(test, 1, s->errors);
kmem_cache_destroy(s);
}
static void test_clobber_redzone_free(struct kunit *test)
{
struct kmem_cache *s = kmem_cache_create("TestSlub_RZ_free", 64, 0,
SLAB_RED_ZONE | SLAB_SILENT_ERRORS, NULL);
u8 *p = kmem_cache_alloc(s, GFP_KERNEL);
kmem_cache_free(s, p);
p[64] = 0xab;
validate_slab_cache(s);
KUNIT_EXPECT_EQ(test, 1, s->errors);
kmem_cache_destroy(s);
}
static struct kunit_case test_cases[] = {
KUNIT_CASE(test_clobber_zone),
KUNIT_CASE(test_next_pointer),
KUNIT_CASE(test_first_word),
KUNIT_CASE(test_clobber_50th_byte),
KUNIT_CASE(test_clobber_redzone_free),
{}
};
static struct kunit_suite test_suite = {
.name = "slub_test",
.test_cases = test_cases,
};
kunit_test_suite(test_suite);
MODULE_LICENSE("GPL");