1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2026, Linutronix GmbH 4 */ 5 6 #include <asan.h> 7 #include <asan_test.h> 8 #include <setjmp.h> 9 #include <malloc.h> 10 #include <config.h> 11 #include <util.h> 12 #include <trace.h> 13 14 #define ASAN_TEST_SUCCESS 1 15 #define ASAN_TEST_BUF_SIZE 15 16 17 static char asan_test_sgbuf[ASAN_TEST_BUF_SIZE]; 18 char asan_test_gbuf[ASAN_TEST_BUF_SIZE]; 19 static const char asan_test_sgbuf_ro[ASAN_TEST_BUF_SIZE + 1]; 20 21 static jmp_buf asan_test_jmp; 22 23 static void asan_out_of_bounds_write(char *buf, size_t pos, 24 char value) 25 { 26 buf[pos] = value; 27 } 28 29 static char asan_out_of_bounds_read(char *buf, size_t pos) 30 { 31 return buf[pos]; 32 } 33 34 static void *asan_out_of_bounds_memcpy(void *__restrict dst, 35 const void *__restrict src, 36 size_t size) 37 { 38 return memcpy(dst, src, size); 39 } 40 41 static void *asan_out_of_bounds_memset(void *buf, int val, size_t size) 42 { 43 return memset(buf, val, size); 44 } 45 46 static void asan_panic_test(void) 47 { 48 longjmp(asan_test_jmp, ASAN_TEST_SUCCESS); 49 } 50 51 static void asan_test_cleanup(struct asan_test_ctx *ctx) 52 { 53 unsigned int i = 0; 54 55 free(ctx->pmalloc1); 56 57 for (; i < ARRAY_SIZE(ctx->pmalloc2); i++) 58 free(ctx->pmalloc2[i]); 59 } 60 61 void asan_test_stack(struct asan_test_ctx *ctx) 62 { 63 char buf[ASAN_TEST_BUF_SIZE] = {0}; 64 65 ctx->write_func(buf, ASAN_TEST_BUF_SIZE, ctx->write_value); 66 } 67 68 void asan_test_global_stat(struct asan_test_ctx *ctx) 69 { 70 ctx->write_func(asan_test_sgbuf, ASAN_TEST_BUF_SIZE, 71 ctx->write_value); 72 } 73 74 void asan_test_global_ro(struct asan_test_ctx *ctx) 75 { 76 ctx->read_func((char *)asan_test_sgbuf_ro, 77 ASAN_TEST_BUF_SIZE + 1); 78 } 79 80 void asan_test_global(struct asan_test_ctx *ctx) 81 { 82 ctx->write_func(asan_test_gbuf, ASAN_TEST_BUF_SIZE, 83 ctx->write_value); 84 } 85 86 void asan_test_malloc(struct asan_test_ctx *ctx) 87 { 88 ctx->pmalloc1 = malloc(ASAN_TEST_BUF_SIZE); 89 90 if (ctx->pmalloc1) 91 ctx->write_func(ctx->pmalloc1, ASAN_TEST_BUF_SIZE, 92 ctx->write_value); 93 } 94 95 void asan_test_malloc2(struct asan_test_ctx *ctx) 96 { 97 size_t aligned_size = ROUNDUP(ASAN_TEST_BUF_SIZE, 8); 98 unsigned int i = 0; 99 char *p = NULL; 100 101 for (; i < ARRAY_SIZE(ctx->pmalloc2); i++) { 102 ctx->pmalloc2[i] = malloc(aligned_size); 103 if (!ctx->pmalloc2[i]) 104 return; 105 } 106 p = ctx->pmalloc2[1]; 107 ctx->write_func(p, aligned_size, ctx->write_value); 108 } 109 110 void asan_test_use_after_free(struct asan_test_ctx *ctx) 111 { 112 char *a = malloc(ASAN_TEST_BUF_SIZE); 113 114 if (a) { 115 ctx->free_func(a); 116 ctx->write_func(a, 0, ctx->write_value); 117 } 118 } 119 120 void asan_test_memcpy_dst(struct asan_test_ctx *ctx) 121 { 122 static char b[ASAN_TEST_BUF_SIZE + 1]; 123 static char a[ASAN_TEST_BUF_SIZE]; 124 125 ctx->memcpy_func(a, b, sizeof(b)); 126 } 127 128 void asan_test_memcpy_src(struct asan_test_ctx *ctx) 129 { 130 static char a[ASAN_TEST_BUF_SIZE + 1]; 131 static char b[ASAN_TEST_BUF_SIZE]; 132 133 ctx->memcpy_func(a, b, sizeof(a)); 134 } 135 136 void asan_test_memset(struct asan_test_ctx *ctx) 137 { 138 static char b[ASAN_TEST_BUF_SIZE]; 139 140 ctx->memset_func(b, ctx->write_value, ASAN_TEST_BUF_SIZE + 1); 141 } 142 143 static void asan_test_free(void *ptr) 144 { 145 free(ptr); 146 } 147 148 void asan_test_init(struct asan_test_ctx *ctx) 149 { 150 ctx->write_value = 0xab; 151 ctx->write_func = asan_out_of_bounds_write; 152 ctx->read_func = asan_out_of_bounds_read; 153 ctx->memcpy_func = asan_out_of_bounds_memcpy; 154 ctx->memset_func = asan_out_of_bounds_memset; 155 ctx->free_func = asan_test_free; 156 157 asan_set_panic_cb(asan_panic_test); 158 } 159 160 void asan_test_deinit(struct asan_test_ctx *ctx) 161 { 162 asan_test_cleanup(ctx); 163 asan_set_panic_cb(asan_panic); 164 } 165 166 int asan_call_test(struct asan_test_ctx *ctx, 167 void (*test)(struct asan_test_ctx *ctx), 168 const char __unused *desc) 169 { 170 int ret = 0; 171 172 ret = setjmp(asan_test_jmp); 173 if (ret == 0) { 174 test(ctx); 175 ret = -1; 176 } else if (ret == ASAN_TEST_SUCCESS) { 177 ret = 0; 178 } else { 179 asan_panic(); 180 } 181 IMSG(" => [asan] test %s: %s", desc, !ret ? "ok" : "FAILED"); 182 183 return ret; 184 } 185