1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2014, STMicroelectronics International N.V. 4 */ 5 #include <assert.h> 6 #include <malloc.h> 7 #include <stdbool.h> 8 #include <trace.h> 9 #include <kernel/panic.h> 10 #include <util.h> 11 12 #include "misc.h" 13 14 /* 15 * Enable expect LOG macro to enable/disable self tests traces. 16 * 17 * #define LOG DMSG_RAW 18 * #define LOG(...) 19 */ 20 #define LOG(...) 21 22 static int self_test_add_overflow(void) 23 { 24 uint32_t r_u32; 25 int32_t r_s32; 26 uintmax_t r_um; 27 intmax_t r_sm; 28 29 if (ADD_OVERFLOW(8U, 0U, &r_s32)) 30 return -1; 31 if (r_s32 != 8) 32 return -1; 33 if (ADD_OVERFLOW(32U, 30U, &r_u32)) 34 return -1; 35 if (r_u32 != 62) 36 return -1; 37 if (!ADD_OVERFLOW(UINT32_MAX, UINT32_MAX, &r_u32)) 38 return -1; 39 if (!ADD_OVERFLOW(UINT32_MAX / 2 + 1, UINT32_MAX / 2 + 1, &r_u32)) 40 return -1; 41 if (ADD_OVERFLOW(UINT32_MAX / 2, UINT32_MAX / 2 + 1, &r_u32)) 42 return -1; 43 if (r_u32 != UINT32_MAX) 44 return -1; 45 46 if (ADD_OVERFLOW((uint32_t)30, (int32_t)-31, &r_s32)) 47 return -1; 48 if (r_s32 != -1) 49 return -1; 50 if (ADD_OVERFLOW((int32_t)30, (int32_t)-31, &r_s32)) 51 return -1; 52 if (r_s32 != -1) 53 return -1; 54 if (ADD_OVERFLOW((int32_t)-31, (uint32_t)30, &r_s32)) 55 return -1; 56 if (r_s32 != -1) 57 return -1; 58 59 if (ADD_OVERFLOW(INT32_MIN + 1, -1, &r_s32)) 60 return -1; 61 if (r_s32 != INT32_MIN) 62 return -1; 63 if (!ADD_OVERFLOW(INT32_MIN, -1, &r_s32)) 64 return -1; 65 if (!ADD_OVERFLOW(INT32_MIN + 1, -2, &r_s32)) 66 return -1; 67 if (!ADD_OVERFLOW(INT32_MAX, INT32_MAX, &r_s32)) 68 return -1; 69 if (ADD_OVERFLOW(INT32_MAX, INT32_MAX, &r_u32)) 70 return -1; 71 if (!ADD_OVERFLOW(INTMAX_MAX, INTMAX_MAX, &r_sm)) 72 return -1; 73 if (ADD_OVERFLOW(INTMAX_MAX, INTMAX_MAX, &r_um)) 74 return -1; 75 if (!ADD_OVERFLOW(INT32_MAX / 2 + 1, INT32_MAX / 2 + 1, &r_s32)) 76 return -1; 77 if (ADD_OVERFLOW(INT32_MAX / 2, INT32_MAX / 2 + 1, &r_s32)) 78 return -1; 79 if (r_s32 != INT32_MAX) 80 return -1; 81 82 return 0; 83 } 84 85 static int self_test_sub_overflow(void) 86 { 87 uint32_t r_u32; 88 int32_t r_s32; 89 intmax_t r_sm; 90 91 if (SUB_OVERFLOW(8U, 1U, &r_s32)) 92 return -1; 93 if (r_s32 != 7) 94 return -1; 95 if (SUB_OVERFLOW(32U, 30U, &r_u32)) 96 return -1; 97 if (r_u32 != 2) 98 return -1; 99 if (!SUB_OVERFLOW(30U, 31U, &r_u32)) 100 return -1; 101 102 if (SUB_OVERFLOW(30, 31, &r_s32)) 103 return -1; 104 if (r_s32 != -1) 105 return -1; 106 if (SUB_OVERFLOW(-1, INT32_MAX, &r_s32)) 107 return -1; 108 if (r_s32 != INT32_MIN) 109 return -1; 110 if (!SUB_OVERFLOW(-2, INT32_MAX, &r_s32)) 111 return -1; 112 113 if (SUB_OVERFLOW((uint32_t)30, (int32_t)-31, &r_s32)) 114 return -1; 115 if (r_s32 != 61) 116 return -1; 117 if (SUB_OVERFLOW((int32_t)30, (int32_t)-31, &r_s32)) 118 return -1; 119 if (r_s32 != 61) 120 return -1; 121 if (SUB_OVERFLOW((int32_t)-31, (uint32_t)30, &r_s32)) 122 return -1; 123 if (r_s32 != -61) 124 return -1; 125 if (SUB_OVERFLOW((int32_t)-31, (int32_t)-30, &r_s32)) 126 return -1; 127 if (r_s32 != -1) 128 return -1; 129 130 if (SUB_OVERFLOW((int32_t)31, -(INTMAX_MIN + 1), &r_sm)) 131 return -1; 132 if (r_sm != (INTMAX_MIN + 32)) 133 return -1; 134 135 return 0; 136 } 137 138 static int self_test_mul_unsigned_overflow(void) 139 { 140 const size_t um_half_shift = sizeof(uintmax_t) * 8 / 2; 141 const uintmax_t um_half_mask = UINTMAX_MAX >> um_half_shift; 142 uint32_t r_u32; 143 uintmax_t r_um; 144 145 if (MUL_OVERFLOW(32, 30, &r_u32)) 146 return -1; 147 if (r_u32 != 960) 148 return -1; 149 if (MUL_OVERFLOW(-32, -30, &r_u32)) 150 return -1; 151 if (r_u32 != 960) 152 return -1; 153 154 if (MUL_OVERFLOW(UINTMAX_MAX, 1, &r_um)) 155 return -1; 156 if (r_um != UINTMAX_MAX) 157 return -1; 158 if (MUL_OVERFLOW(UINTMAX_MAX / 4, 4, &r_um)) 159 return -1; 160 if (r_um != (UINTMAX_MAX - 3)) 161 return -1; 162 if (!MUL_OVERFLOW(UINTMAX_MAX / 4 + 1, 4, &r_um)) 163 return -1; 164 if (!MUL_OVERFLOW(UINTMAX_MAX, UINTMAX_MAX, &r_um)) 165 return -1; 166 if (!MUL_OVERFLOW(um_half_mask << um_half_shift, 167 um_half_mask << um_half_shift, &r_um)) 168 return -1; 169 170 return 0; 171 } 172 173 static int self_test_mul_signed_overflow(void) 174 { 175 intmax_t r; 176 177 if (MUL_OVERFLOW(32, -30, &r)) 178 return -1; 179 if (r != -960) 180 return -1; 181 if (MUL_OVERFLOW(-32, 30, &r)) 182 return -1; 183 if (r != -960) 184 return -1; 185 if (MUL_OVERFLOW(32, 30, &r)) 186 return -1; 187 if (r != 960) 188 return -1; 189 190 if (MUL_OVERFLOW(INTMAX_MAX, 1, &r)) 191 return -1; 192 if (r != INTMAX_MAX) 193 return -1; 194 if (MUL_OVERFLOW(INTMAX_MAX / 4, 4, &r)) 195 return -1; 196 if (r != (INTMAX_MAX - 3)) 197 return -1; 198 if (!MUL_OVERFLOW(INTMAX_MAX / 4 + 1, 4, &r)) 199 return -1; 200 if (!MUL_OVERFLOW(INTMAX_MAX, INTMAX_MAX, &r)) 201 return -1; 202 if (MUL_OVERFLOW(INTMAX_MIN + 1, 1, &r)) 203 return -1; 204 if (r != INTMAX_MIN + 1) 205 return -1; 206 if (MUL_OVERFLOW(1, INTMAX_MIN + 1, &r)) 207 return -1; 208 if (r != INTMAX_MIN + 1) 209 return -1; 210 if (MUL_OVERFLOW(0, INTMAX_MIN, &r)) 211 return -1; 212 if (r != 0) 213 return -1; 214 if (MUL_OVERFLOW(1, INTMAX_MIN, &r)) 215 return -1; 216 if (r != INTMAX_MIN) 217 return -1; 218 219 return 0; 220 } 221 222 /* test division support. resulting trace shall be manually checked */ 223 static int self_test_division(void) 224 { 225 signed a, b, c, d; 226 bool r; 227 int ret = 0; 228 229 LOG(""); 230 LOG("division tests (division and modulo):"); 231 /* get some unpredicted values to prevent compilation optimizations: */ 232 /* => use the stack address */ 233 234 LOG("- test with unsigned small integers:"); 235 a = (signed)((unsigned)(vaddr_t)&a & 0xFFFFF); 236 b = (signed)((unsigned)(vaddr_t)&b & 0x00FFF) + 1; 237 c = a / b; 238 d = a % b; 239 r = ((b * c + d) == a); 240 if (!r) 241 ret = -1; 242 LOG(" 0x%08x / 0x%08x = %u / %u = %u = 0x%x)", 243 (unsigned)a, (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)c, 244 (unsigned)c); 245 LOG(" 0x%08x %% 0x%08x = %u %% %u = %u = 0x%x)", (unsigned)a, 246 (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)d, (unsigned)d); 247 LOG(" check results => %s", r ? "ok" : "FAILED !!!"); 248 LOG(""); 249 250 LOG("- test with signed small integers, negative numerator:"); 251 a = (signed)(vaddr_t)&a; 252 b = (signed)((unsigned)(vaddr_t)&b & 0x00FFF) - 1; 253 c = a / b; 254 d = a % b; 255 r = ((b * c + d) == a); 256 if (!r) 257 ret = -1; 258 LOG(" 0x%08x / 0x%08x = %d / %d = %d = 0x%x)", 259 (unsigned)a, (unsigned)b, (signed)a, (signed)b, (signed)c, 260 (unsigned)c); 261 LOG(" 0x%08x %% 0x%08x = %d %% %d = %d = 0x%x)", (unsigned)a, 262 (unsigned)b, (signed)a, (signed)b, (signed)d, (unsigned)d); 263 LOG(" check results => %s", r ? "ok" : "FAILED !!!"); 264 LOG(""); 265 266 LOG("- test with signed small integers, negative denominator:"); 267 a = (signed)((unsigned)(vaddr_t)&a & 0xFFFFF); 268 b = -(signed)((unsigned)(vaddr_t)&b & 0x00FFF) + 1; 269 c = a / b; 270 d = a % b; 271 272 LOG("- test with unsigned integers, big numerator (> 0x80000000):"); 273 a = (signed)(vaddr_t)&a; 274 b = (signed)((unsigned)(vaddr_t)&b & 0x00FFF) + 1; 275 c = (signed)((unsigned)a / (unsigned)b); 276 d = (signed)((unsigned)a % (unsigned)b); 277 r = (((unsigned)b * (unsigned)c + (unsigned)d) == (unsigned)a); 278 if (!r) 279 ret = -1; 280 LOG(" 0x%08x / 0x%08x = %u / %u = %u = 0x%x)", 281 (unsigned)a, (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)c, 282 (unsigned)c); 283 LOG(" 0x%08x %% 0x%08x = %u %% %u = %u = 0x%x)", (unsigned)a, 284 (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)d, (unsigned)d); 285 LOG(" check results => %s", r ? "ok" : "FAILED !!!"); 286 LOG(""); 287 288 LOG("- test with unsigned integers, big num. & denom. (> 0x80000000):"); 289 a = (signed)(vaddr_t)&a; 290 b = (signed)((unsigned)(vaddr_t)&a - 1); 291 c = (signed)((unsigned)a / (unsigned)b); 292 d = (signed)((unsigned)a % (unsigned)b); 293 r = (((unsigned)b * (unsigned)c + (unsigned)d) == (unsigned)a); 294 if (!r) 295 ret = -1; 296 LOG(" 0x%08x / 0x%08x = %u / %u = %u = 0x%x)", 297 (unsigned)a, (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)c, 298 (unsigned)c); 299 LOG(" 0x%08x %% 0x%08x = %u %% %u = %u = 0x%x)", (unsigned)a, 300 (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)d, (unsigned)d); 301 LOG(" check results => %s", r ? "ok" : "FAILED !!!"); 302 LOG(""); 303 304 return ret; 305 } 306 307 /* test malloc support. resulting trace shall be manually checked */ 308 static int self_test_malloc(void) 309 { 310 char *p1 = NULL, *p2 = NULL; 311 int *p3 = NULL, *p4 = NULL; 312 bool r; 313 int ret = 0; 314 315 LOG("malloc tests (malloc, free, calloc, realloc):"); 316 LOG(" p1=%p p2=%p p3=%p p4=%p", 317 (void *)p1, (void *)p2, (void *)p3, (void *)p4); 318 /* test malloc */ 319 p1 = malloc(1024); 320 LOG("- p1 = malloc(1024)"); 321 p2 = malloc(1024); 322 LOG("- p2 = malloc(1024)"); 323 LOG(" p1=%p p2=%p p3=%p p4=%p", 324 (void *)p1, (void *)p2, (void *)p3, (void *)p4); 325 r = (p1 && p2 && malloc_buffer_is_within_alloced(p1, 1024) && 326 !malloc_buffer_is_within_alloced(p1 + 25, 1000) && 327 !malloc_buffer_is_within_alloced(p1 - 25, 500) && 328 malloc_buffer_overlaps_heap(p1 - 25, 500)); 329 if (!r) 330 ret = -1; 331 LOG(" => test %s", r ? "ok" : "FAILED"); 332 LOG(""); 333 334 /* test realloc */ 335 p3 = realloc(p1, 3 * 1024); 336 if (p3) 337 p1 = NULL; 338 LOG("- p3 = realloc(p1, 3*1024)"); 339 LOG("- free p2"); 340 free(p2); 341 p2 = malloc(1024); 342 LOG("- p2 = malloc(1024)"); 343 LOG(" p1=%p p2=%p p3=%p p4=%p", 344 (void *)p1, (void *)p2, (void *)p3, (void *)p4); 345 r = (p2 && p3); 346 if (!r) 347 ret = -1; 348 LOG(" => test %s", r ? "ok" : "FAILED"); 349 LOG(""); 350 LOG("- free p1, p2, p3"); 351 free(p1); 352 free(p2); 353 free(p3); 354 p1 = NULL; 355 p2 = NULL; 356 p3 = NULL; 357 358 /* test calloc */ 359 p3 = calloc(4, 1024); 360 p4 = calloc(0x100, 1024 * 1024); 361 LOG("- p3 = calloc(4, 1024)"); 362 LOG("- p4 = calloc(0x100, 1024*1024) too big: should fail!"); 363 LOG(" p1=%p p2=%p p3=%p p4=%p", 364 (void *)p1, (void *)p2, (void *)p3, (void *)p4); 365 r = (p3 && !p4); 366 if (!r) 367 ret = -1; 368 LOG(" => test %s", r ? "ok" : "FAILED"); 369 LOG(""); 370 LOG("- free p3, p4"); 371 free(p3); 372 free(p4); 373 p3 = NULL; 374 p4 = NULL; 375 376 /* test free(NULL) */ 377 LOG("- free NULL"); 378 free(NULL); 379 LOG(""); 380 LOG("malloc test done"); 381 382 return ret; 383 } 384 385 #ifdef CFG_VIRTUALIZATION 386 /* test nex_malloc support. resulting trace shall be manually checked */ 387 static int self_test_nex_malloc(void) 388 { 389 char *p1 = NULL, *p2 = NULL; 390 int *p3 = NULL, *p4 = NULL; 391 bool r; 392 int ret = 0; 393 394 LOG("nex_malloc tests (nex_malloc, nex_free, nex_calloc, nex_realloc):"); 395 LOG(" p1=%p p2=%p p3=%p p4=%p", 396 (void *)p1, (void *)p2, (void *)p3, (void *)p4); 397 /* test malloc */ 398 p1 = nex_malloc(1024); 399 LOG("- p1 = nex_malloc(1024)"); 400 p2 = nex_malloc(1024); 401 LOG("- p2 = nex_malloc(1024)"); 402 LOG(" p1=%p p2=%p p3=%p p4=%p", 403 (void *)p1, (void *)p2, (void *)p3, (void *)p4); 404 r = (p1 && p2 && nex_malloc_buffer_is_within_alloced(p1, 1024) && 405 !nex_malloc_buffer_is_within_alloced(p1 + 25, 1000) && 406 !nex_malloc_buffer_is_within_alloced(p1 - 25, 500) && 407 nex_malloc_buffer_overlaps_heap(p1 - 25, 500)); 408 if (!r) 409 ret = -1; 410 LOG(" => test %s", r ? "ok" : "FAILED"); 411 LOG(""); 412 413 /* test realloc */ 414 p3 = nex_realloc(p1, 3 * 1024); 415 if (p3) 416 p1 = NULL; 417 LOG("- p3 = nex_realloc(p1, 3*1024)"); 418 LOG("- nex_free p2"); 419 nex_free(p2); 420 p2 = nex_malloc(1024); 421 LOG("- p2 = nex_malloc(1024)"); 422 LOG(" p1=%p p2=%p p3=%p p4=%p", 423 (void *)p1, (void *)p2, (void *)p3, (void *)p4); 424 r = (p2 && p3); 425 if (!r) 426 ret = -1; 427 LOG(" => test %s", r ? "ok" : "FAILED"); 428 LOG(""); 429 LOG("- nex_free p1, p2, p3"); 430 nex_free(p1); 431 nex_free(p2); 432 nex_free(p3); 433 p1 = NULL; 434 p2 = NULL; 435 p3 = NULL; 436 437 /* test calloc */ 438 p3 = nex_calloc(4, 1024); 439 p4 = nex_calloc(0x100, 1024 * 1024); 440 LOG("- p3 = nex_calloc(4, 1024)"); 441 LOG("- p4 = nex_calloc(0x100, 1024*1024) too big: should fail!"); 442 LOG(" p1=%p p2=%p p3=%p p4=%p", 443 (void *)p1, (void *)p2, (void *)p3, (void *)p4); 444 r = (p3 && !p4); 445 if (!r) 446 ret = -1; 447 LOG(" => test %s", r ? "ok" : "FAILED"); 448 LOG(""); 449 LOG("- nex_free p3, p4"); 450 nex_free(p3); 451 nex_free(p4); 452 p3 = NULL; 453 p4 = NULL; 454 455 /* test free(NULL) */ 456 LOG("- nex_free NULL"); 457 nex_free(NULL); 458 LOG(""); 459 LOG("nex_malloc test done"); 460 461 return ret; 462 } 463 #else /* CFG_VIRTUALIZATION */ 464 static int self_test_nex_malloc(void) 465 { 466 return 0; 467 } 468 #endif 469 /* exported entry points for some basic test */ 470 TEE_Result core_self_tests(uint32_t nParamTypes __unused, 471 TEE_Param pParams[TEE_NUM_PARAMS] __unused) 472 { 473 if (self_test_mul_signed_overflow() || self_test_add_overflow() || 474 self_test_sub_overflow() || self_test_mul_unsigned_overflow() || 475 self_test_division() || self_test_malloc() || 476 self_test_nex_malloc()) { 477 EMSG("some self_test_xxx failed! you should enable local LOG"); 478 return TEE_ERROR_GENERIC; 479 } 480 return TEE_SUCCESS; 481 } 482