Skip to content

Commit 85ad50c

Browse files
Gary-Hobsonxiaoxiang781216
authored andcommitted
testing: refactor kasan test
Signed-off-by: yinshengkai <[email protected]>
1 parent 7cd9919 commit 85ad50c

File tree

1 file changed

+187
-89
lines changed

1 file changed

+187
-89
lines changed

testing/kasantest/kasantest.c

Lines changed: 187 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -22,154 +22,252 @@
2222
* Included Files
2323
****************************************************************************/
2424

25-
#include <nuttx/config.h>
26-
#include <nuttx/mm/kasan.h>
27-
25+
#include <assert.h>
26+
#include <malloc.h>
27+
#include <pthread.h>
28+
#include <stdint.h>
2829
#include <stdio.h>
30+
#include <stdlib.h>
31+
#include <sys/types.h>
2932
#include <syslog.h>
30-
#include <pthread.h>
33+
34+
#include <sys/param.h>
35+
#include <sys/wait.h>
36+
37+
#include <nuttx/fs/procfs.h>
38+
#include <nuttx/mm/mm.h>
39+
#include <nuttx/mm/kasan.h>
40+
41+
/****************************************************************************
42+
* Private Types Prototypes
43+
****************************************************************************/
44+
45+
typedef struct testcase_s
46+
{
47+
bool (*func)(FAR struct mm_heap_s *heap, size_t size);
48+
FAR const char *name;
49+
} testcase_t;
50+
51+
typedef struct run_s
52+
{
53+
char argv[16];
54+
FAR const testcase_t *testcase;
55+
FAR struct mm_heap_s *heap;
56+
size_t size;
57+
} run_t;
3158

3259
/****************************************************************************
33-
* Pre-processor Definitions
60+
* Private Function Prototypes
3461
****************************************************************************/
3562

36-
#define KASAN_TEST_MEM_SIZE 128
63+
static bool test_heap_underflow(FAR struct mm_heap_s *heap, size_t size);
64+
static bool test_heap_overflow(FAR struct mm_heap_s *heap, size_t size);
65+
static bool test_heap_use_after_free(FAR struct mm_heap_s *heap,
66+
size_t size);
67+
static bool test_heap_invalid_free(FAR struct mm_heap_s *heap, size_t size);
68+
static bool test_heap_double_free(FAR struct mm_heap_s *heap, size_t size);
69+
static bool test_heap_poison(FAR struct mm_heap_s *heap, size_t size);
70+
static bool test_heap_unpoison(FAR struct mm_heap_s *heap, size_t size);
71+
static bool test_heap_memset(FAR struct mm_heap_s *heap, size_t size);
72+
static bool test_heap_memcpy(FAR struct mm_heap_s *heap, size_t size);
73+
static bool test_heap_memmove(FAR struct mm_heap_s *heap, size_t size);
3774

3875
/****************************************************************************
3976
* Private Data
4077
****************************************************************************/
4178

42-
static char g_kasan_test_buffer[KASAN_TEST_MEM_SIZE];
79+
const static testcase_t g_kasan_test[] =
80+
{
81+
{test_heap_underflow, "heap underflow"},
82+
{test_heap_overflow, "heap overflow"},
83+
{test_heap_use_after_free, "heap use after free"},
84+
{test_heap_invalid_free, "heap inval free"},
85+
{test_heap_double_free, "test heap double free"},
86+
{test_heap_poison, "heap poison"},
87+
{test_heap_unpoison, "heap unpoison"},
88+
{test_heap_memset, "heap memset"},
89+
{test_heap_memcpy, "heap memcpy"},
90+
{test_heap_memmove, "heap memmove"}
91+
};
4392

4493
/****************************************************************************
4594
* Private Functions
4695
****************************************************************************/
4796

48-
static void kasan_test(char *p, size_t size)
97+
static bool test_heap_underflow(FAR struct mm_heap_s *heap, size_t size)
4998
{
50-
size_t i;
99+
FAR uint8_t *mem = mm_malloc(heap, size);
100+
*(mem - 1) = 0x12;
101+
return false;
102+
}
51103

52-
for (i = 0; i < size + 64; i++)
53-
{
54-
syslog(LOG_SYSLOG,
55-
"Access Buffer[%zu] : %zu address: %p", size, i, &p[i]);
56-
p[i]++;
57-
syslog(LOG_SYSLOG, "read: %02x -- Successful\n", p[i]);
58-
}
104+
static bool test_heap_overflow(FAR struct mm_heap_s *heap, size_t size)
105+
{
106+
FAR uint8_t *mem = mm_malloc(heap, size);
107+
size = mm_malloc_size(heap, mem);
108+
109+
mem[size + 1] = 0x11;
110+
return false;
59111
}
60112

