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
self_test_add_overflow(void)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
self_test_sub_overflow(void)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
self_test_mul_unsigned_overflow(void)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
self_test_mul_signed_overflow(void)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 */
self_test_division(void)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 */
self_test_malloc(void)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 */
self_test_nex_malloc(void)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 */
self_test_nex_malloc(void)546 static int self_test_nex_malloc(void)
547 {
548 return 0;
549 }
550 #endif
551 /* exported entry points for some basic test */
core_self_tests(uint32_t nParamTypes __unused,TEE_Param pParams[TEE_NUM_PARAMS]__unused)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