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:"); 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 memalign */ 377 p3 = memalign(0x1000, 1024); 378 LOG("- p3 = memalign(%d, 1024)", 0x1000); 379 p1 = malloc(1024); 380 LOG("- p1 = malloc(1024)"); 381 p4 = memalign(0x100, 512); 382 LOG("- p4 = memalign(%d, 512)", 0x100); 383 LOG(" p1=%p p2=%p p3=%p p4=%p", 384 (void *)p1, (void *)p2, (void *)p3, (void *)p4); 385 r = (p1 && p3 && p4 && 386 !((vaddr_t)p3 % 0x1000) && !((vaddr_t)p4 % 0x100)); 387 if (!r) 388 ret = -1; 389 LOG(" => test %s", r ? "ok" : "FAILED"); 390 LOG(""); 391 LOG("- free p1, p3, p4"); 392 free(p1); 393 free(p3); 394 free(p4); 395 p1 = NULL; 396 p3 = NULL; 397 p4 = NULL; 398 399 /* test memalign with invalid alignments */ 400 p3 = memalign(100, 1024); 401 LOG("- p3 = memalign(%d, 1024)", 100); 402 p4 = memalign(0, 1024); 403 LOG("- p4 = memalign(%d, 1024)", 0); 404 LOG(" p1=%p p2=%p p3=%p p4=%p", 405 (void *)p1, (void *)p2, (void *)p3, (void *)p4); 406 r = (!p3 && !p4); 407 if (!r) 408 ret = -1; 409 LOG(" => test %s", r ? "ok" : "FAILED"); 410 LOG(""); 411 LOG("- free p3, p4"); 412 free(p3); 413 free(p4); 414 p3 = NULL; 415 p4 = NULL; 416 417 /* test free(NULL) */ 418 LOG("- free NULL"); 419 free(NULL); 420 LOG(""); 421 LOG("malloc test done"); 422 423 return ret; 424 } 425 426 #ifdef CFG_VIRTUALIZATION 427 /* test nex_malloc support. resulting trace shall be manually checked */ 428 static int self_test_nex_malloc(void) 429 { 430 char *p1 = NULL, *p2 = NULL; 431 int *p3 = NULL, *p4 = NULL; 432 bool r; 433 int ret = 0; 434 435 LOG("nex_malloc tests:"); 436 LOG(" p1=%p p2=%p p3=%p p4=%p", 437 (void *)p1, (void *)p2, (void *)p3, (void *)p4); 438 /* test malloc */ 439 p1 = nex_malloc(1024); 440 LOG("- p1 = nex_malloc(1024)"); 441 p2 = nex_malloc(1024); 442 LOG("- p2 = nex_malloc(1024)"); 443 LOG(" p1=%p p2=%p p3=%p p4=%p", 444 (void *)p1, (void *)p2, (void *)p3, (void *)p4); 445 r = (p1 && p2 && nex_malloc_buffer_is_within_alloced(p1, 1024) && 446 !nex_malloc_buffer_is_within_alloced(p1 + 25, 1000) && 447 !nex_malloc_buffer_is_within_alloced(p1 - 25, 500) && 448 nex_malloc_buffer_overlaps_heap(p1 - 25, 500)); 449 if (!r) 450 ret = -1; 451 LOG(" => test %s", r ? "ok" : "FAILED"); 452 LOG(""); 453 454 /* test realloc */ 455 p3 = nex_realloc(p1, 3 * 1024); 456 if (p3) 457 p1 = NULL; 458 LOG("- p3 = nex_realloc(p1, 3*1024)"); 459 LOG("- nex_free p2"); 460 nex_free(p2); 461 p2 = nex_malloc(1024); 462 LOG("- p2 = nex_malloc(1024)"); 463 LOG(" p1=%p p2=%p p3=%p p4=%p", 464 (void *)p1, (void *)p2, (void *)p3, (void *)p4); 465 r = (p2 && p3); 466 if (!r) 467 ret = -1; 468 LOG(" => test %s", r ? "ok" : "FAILED"); 469 LOG(""); 470 LOG("- nex_free p1, p2, p3"); 471 nex_free(p1); 472 nex_free(p2); 473 nex_free(p3); 474 p1 = NULL; 475 p2 = NULL; 476 p3 = NULL; 477 478 /* test calloc */ 479 p3 = nex_calloc(4, 1024); 480 p4 = nex_calloc(0x100, 1024 * 1024); 481 LOG("- p3 = nex_calloc(4, 1024)"); 482 LOG("- p4 = nex_calloc(0x100, 1024*1024) too big: should fail!"); 483 LOG(" p1=%p p2=%p p3=%p p4=%p", 484 (void *)p1, (void *)p2, (void *)p3, (void *)p4); 485 r = (p3 && !p4); 486 if (!r) 487 ret = -1; 488 LOG(" => test %s", r ? "ok" : "FAILED"); 489 LOG(""); 490 LOG("- nex_free p3, p4"); 491 nex_free(p3); 492 nex_free(p4); 493 p3 = NULL; 494 p4 = NULL; 495 496 /* test memalign */ 497 p3 = nex_memalign(0x1000, 1024); 498 LOG("- p3 = nex_memalign(%d, 1024)", 0x1000); 499 p1 = nex_malloc(1024); 500 LOG("- p1 = nex_malloc(1024)"); 501 p4 = nex_memalign(0x100, 512); 502 LOG("- p4 = nex_memalign(%d, 512)", 0x100); 503 LOG(" p1=%p p2=%p p3=%p p4=%p", 504 (void *)p1, (void *)p2, (void *)p3, (void *)p4); 505 r = (p1 && p3 && p4 && 506 !((vaddr_t)p3 % 0x1000) && !((vaddr_t)p4 % 0x100)); 507 if (!r) 508 ret = -1; 509 LOG(" => test %s", r ? "ok" : "FAILED"); 510 LOG(""); 511 LOG("- nex_free p1, p3, p4"); 512 nex_free(p1); 513 nex_free(p3); 514 nex_free(p4); 515 p1 = NULL; 516 p3 = NULL; 517 p4 = NULL; 518 519 /* test memalign with invalid alignments */ 520 p3 = nex_memalign(100, 1024); 521 LOG("- p3 = nex_memalign(%d, 1024)", 100); 522 p4 = nex_memalign(0, 1024); 523 LOG("- p4 = nex_memalign(%d, 1024)", 0); 524 LOG(" p1=%p p2=%p p3=%p p4=%p", 525 (void *)p1, (void *)p2, (void *)p3, (void *)p4); 526 r = (!p3 && !p4); 527 if (!r) 528 ret = -1; 529 LOG(" => test %s", r ? "ok" : "FAILED"); 530 LOG(""); 531 LOG("- nex_free p3, p4"); 532 nex_free(p3); 533 nex_free(p4); 534 p3 = NULL; 535 p4 = NULL; 536 537 /* test free(NULL) */ 538 LOG("- nex_free NULL"); 539 nex_free(NULL); 540 LOG(""); 541 LOG("nex_malloc test done"); 542 543 return ret; 544 } 545 #else /* CFG_VIRTUALIZATION */ 546 static int self_test_nex_malloc(void) 547 { 548 return 0; 549 } 550 #endif 551 /* exported entry points for some basic test */ 552 TEE_Result core_self_tests(uint32_t nParamTypes __unused, 553 TEE_Param pParams[TEE_NUM_PARAMS] __unused) 554 { 555 if (self_test_mul_signed_overflow() || self_test_add_overflow() || 556 self_test_sub_overflow() || self_test_mul_unsigned_overflow() || 557 self_test_division() || self_test_malloc() || 558 self_test_nex_malloc()) { 559 EMSG("some self_test_xxx failed! you should enable local LOG"); 560 return TEE_ERROR_GENERIC; 561 } 562 return TEE_SUCCESS; 563 } 564