61-
static void kasan_test_use_after_free(void)
113+
static bool test_heap_use_after_free(FAR struct mm_heap_s *heap, size_t size)
62114
{
63-
char *ptr = malloc(KASAN_TEST_MEM_SIZE);
115+
FAR uint8_t *mem = mm_malloc(heap, size);
64116

65-
if (ptr == NULL)
66-
{
67-
syslog(LOG_SYSLOG, "Failed to allocate memory\n");
68-
return;
69-
}
117+
mm_free(heap, mem);
118+
mem[0] = 0x10;
119+
return 0;
120+
}
70121

71-
syslog(LOG_SYSLOG, "KASan test use after free\n");
72-
strcpy(ptr, "kasan test use after free");
73-
free(ptr);
74-
printf("%s\n", ptr);
122+
static bool test_heap_invalid_free(FAR struct mm_heap_s *heap, size_t size)
123+
{
124+
int x;
125+
mm_free(heap, &x);
126+
return false;
75127
}
76128

77-
static void kasan_test_heap_memory_out_of_bounds(char *str)
129+
static bool test_heap_double_free(FAR struct mm_heap_s *heap, size_t size)
78130
{
79-
char *endptr;
80-
size_t size;
81-
char *ptr;
131+
uint8_t *mem = mm_malloc(heap, size);
82132

83-
size = strtoul(str, &endptr, 0);
84-
if (*endptr != '\0')
85-
{
86-
printf("Conversion failed: Not a valid integer.\n");
87-
return;
88-
}
133+
mm_free(heap, mem);
134+
mm_free(heap, mem);
135+
return false;
136+
}
89137

90-
ptr = zalloc(size);
91-
if (ptr == NULL)
92-
{
93-
syslog(LOG_SYSLOG, "Failed to allocate memory\n");
94-
return;
95-
}
138+
static bool test_heap_poison(FAR struct mm_heap_s *heap, size_t size)
139+
{
140+
FAR uint8_t *mem = mm_malloc(heap, size);
141+
size = mm_malloc_size(heap, mem);
96142

97-
syslog(LOG_SYSLOG,
98-
"KASan test accessing heap memory out of bounds completed\n");
99-
kasan_test(ptr, size);
143+
kasan_poison(mem, size);
144+
mem[0] = 0x10;
145+
return false;
100146
}
101147

102-
static void kasan_test_global_variable_out_of_bounds(void)
148+
static bool test_heap_unpoison(FAR struct mm_heap_s *heap, size_t size)
103149
{
104-
syslog(LOG_SYSLOG,
105-
"KASan test accessing global variable out of bounds\n");
106-
kasan_test(g_kasan_test_buffer, KASAN_TEST_MEM_SIZE);
150+
FAR uint8_t *mem = mm_malloc(heap, size);
151+
size_t memsize = mm_malloc_size(heap, mem);
152+
153+
kasan_poison(mem, memsize);
154+
kasan_unpoison(mem, memsize);
155+
mem[0] = 0x10;
156+
return true;
107157
}
108158

109-
static void *mm_stampede_thread(void *arg)
159+
static bool test_heap_memset(FAR struct mm_heap_s *heap, size_t size)
110160
{
111-
char *p = (char *)arg;
161+
FAR uint8_t *mem = mm_malloc(heap, size);
162+
size = mm_malloc_size(heap, mem);
112163

113-
syslog(LOG_SYSLOG, "Child thread is running");
114-
kasan_test(p, KASAN_TEST_MEM_SIZE);
115-
pthread_exit(NULL);
164+
memset(mem, 0x11, size + 1);
165+
return false;
116166
}
117167

118-
static void kasan_test_memory_stampede(void)
168+
static bool test_heap_memcpy(FAR struct mm_heap_s *heap, size_t size)
119169
{
120-
pthread_t thread;
121-
char array[KASAN_TEST_MEM_SIZE];
170+
FAR uint8_t *src;
171+
FAR uint8_t *dst;
122172

123-
syslog(LOG_SYSLOG, "KASan test accessing memory stampede\n");
124-
pthread_create(&thread, NULL, mm_stampede_thread, kasan_reset_tag(&array));
125-
pthread_join(thread, NULL);
173+
size = size / 2;
174+
src = mm_malloc(heap, size);
175+
size = mm_malloc_size(heap, src);
176+
dst = mm_malloc(heap, size);
177+
178+
memcpy(dst, src, size);
179+
memcpy(dst, src, size + 4);
180+
return false;
126181
}
127182

