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