128-
/****************************************************************************
129-
* Public Functions
130-
****************************************************************************/
183+
static bool test_heap_memmove(FAR struct mm_heap_s *heap, size_t size)
184+
{
185+
FAR uint8_t *src;
186+
FAR uint8_t *dst;
131187

132-
/****************************************************************************
133-
* Name: kasantest_main
134-
****************************************************************************/
188+
size = size / 2;
189+
src = mm_malloc(heap, size);
190+
size = mm_malloc_size(heap, src);
191+
dst = mm_malloc(heap, size);
192+
193+
memmove(dst, src, size);
194+
memmove(dst, src, size + 4);
195+
return false;
196+
}
197+
198+
static int run_testcase(int argc, FAR char *argv[])
199+
{
200+
FAR run_t *run = (FAR run_t *)(uintptr_t)strtoul(argv[1], NULL, 0);
201+
return run->testcase->func(run->heap, run->size);
202+
}
135203

136-
int main(int argc, char *argv[])
204+
static int run_test(FAR const testcase_t *test)
137205
{
138-
/* NutttX cannot check the secondary release
139-
* because the mm module has closed kasan instrumentation
206+
size_t heap_size = 65536;
207+
FAR char *argv[3];
208+
FAR run_t *run;
209+
int status;
210+
pid_t pid;
211+
212+
/* There is a memory leak here because we cannot guarantee that
213+
* it can be released correctly.
140214
*/
141215

142-
if (argc < 2)
216+
run = malloc(sizeof(run_t) + heap_size);
217+
if (!run)
143218
{
144-
printf("Usage: %s <test_option>\n", argv[0]);
145-
printf("Available test options:\n");
146-
printf(" -u : Test use after free\n");
147-
printf(" -h <arg> : Test heap memory out of bounds (provide size)\n");
148-
printf(" -g : Test global variable out of bounds\n");
149-
printf(" -s : Test memory stampede\n");
150-
return 0;
219+
return ERROR;
151220
}
152-
else if (strncmp(argv[1], "-u", 2) == 0)
221+
222+
snprintf(run->argv, sizeof(run->argv), "%p", run);
223+
run->testcase = test;
224+
run->size = rand() % (heap_size / 2) + 1;
225+
run->heap = mm_initialize("kasan", &run[1], heap_size);
226+
if (!run->heap)
153227
{
154-
kasan_test_use_after_free();
228+
free(run);
229+
return ERROR;
155230
}
156-
else if (strncmp(argv[1], "-h", 2) == 0 && argc == 3)
231+
232+
argv[0] = "kasantest";
233+
argv[1] = run->argv;
234+
argv[2] = NULL;
235+
236+
posix_spawn(&pid, "kasantest", NULL, NULL, argv, NULL);
237+
waitpid(pid, &status, 0);
238+
if (status == 0)
157239
{
158-
kasan_test_heap_memory_out_of_bounds(argv[2]);
240+
printf("KASan test: %s, size: %d FAIL\n", test->name, run->size);
159241
}
160-
else if (strncmp(argv[1], "-g", 2) == 0)
242+
else
161243
{
162-
kasan_test_global_variable_out_of_bounds();
244+
printf("KASan test: %s, size: %d PASS\n", test->name, run->size);
163245
}
164-
else if (strncmp(argv[1], "-s", 2) == 0)
246+
247+
return 0;
248+
}
249+
250+
/****************************************************************************
251+
* Public Functions
252+
****************************************************************************/
253+
254+
int main(int argc, FAR char *argv[])
255+
{
256+
if (argc < 2)
165257
{
166-
kasan_test_memory_stampede();
258+
size_t j;
259+
for (j = 0; j < nitems(g_kasan_test); j++)
260+
{
261+
if (run_test(&g_kasan_test[j]) < 0)
262+
{
263+
return EXIT_FAILURE;
264+
}
265+
}
167266
}
168267
else
169268
{
170-
printf("Unknown test option: %s\n", argv[1]);
269+
return run_testcase(argc, argv);
171270
}
172271

173-
syslog(LOG_SYSLOG, "KASan test failed, please check\n");
174-
return 0;
272+
return EXIT_SUCCESS;
175273
}

0 commit comments

Comments
 (0)