1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | |
3 | #define _GNU_SOURCE |
4 | #define _LARGEFILE64_SOURCE |
5 | |
6 | /* libc-specific include files |
7 | * The program may be built in 3 ways: |
8 | * $(CC) -nostdlib -include /path/to/nolibc.h => NOLIBC already defined |
9 | * $(CC) -nostdlib -I/path/to/nolibc/sysroot => _NOLIBC_* guards are present |
10 | * $(CC) with default libc => NOLIBC* never defined |
11 | */ |
12 | #ifndef NOLIBC |
13 | #include <stdio.h> |
14 | #include <stdlib.h> |
15 | #include <string.h> |
16 | #ifndef _NOLIBC_STDIO_H |
17 | /* standard libcs need more includes */ |
18 | #include <sys/auxv.h> |
19 | #include <sys/io.h> |
20 | #include <sys/ioctl.h> |
21 | #include <sys/mman.h> |
22 | #include <sys/mount.h> |
23 | #include <sys/prctl.h> |
24 | #include <sys/reboot.h> |
25 | #include <sys/resource.h> |
26 | #include <sys/stat.h> |
27 | #include <sys/syscall.h> |
28 | #include <sys/sysmacros.h> |
29 | #include <sys/time.h> |
30 | #include <sys/wait.h> |
31 | #include <dirent.h> |
32 | #include <errno.h> |
33 | #include <fcntl.h> |
34 | #include <poll.h> |
35 | #include <sched.h> |
36 | #include <signal.h> |
37 | #include <stdarg.h> |
38 | #include <stddef.h> |
39 | #include <stdint.h> |
40 | #include <unistd.h> |
41 | #include <limits.h> |
42 | #endif |
43 | #endif |
44 | |
45 | #include "nolibc-test-linkage.h" |
46 | |
47 | /* for the type of int_fast16_t and int_fast32_t, musl differs from glibc and nolibc */ |
48 | #define SINT_MAX_OF_TYPE(type) (((type)1 << (sizeof(type) * 8 - 2)) - (type)1 + ((type)1 << (sizeof(type) * 8 - 2))) |
49 | #define SINT_MIN_OF_TYPE(type) (-SINT_MAX_OF_TYPE(type) - 1) |
50 | |
51 | /* will be used to test initialization of environ */ |
52 | static char **test_envp; |
53 | |
54 | /* will be used to test initialization of argv */ |
55 | static char **test_argv; |
56 | |
57 | /* will be used to test initialization of argc */ |
58 | static int test_argc; |
59 | |
60 | /* will be used by some test cases as readable file, please don't write it */ |
61 | static const char *argv0; |
62 | |
63 | /* will be used by constructor tests */ |
64 | static int constructor_test_value; |
65 | |
66 | /* definition of a series of tests */ |
67 | struct test { |
68 | const char *name; /* test name */ |
69 | int (*func)(int min, int max); /* handler */ |
70 | }; |
71 | |
72 | #ifndef _NOLIBC_STDLIB_H |
73 | char *itoa(int i) |
74 | { |
75 | static char buf[12]; |
76 | int ret; |
77 | |
78 | ret = snprintf(buf, sizeof(buf), "%d" , i); |
79 | return (ret >= 0 && ret < sizeof(buf)) ? buf : "#err" ; |
80 | } |
81 | #endif |
82 | |
83 | #define CASE_ERR(err) \ |
84 | case err: return #err |
85 | |
86 | /* returns the error name (e.g. "ENOENT") for common errors, "SUCCESS" for 0, |
87 | * or the decimal value for less common ones. |
88 | */ |
89 | static const char *errorname(int err) |
90 | { |
91 | switch (err) { |
92 | case 0: return "SUCCESS" ; |
93 | CASE_ERR(EPERM); |
94 | CASE_ERR(ENOENT); |
95 | CASE_ERR(ESRCH); |
96 | CASE_ERR(EINTR); |
97 | CASE_ERR(EIO); |
98 | CASE_ERR(ENXIO); |
99 | CASE_ERR(E2BIG); |
100 | CASE_ERR(ENOEXEC); |
101 | CASE_ERR(EBADF); |
102 | CASE_ERR(ECHILD); |
103 | CASE_ERR(EAGAIN); |
104 | CASE_ERR(ENOMEM); |
105 | CASE_ERR(EACCES); |
106 | CASE_ERR(EFAULT); |
107 | CASE_ERR(ENOTBLK); |
108 | CASE_ERR(EBUSY); |
109 | CASE_ERR(EEXIST); |
110 | CASE_ERR(EXDEV); |
111 | CASE_ERR(ENODEV); |
112 | CASE_ERR(ENOTDIR); |
113 | CASE_ERR(EISDIR); |
114 | CASE_ERR(EINVAL); |
115 | CASE_ERR(ENFILE); |
116 | CASE_ERR(EMFILE); |
117 | CASE_ERR(ENOTTY); |
118 | CASE_ERR(ETXTBSY); |
119 | CASE_ERR(EFBIG); |
120 | CASE_ERR(ENOSPC); |
121 | CASE_ERR(ESPIPE); |
122 | CASE_ERR(EROFS); |
123 | CASE_ERR(EMLINK); |
124 | CASE_ERR(EPIPE); |
125 | CASE_ERR(EDOM); |
126 | CASE_ERR(ERANGE); |
127 | CASE_ERR(ENOSYS); |
128 | CASE_ERR(EOVERFLOW); |
129 | default: |
130 | return itoa(i: err); |
131 | } |
132 | } |
133 | |
134 | static void align_result(size_t llen) |
135 | { |
136 | const size_t align = 64; |
137 | char buf[align]; |
138 | size_t n; |
139 | |
140 | if (llen >= align) |
141 | return; |
142 | |
143 | n = align - llen; |
144 | memset(buf, ' ', n); |
145 | buf[n] = '\0'; |
146 | fputs(buf, stdout); |
147 | } |
148 | |
149 | enum RESULT { |
150 | OK, |
151 | FAIL, |
152 | SKIPPED, |
153 | }; |
154 | |
155 | static void result(int llen, enum RESULT r) |
156 | { |
157 | const char *msg; |
158 | |
159 | if (r == OK) |
160 | msg = " [OK]" ; |
161 | else if (r == SKIPPED) |
162 | msg = "[SKIPPED]" ; |
163 | else |
164 | msg = " [FAIL]" ; |
165 | |
166 | align_result(llen); |
167 | puts(msg); |
168 | } |
169 | |
170 | /* The tests below are intended to be used by the macroes, which evaluate |
171 | * expression <expr>, print the status to stdout, and update the "ret" |
172 | * variable to count failures. The functions themselves return the number |
173 | * of failures, thus either 0 or 1. |
174 | */ |
175 | |
176 | #define EXPECT_ZR(cond, expr) \ |
177 | do { if (!(cond)) result(llen, SKIPPED); else ret += expect_zr(expr, llen); } while (0) |
178 | |
179 | static __attribute__((unused)) |
180 | int expect_zr(int expr, int llen) |
181 | { |
182 | int ret = !(expr == 0); |
183 | |
184 | llen += printf(" = %d " , expr); |
185 | result(llen, r: ret ? FAIL : OK); |
186 | return ret; |
187 | } |
188 | |
189 | |
190 | #define EXPECT_NZ(cond, expr, val) \ |
191 | do { if (!(cond)) result(llen, SKIPPED); else ret += expect_nz(expr, llen; } while (0) |
192 | |
193 | static __attribute__((unused)) |
194 | int expect_nz(int expr, int llen) |
195 | { |
196 | int ret = !(expr != 0); |
197 | |
198 | llen += printf(" = %d " , expr); |
199 | result(llen, r: ret ? FAIL : OK); |
200 | return ret; |
201 | } |
202 | |
203 | |
204 | #define EXPECT_EQ(cond, expr, val) \ |
205 | do { if (!(cond)) result(llen, SKIPPED); else ret += expect_eq(expr, llen, val); } while (0) |
206 | |
207 | static __attribute__((unused)) |
208 | int expect_eq(uint64_t expr, int llen, uint64_t val) |
209 | { |
210 | int ret = !(expr == val); |
211 | |
212 | llen += printf(" = %lld " , (long long)expr); |
213 | result(llen, r: ret ? FAIL : OK); |
214 | return ret; |
215 | } |
216 | |
217 | |
218 | #define EXPECT_NE(cond, expr, val) \ |
219 | do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ne(expr, llen, val); } while (0) |
220 | |
221 | static __attribute__((unused)) |
222 | int expect_ne(int expr, int llen, int val) |
223 | { |
224 | int ret = !(expr != val); |
225 | |
226 | llen += printf(" = %d " , expr); |
227 | result(llen, r: ret ? FAIL : OK); |
228 | return ret; |
229 | } |
230 | |
231 | |
232 | #define EXPECT_GE(cond, expr, val) \ |
233 | do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ge(expr, llen, val); } while (0) |
234 | |
235 | static __attribute__((unused)) |
236 | int expect_ge(int expr, int llen, int val) |
237 | { |
238 | int ret = !(expr >= val); |
239 | |
240 | llen += printf(" = %d " , expr); |
241 | result(llen, r: ret ? FAIL : OK); |
242 | return ret; |
243 | } |
244 | |
245 | |
246 | #define EXPECT_GT(cond, expr, val) \ |
247 | do { if (!(cond)) result(llen, SKIPPED); else ret += expect_gt(expr, llen, val); } while (0) |
248 | |
249 | static __attribute__((unused)) |
250 | int expect_gt(int expr, int llen, int val) |
251 | { |
252 | int ret = !(expr > val); |
253 | |
254 | llen += printf(" = %d " , expr); |
255 | result(llen, r: ret ? FAIL : OK); |
256 | return ret; |
257 | } |
258 | |
259 | |
260 | #define EXPECT_LE(cond, expr, val) \ |
261 | do { if (!(cond)) result(llen, SKIPPED); else ret += expect_le(expr, llen, val); } while (0) |
262 | |
263 | static __attribute__((unused)) |
264 | int expect_le(int expr, int llen, int val) |
265 | { |
266 | int ret = !(expr <= val); |
267 | |
268 | llen += printf(" = %d " , expr); |
269 | result(llen, r: ret ? FAIL : OK); |
270 | return ret; |
271 | } |
272 | |
273 | |
274 | #define EXPECT_LT(cond, expr, val) \ |
275 | do { if (!(cond)) result(llen, SKIPPED); else ret += expect_lt(expr, llen, val); } while (0) |
276 | |
277 | static __attribute__((unused)) |
278 | int expect_lt(int expr, int llen, int val) |
279 | { |
280 | int ret = !(expr < val); |
281 | |
282 | llen += printf(" = %d " , expr); |
283 | result(llen, r: ret ? FAIL : OK); |
284 | return ret; |
285 | } |
286 | |
287 | |
288 | #define EXPECT_SYSZR(cond, expr) \ |
289 | do { if (!(cond)) result(llen, SKIPPED); else ret += expect_syszr(expr, llen); } while (0) |
290 | |
291 | static __attribute__((unused)) |
292 | int expect_syszr(int expr, int llen) |
293 | { |
294 | int ret = 0; |
295 | |
296 | if (expr) { |
297 | ret = 1; |
298 | llen += printf(" = %d %s " , expr, errorname(err: errno)); |
299 | result(llen, r: FAIL); |
300 | } else { |
301 | llen += printf(" = %d " , expr); |
302 | result(llen, r: OK); |
303 | } |
304 | return ret; |
305 | } |
306 | |
307 | |
308 | #define EXPECT_SYSEQ(cond, expr, val) \ |
309 | do { if (!(cond)) result(llen, SKIPPED); else ret += expect_syseq(expr, llen, val); } while (0) |
310 | |
311 | static __attribute__((unused)) |
312 | int expect_syseq(int expr, int llen, int val) |
313 | { |
314 | int ret = 0; |
315 | |
316 | if (expr != val) { |
317 | ret = 1; |
318 | llen += printf(" = %d %s " , expr, errorname(err: errno)); |
319 | result(llen, r: FAIL); |
320 | } else { |
321 | llen += printf(" = %d " , expr); |
322 | result(llen, r: OK); |
323 | } |
324 | return ret; |
325 | } |
326 | |
327 | |
328 | #define EXPECT_SYSNE(cond, expr, val) \ |
329 | do { if (!(cond)) result(llen, SKIPPED); else ret += expect_sysne(expr, llen, val); } while (0) |
330 | |
331 | static __attribute__((unused)) |
332 | int expect_sysne(int expr, int llen, int val) |
333 | { |
334 | int ret = 0; |
335 | |
336 | if (expr == val) { |
337 | ret = 1; |
338 | llen += printf(" = %d %s " , expr, errorname(errno)); |
339 | result(llen, r: FAIL); |
340 | } else { |
341 | llen += printf(" = %d " , expr); |
342 | result(llen, r: OK); |
343 | } |
344 | return ret; |
345 | } |
346 | |
347 | |
348 | #define EXPECT_SYSER2(cond, expr, expret, experr1, experr2) \ |
349 | do { if (!(cond)) result(llen, SKIPPED); else ret += expect_syserr2(expr, expret, experr1, experr2, llen); } while (0) |
350 | |
351 | #define EXPECT_SYSER(cond, expr, expret, experr) \ |
352 | EXPECT_SYSER2(cond, expr, expret, experr, 0) |
353 | |
354 | static __attribute__((unused)) |
355 | int expect_syserr2(int expr, int expret, int experr1, int experr2, int llen) |
356 | { |
357 | int ret = 0; |
358 | int _errno = errno; |
359 | |
360 | llen += printf(" = %d %s " , expr, errorname(err: _errno)); |
361 | if (expr != expret || (_errno != experr1 && _errno != experr2)) { |
362 | ret = 1; |
363 | if (experr2 == 0) |
364 | llen += printf(" != (%d %s) " , expret, errorname(err: experr1)); |
365 | else |
366 | llen += printf(" != (%d %s %s) " , expret, errorname(err: experr1), errorname(err: experr2)); |
367 | result(llen, r: FAIL); |
368 | } else { |
369 | result(llen, r: OK); |
370 | } |
371 | return ret; |
372 | } |
373 | |
374 | |
375 | #define EXPECT_PTRZR(cond, expr) \ |
376 | do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptrzr(expr, llen); } while (0) |
377 | |
378 | static __attribute__((unused)) |
379 | int expect_ptrzr(const void *expr, int llen) |
380 | { |
381 | int ret = 0; |
382 | |
383 | llen += printf(" = <%p> " , expr); |
384 | if (expr) { |
385 | ret = 1; |
386 | result(llen, r: FAIL); |
387 | } else { |
388 | result(llen, r: OK); |
389 | } |
390 | return ret; |
391 | } |
392 | |
393 | |
394 | #define EXPECT_PTRNZ(cond, expr) \ |
395 | do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptrnz(expr, llen); } while (0) |
396 | |
397 | static __attribute__((unused)) |
398 | int expect_ptrnz(const void *expr, int llen) |
399 | { |
400 | int ret = 0; |
401 | |
402 | llen += printf(" = <%p> " , expr); |
403 | if (!expr) { |
404 | ret = 1; |
405 | result(llen, r: FAIL); |
406 | } else { |
407 | result(llen, r: OK); |
408 | } |
409 | return ret; |
410 | } |
411 | |
412 | #define EXPECT_PTREQ(cond, expr, cmp) \ |
413 | do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptreq(expr, llen, cmp); } while (0) |
414 | |
415 | static __attribute__((unused)) |
416 | int expect_ptreq(const void *expr, int llen, const void *cmp) |
417 | { |
418 | int ret = 0; |
419 | |
420 | llen += printf(" = <%p> " , expr); |
421 | if (expr != cmp) { |
422 | ret = 1; |
423 | result(llen, r: FAIL); |
424 | } else { |
425 | result(llen, r: OK); |
426 | } |
427 | return ret; |
428 | } |
429 | |
430 | #define EXPECT_PTRNE(cond, expr, cmp) \ |
431 | do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptrne(expr, llen, cmp); } while (0) |
432 | |
433 | static __attribute__((unused)) |
434 | int expect_ptrne(const void *expr, int llen, const void *cmp) |
435 | { |
436 | int ret = 0; |
437 | |
438 | llen += printf(" = <%p> " , expr); |
439 | if (expr == cmp) { |
440 | ret = 1; |
441 | result(llen, r: FAIL); |
442 | } else { |
443 | result(llen, r: OK); |
444 | } |
445 | return ret; |
446 | } |
447 | |
448 | #define EXPECT_PTRGE(cond, expr, cmp) \ |
449 | do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptrge(expr, llen, cmp); } while (0) |
450 | |
451 | static __attribute__((unused)) |
452 | int expect_ptrge(const void *expr, int llen, const void *cmp) |
453 | { |
454 | int ret = !(expr >= cmp); |
455 | |
456 | llen += printf(" = <%p> " , expr); |
457 | result(llen, r: ret ? FAIL : OK); |
458 | return ret; |
459 | } |
460 | |
461 | #define EXPECT_PTRGT(cond, expr, cmp) \ |
462 | do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptrgt(expr, llen, cmp); } while (0) |
463 | |
464 | static __attribute__((unused)) |
465 | int expect_ptrgt(const void *expr, int llen, const void *cmp) |
466 | { |
467 | int ret = !(expr > cmp); |
468 | |
469 | llen += printf(" = <%p> " , expr); |
470 | result(llen, r: ret ? FAIL : OK); |
471 | return ret; |
472 | } |
473 | |
474 | |
475 | #define EXPECT_PTRLE(cond, expr, cmp) \ |
476 | do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptrle(expr, llen, cmp); } while (0) |
477 | |
478 | static __attribute__((unused)) |
479 | int expect_ptrle(const void *expr, int llen, const void *cmp) |
480 | { |
481 | int ret = !(expr <= cmp); |
482 | |
483 | llen += printf(" = <%p> " , expr); |
484 | result(llen, r: ret ? FAIL : OK); |
485 | return ret; |
486 | } |
487 | |
488 | |
489 | #define EXPECT_PTRLT(cond, expr, cmp) \ |
490 | do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptrlt(expr, llen, cmp); } while (0) |
491 | |
492 | static __attribute__((unused)) |
493 | int expect_ptrlt(const void *expr, int llen, const void *cmp) |
494 | { |
495 | int ret = !(expr < cmp); |
496 | |
497 | llen += printf(" = <%p> " , expr); |
498 | result(llen, r: ret ? FAIL : OK); |
499 | return ret; |
500 | } |
501 | |
502 | #define EXPECT_PTRER2(cond, expr, expret, experr1, experr2) \ |
503 | do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptrerr2(expr, expret, experr1, experr2, llen); } while (0) |
504 | |
505 | #define EXPECT_PTRER(cond, expr, expret, experr) \ |
506 | EXPECT_PTRER2(cond, expr, expret, experr, 0) |
507 | |
508 | static __attribute__((unused)) |
509 | int expect_ptrerr2(const void *expr, const void *expret, int experr1, int experr2, int llen) |
510 | { |
511 | int ret = 0; |
512 | int _errno = errno; |
513 | |
514 | llen += printf(" = <%p> %s " , expr, errorname(err: _errno)); |
515 | if (expr != expret || (_errno != experr1 && _errno != experr2)) { |
516 | ret = 1; |
517 | if (experr2 == 0) |
518 | llen += printf(" != (<%p> %s) " , expret, errorname(err: experr1)); |
519 | else |
520 | llen += printf(" != (<%p> %s %s) " , expret, errorname(err: experr1), errorname(err: experr2)); |
521 | result(llen, r: FAIL); |
522 | } else { |
523 | result(llen, r: OK); |
524 | } |
525 | return ret; |
526 | } |
527 | |
528 | #define EXPECT_STRZR(cond, expr) \ |
529 | do { if (!(cond)) result(llen, SKIPPED); else ret += expect_strzr(expr, llen); } while (0) |
530 | |
531 | static __attribute__((unused)) |
532 | int expect_strzr(const char *expr, int llen) |
533 | { |
534 | int ret = 0; |
535 | |
536 | llen += printf(" = <%s> " , expr); |
537 | if (expr) { |
538 | ret = 1; |
539 | result(llen, r: FAIL); |
540 | } else { |
541 | result(llen, r: OK); |
542 | } |
543 | return ret; |
544 | } |
545 | |
546 | |
547 | #define EXPECT_STRNZ(cond, expr) \ |
548 | do { if (!(cond)) result(llen, SKIPPED); else ret += expect_strnz(expr, llen); } while (0) |
549 | |
550 | static __attribute__((unused)) |
551 | int expect_strnz(const char *expr, int llen) |
552 | { |
553 | int ret = 0; |
554 | |
555 | llen += printf(" = <%s> " , expr); |
556 | if (!expr) { |
557 | ret = 1; |
558 | result(llen, r: FAIL); |
559 | } else { |
560 | result(llen, r: OK); |
561 | } |
562 | return ret; |
563 | } |
564 | |
565 | |
566 | #define EXPECT_STREQ(cond, expr, cmp) \ |
567 | do { if (!(cond)) result(llen, SKIPPED); else ret += expect_streq(expr, llen, cmp); } while (0) |
568 | |
569 | static __attribute__((unused)) |
570 | int expect_streq(const char *expr, int llen, const char *cmp) |
571 | { |
572 | int ret = 0; |
573 | |
574 | llen += printf(" = <%s> " , expr); |
575 | if (strcmp(expr, cmp) != 0) { |
576 | ret = 1; |
577 | result(llen, r: FAIL); |
578 | } else { |
579 | result(llen, r: OK); |
580 | } |
581 | return ret; |
582 | } |
583 | |
584 | |
585 | #define EXPECT_STRNE(cond, expr, cmp) \ |
586 | do { if (!(cond)) result(llen, SKIPPED); else ret += expect_strne(expr, llen, cmp); } while (0) |
587 | |
588 | static __attribute__((unused)) |
589 | int expect_strne(const char *expr, int llen, const char *cmp) |
590 | { |
591 | int ret = 0; |
592 | |
593 | llen += printf(" = <%s> " , expr); |
594 | if (strcmp(expr, cmp) == 0) { |
595 | ret = 1; |
596 | result(llen, r: FAIL); |
597 | } else { |
598 | result(llen, r: OK); |
599 | } |
600 | return ret; |
601 | } |
602 | |
603 | |
604 | /* declare tests based on line numbers. There must be exactly one test per line. */ |
605 | #define CASE_TEST(name) \ |
606 | case __LINE__: llen += printf("%d %s", test, #name); |
607 | |
608 | /* constructors validate that they are executed in definition order */ |
609 | __attribute__((constructor)) |
610 | static void constructor1(void) |
611 | { |
612 | constructor_test_value = 1; |
613 | } |
614 | |
615 | __attribute__((constructor)) |
616 | static void constructor2(void) |
617 | { |
618 | constructor_test_value *= 2; |
619 | } |
620 | |
621 | int run_startup(int min, int max) |
622 | { |
623 | int test; |
624 | int ret = 0; |
625 | /* kernel at least passes HOME and TERM, shell passes more */ |
626 | int env_total = 2; |
627 | /* checking NULL for argv/argv0, environ and _auxv is not enough, let's compare with sbrk(0) or &end */ |
628 | extern char end; |
629 | char *brk = sbrk(0) != (void *)-1 ? sbrk(0) : &end; |
630 | /* differ from nolibc, both glibc and musl have no global _auxv */ |
631 | const unsigned long *test_auxv = (void *)-1; |
632 | #ifdef NOLIBC |
633 | test_auxv = _auxv; |
634 | #endif |
635 | |
636 | for (test = min; test >= 0 && test <= max; test++) { |
637 | int llen = 0; /* line length */ |
638 | |
639 | /* avoid leaving empty lines below, this will insert holes into |
640 | * test numbers. |
641 | */ |
642 | switch (test + __LINE__ + 1) { |
643 | CASE_TEST(argc); EXPECT_GE(1, test_argc, 1); break; |
644 | CASE_TEST(argv_addr); EXPECT_PTRGT(1, test_argv, brk); break; |
645 | CASE_TEST(argv_environ); EXPECT_PTRLT(1, test_argv, environ); break; |
646 | CASE_TEST(argv_total); EXPECT_EQ(1, environ - test_argv - 1, test_argc ?: 1); break; |
647 | CASE_TEST(argv0_addr); EXPECT_PTRGT(1, argv0, brk); break; |
648 | CASE_TEST(argv0_str); EXPECT_STRNZ(1, argv0 > brk ? argv0 : NULL); break; |
649 | CASE_TEST(argv0_len); EXPECT_GE(1, argv0 > brk ? strlen(argv0) : 0, 1); break; |
650 | CASE_TEST(environ_addr); EXPECT_PTRGT(1, environ, brk); break; |
651 | CASE_TEST(environ_envp); EXPECT_PTREQ(1, environ, test_envp); break; |
652 | CASE_TEST(environ_auxv); EXPECT_PTRLT(test_auxv != (void *)-1, environ, test_auxv); break; |
653 | CASE_TEST(environ_total); EXPECT_GE(test_auxv != (void *)-1, (void *)test_auxv - (void *)environ - 1, env_total); break; |
654 | CASE_TEST(environ_HOME); EXPECT_PTRNZ(1, getenv("HOME" )); break; |
655 | CASE_TEST(auxv_addr); EXPECT_PTRGT(test_auxv != (void *)-1, test_auxv, brk); break; |
656 | CASE_TEST(auxv_AT_UID); EXPECT_EQ(1, getauxval(AT_UID), getuid()); break; |
657 | CASE_TEST(constructor); EXPECT_EQ(1, constructor_test_value, 2); break; |
658 | CASE_TEST(linkage_errno); EXPECT_PTREQ(1, linkage_test_errno_addr(), &errno); break; |
659 | CASE_TEST(linkage_constr); EXPECT_EQ(1, linkage_test_constructor_test_value, 6); break; |
660 | case __LINE__: |
661 | return ret; /* must be last */ |
662 | /* note: do not set any defaults so as to permit holes above */ |
663 | } |
664 | } |
665 | return ret; |
666 | } |
667 | |
668 | |
669 | /* used by some syscall tests below */ |
670 | int test_getdents64(const char *dir) |
671 | { |
672 | char buffer[4096]; |
673 | int fd, ret; |
674 | int err; |
675 | |
676 | ret = fd = open(dir, O_RDONLY | O_DIRECTORY, 0); |
677 | if (ret < 0) |
678 | return ret; |
679 | |
680 | ret = getdents64(fd, (void *)buffer, sizeof(buffer)); |
681 | err = errno; |
682 | close(fd); |
683 | |
684 | errno = err; |
685 | return ret; |
686 | } |
687 | |
688 | int test_getpagesize(void) |
689 | { |
690 | int x = getpagesize(); |
691 | int c; |
692 | |
693 | if (x < 0) |
694 | return x; |
695 | |
696 | #if defined(__x86_64__) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) |
697 | /* |
698 | * x86 family is always 4K page. |
699 | */ |
700 | c = (x == 4096); |
701 | #elif defined(__aarch64__) |
702 | /* |
703 | * Linux aarch64 supports three values of page size: 4K, 16K, and 64K |
704 | * which are selected at kernel compilation time. |
705 | */ |
706 | c = (x == 4096 || x == (16 * 1024) || x == (64 * 1024)); |
707 | #else |
708 | /* |
709 | * Assuming other architectures must have at least 4K page. |
710 | */ |
711 | c = (x >= 4096); |
712 | #endif |
713 | |
714 | return !c; |
715 | } |
716 | |
717 | int test_fork(void) |
718 | { |
719 | int status; |
720 | pid_t pid; |
721 | |
722 | /* flush the printf buffer to avoid child flush it */ |
723 | fflush(stdout); |
724 | fflush(stderr); |
725 | |
726 | pid = fork(); |
727 | |
728 | switch (pid) { |
729 | case -1: |
730 | return 1; |
731 | |
732 | case 0: |
733 | exit(123); |
734 | |
735 | default: |
736 | pid = waitpid(pid, &status, 0); |
737 | |
738 | return pid == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 123; |
739 | } |
740 | } |
741 | |
742 | int test_stat_timestamps(void) |
743 | { |
744 | struct stat st; |
745 | |
746 | if (sizeof(st.st_atim.tv_sec) != sizeof(st.st_atime)) |
747 | return 1; |
748 | |
749 | if (stat("/proc/self/" , &st) && stat(argv0, &st) && stat("/" , &st)) |
750 | return 1; |
751 | |
752 | if (st.st_atim.tv_sec != st.st_atime || st.st_atim.tv_nsec > 1000000000) |
753 | return 1; |
754 | |
755 | if (st.st_mtim.tv_sec != st.st_mtime || st.st_mtim.tv_nsec > 1000000000) |
756 | return 1; |
757 | |
758 | if (st.st_ctim.tv_sec != st.st_ctime || st.st_ctim.tv_nsec > 1000000000) |
759 | return 1; |
760 | |
761 | return 0; |
762 | } |
763 | |
764 | int test_mmap_munmap(void) |
765 | { |
766 | int ret, fd, i, page_size; |
767 | void *mem; |
768 | size_t file_size, length; |
769 | off_t offset, pa_offset; |
770 | struct stat stat_buf; |
771 | const char * const files[] = { |
772 | "/dev/zero" , |
773 | "/proc/1/exe" , "/proc/self/exe" , |
774 | argv0, |
775 | NULL |
776 | }; |
777 | |
778 | page_size = getpagesize(); |
779 | if (page_size < 0) |
780 | return 1; |
781 | |
782 | /* find a right file to mmap, existed and accessible */ |
783 | for (i = 0; files[i] != NULL; i++) { |
784 | ret = fd = open(files[i], O_RDONLY); |
785 | if (ret == -1) |
786 | continue; |
787 | else |
788 | break; |
789 | } |
790 | if (ret == -1) |
791 | return 1; |
792 | |
793 | ret = stat(files[i], &stat_buf); |
794 | if (ret == -1) |
795 | goto end; |
796 | |
797 | /* file size of the special /dev/zero is 0, let's assign one manually */ |
798 | if (i == 0) |
799 | file_size = 3*page_size; |
800 | else |
801 | file_size = stat_buf.st_size; |
802 | |
803 | offset = file_size - 1; |
804 | if (offset < 0) |
805 | offset = 0; |
806 | length = file_size - offset; |
807 | pa_offset = offset & ~(page_size - 1); |
808 | |
809 | mem = mmap(NULL, length + offset - pa_offset, PROT_READ, MAP_SHARED, fd, pa_offset); |
810 | if (mem == MAP_FAILED) { |
811 | ret = 1; |
812 | goto end; |
813 | } |
814 | |
815 | ret = munmap(mem, length + offset - pa_offset); |
816 | |
817 | end: |
818 | close(fd); |
819 | return !!ret; |
820 | } |
821 | |
822 | int test_pipe(void) |
823 | { |
824 | const char *const msg = "hello, nolibc" ; |
825 | int pipefd[2]; |
826 | char buf[32]; |
827 | size_t len; |
828 | |
829 | if (pipe(pipefd) == -1) |
830 | return 1; |
831 | |
832 | write(pipefd[1], msg, strlen(msg)); |
833 | close(pipefd[1]); |
834 | len = read(pipefd[0], buf, sizeof(buf)); |
835 | close(pipefd[0]); |
836 | |
837 | if (len != strlen(msg)) |
838 | return 1; |
839 | |
840 | return !!memcmp(buf, msg, len); |
841 | } |
842 | |
843 | int test_rlimit(void) |
844 | { |
845 | struct rlimit rlim = { |
846 | .rlim_cur = 1 << 20, |
847 | .rlim_max = 1 << 21, |
848 | }; |
849 | int ret; |
850 | |
851 | ret = setrlimit(RLIMIT_CORE, &rlim); |
852 | if (ret) |
853 | return -1; |
854 | |
855 | rlim.rlim_cur = 0; |
856 | rlim.rlim_max = 0; |
857 | |
858 | ret = getrlimit(RLIMIT_CORE, &rlim); |
859 | if (ret) |
860 | return -1; |
861 | |
862 | if (rlim.rlim_cur != 1 << 20) |
863 | return -1; |
864 | if (rlim.rlim_max != 1 << 21) |
865 | return -1; |
866 | |
867 | return 0; |
868 | } |
869 | |
870 | |
871 | /* Run syscall tests between IDs <min> and <max>. |
872 | * Return 0 on success, non-zero on failure. |
873 | */ |
874 | int run_syscall(int min, int max) |
875 | { |
876 | struct timeval tv; |
877 | struct timezone tz; |
878 | struct stat stat_buf; |
879 | int euid0; |
880 | int proc; |
881 | int test; |
882 | int tmp; |
883 | int ret = 0; |
884 | void *p1, *p2; |
885 | int has_gettid = 1; |
886 | |
887 | /* <proc> indicates whether or not /proc is mounted */ |
888 | proc = stat("/proc" , &stat_buf) == 0; |
889 | |
890 | /* this will be used to skip certain tests that can't be run unprivileged */ |
891 | euid0 = geteuid() == 0; |
892 | |
893 | /* from 2.30, glibc provides gettid() */ |
894 | #if defined(__GLIBC_MINOR__) && defined(__GLIBC__) |
895 | has_gettid = __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 30); |
896 | #endif |
897 | |
898 | for (test = min; test >= 0 && test <= max; test++) { |
899 | int llen = 0; /* line length */ |
900 | |
901 | /* avoid leaving empty lines below, this will insert holes into |
902 | * test numbers. |
903 | */ |
904 | switch (test + __LINE__ + 1) { |
905 | CASE_TEST(getpid); EXPECT_SYSNE(1, getpid(), -1); break; |
906 | CASE_TEST(getppid); EXPECT_SYSNE(1, getppid(), -1); break; |
907 | CASE_TEST(gettid); EXPECT_SYSNE(has_gettid, gettid(), -1); break; |
908 | CASE_TEST(getpgid_self); EXPECT_SYSNE(1, getpgid(0), -1); break; |
909 | CASE_TEST(getpgid_bad); EXPECT_SYSER(1, getpgid(-1), -1, ESRCH); break; |
910 | CASE_TEST(kill_0); EXPECT_SYSZR(1, kill(getpid(), 0)); break; |
911 | CASE_TEST(kill_CONT); EXPECT_SYSZR(1, kill(getpid(), 0)); break; |
912 | CASE_TEST(kill_BADPID); EXPECT_SYSER(1, kill(INT_MAX, 0), -1, ESRCH); break; |
913 | CASE_TEST(sbrk_0); EXPECT_PTRNE(1, sbrk(0), (void *)-1); break; |
914 | CASE_TEST(sbrk); if ((p1 = p2 = sbrk(4096)) != (void *)-1) p2 = sbrk(-4096); EXPECT_SYSZR(1, (p2 == (void *)-1) || p2 == p1); break; |
915 | CASE_TEST(brk); EXPECT_SYSZR(1, brk(sbrk(0))); break; |
916 | CASE_TEST(chdir_root); EXPECT_SYSZR(1, chdir("/" )); chdir(getenv("PWD" )); break; |
917 | CASE_TEST(chdir_dot); EXPECT_SYSZR(1, chdir("." )); break; |
918 | CASE_TEST(chdir_blah); EXPECT_SYSER(1, chdir("/blah" ), -1, ENOENT); break; |
919 | CASE_TEST(chmod_argv0); EXPECT_SYSZR(1, chmod(argv0, 0555)); break; |
920 | CASE_TEST(chmod_self); EXPECT_SYSER(proc, chmod("/proc/self" , 0555), -1, EPERM); break; |
921 | CASE_TEST(chown_self); EXPECT_SYSER(proc, chown("/proc/self" , 0, 0), -1, EPERM); break; |
922 | CASE_TEST(chroot_root); EXPECT_SYSZR(euid0, chroot("/" )); break; |
923 | CASE_TEST(chroot_blah); EXPECT_SYSER(1, chroot("/proc/self/blah" ), -1, ENOENT); break; |
924 | CASE_TEST(chroot_exe); EXPECT_SYSER(1, chroot(argv0), -1, ENOTDIR); break; |
925 | CASE_TEST(close_m1); EXPECT_SYSER(1, close(-1), -1, EBADF); break; |
926 | CASE_TEST(close_dup); EXPECT_SYSZR(1, close(dup(0))); break; |
927 | CASE_TEST(dup_0); tmp = dup(0); EXPECT_SYSNE(1, tmp, -1); close(tmp); break; |
928 | CASE_TEST(dup_m1); tmp = dup(-1); EXPECT_SYSER(1, tmp, -1, EBADF); if (tmp != -1) close(tmp); break; |
929 | CASE_TEST(dup2_0); tmp = dup2(0, 100); EXPECT_SYSNE(1, tmp, -1); close(tmp); break; |
930 | CASE_TEST(dup2_m1); tmp = dup2(-1, 100); EXPECT_SYSER(1, tmp, -1, EBADF); if (tmp != -1) close(tmp); break; |
931 | CASE_TEST(dup3_0); tmp = dup3(0, 100, 0); EXPECT_SYSNE(1, tmp, -1); close(tmp); break; |
932 | CASE_TEST(dup3_m1); tmp = dup3(-1, 100, 0); EXPECT_SYSER(1, tmp, -1, EBADF); if (tmp != -1) close(tmp); break; |
933 | CASE_TEST(execve_root); EXPECT_SYSER(1, execve("/" , (char*[]){ [0] = "/" , [1] = NULL }, NULL), -1, EACCES); break; |
934 | CASE_TEST(fork); EXPECT_SYSZR(1, test_fork()); break; |
935 | CASE_TEST(getdents64_root); EXPECT_SYSNE(1, test_getdents64("/" ), -1); break; |
936 | CASE_TEST(getdents64_null); EXPECT_SYSER(1, test_getdents64("/dev/null" ), -1, ENOTDIR); break; |
937 | CASE_TEST(gettimeofday_tv); EXPECT_SYSZR(1, gettimeofday(&tv, NULL)); break; |
938 | CASE_TEST(gettimeofday_tv_tz);EXPECT_SYSZR(1, gettimeofday(&tv, &tz)); break; |
939 | CASE_TEST(getpagesize); EXPECT_SYSZR(1, test_getpagesize()); break; |
940 | CASE_TEST(ioctl_tiocinq); EXPECT_SYSZR(1, ioctl(0, TIOCINQ, &tmp)); break; |
941 | CASE_TEST(link_root1); EXPECT_SYSER(1, link("/" , "/" ), -1, EEXIST); break; |
942 | CASE_TEST(link_blah); EXPECT_SYSER(1, link("/proc/self/blah" , "/blah" ), -1, ENOENT); break; |
943 | CASE_TEST(link_dir); EXPECT_SYSER(euid0, link("/" , "/blah" ), -1, EPERM); break; |
944 | CASE_TEST(link_cross); EXPECT_SYSER(proc, link("/proc/self/cmdline" , "/blah" ), -1, EXDEV); break; |
945 | CASE_TEST(lseek_m1); EXPECT_SYSER(1, lseek(-1, 0, SEEK_SET), -1, EBADF); break; |
946 | CASE_TEST(lseek_0); EXPECT_SYSER(1, lseek(0, 0, SEEK_SET), -1, ESPIPE); break; |
947 | CASE_TEST(mkdir_root); EXPECT_SYSER(1, mkdir("/" , 0755), -1, EEXIST); break; |
948 | CASE_TEST(mmap_bad); EXPECT_PTRER(1, mmap(NULL, 0, PROT_READ, MAP_PRIVATE, 0, 0), MAP_FAILED, EINVAL); break; |
949 | CASE_TEST(munmap_bad); EXPECT_SYSER(1, munmap(NULL, 0), -1, EINVAL); break; |
950 | CASE_TEST(mmap_munmap_good); EXPECT_SYSZR(1, test_mmap_munmap()); break; |
951 | CASE_TEST(open_tty); EXPECT_SYSNE(1, tmp = open("/dev/null" , 0), -1); if (tmp != -1) close(tmp); break; |
952 | CASE_TEST(open_blah); EXPECT_SYSER(1, tmp = open("/proc/self/blah" , 0), -1, ENOENT); if (tmp != -1) close(tmp); break; |
953 | CASE_TEST(pipe); EXPECT_SYSZR(1, test_pipe()); break; |
954 | CASE_TEST(poll_null); EXPECT_SYSZR(1, poll(NULL, 0, 0)); break; |
955 | CASE_TEST(poll_stdout); EXPECT_SYSNE(1, ({ struct pollfd fds = { 1, POLLOUT, 0}; poll(&fds, 1, 0); }), -1); break; |
956 | CASE_TEST(poll_fault); EXPECT_SYSER(1, poll(NULL, 1, 0), -1, EFAULT); break; |
957 | CASE_TEST(prctl); EXPECT_SYSER(1, prctl(PR_SET_NAME, (unsigned long)NULL, 0, 0, 0), -1, EFAULT); break; |
958 | CASE_TEST(read_badf); EXPECT_SYSER(1, read(-1, &tmp, 1), -1, EBADF); break; |
959 | CASE_TEST(rlimit); EXPECT_SYSZR(1, test_rlimit()); break; |
960 | CASE_TEST(rmdir_blah); EXPECT_SYSER(1, rmdir("/blah" ), -1, ENOENT); break; |
961 | CASE_TEST(sched_yield); EXPECT_SYSZR(1, sched_yield()); break; |
962 | CASE_TEST(select_null); EXPECT_SYSZR(1, ({ struct timeval tv = { 0 }; select(0, NULL, NULL, NULL, &tv); })); break; |
963 | CASE_TEST(select_stdout); EXPECT_SYSNE(1, ({ fd_set fds; FD_ZERO(&fds); FD_SET(1, &fds); select(2, NULL, &fds, NULL, NULL); }), -1); break; |
964 | CASE_TEST(select_fault); EXPECT_SYSER(1, select(1, (void *)1, NULL, NULL, 0), -1, EFAULT); break; |
965 | CASE_TEST(stat_blah); EXPECT_SYSER(1, stat("/proc/self/blah" , &stat_buf), -1, ENOENT); break; |
966 | CASE_TEST(stat_fault); EXPECT_SYSER(1, stat(NULL, &stat_buf), -1, EFAULT); break; |
967 | CASE_TEST(stat_timestamps); EXPECT_SYSZR(1, test_stat_timestamps()); break; |
968 | CASE_TEST(symlink_root); EXPECT_SYSER(1, symlink("/" , "/" ), -1, EEXIST); break; |
969 | CASE_TEST(unlink_root); EXPECT_SYSER(1, unlink("/" ), -1, EISDIR); break; |
970 | CASE_TEST(unlink_blah); EXPECT_SYSER(1, unlink("/proc/self/blah" ), -1, ENOENT); break; |
971 | CASE_TEST(wait_child); EXPECT_SYSER(1, wait(&tmp), -1, ECHILD); break; |
972 | CASE_TEST(waitpid_min); EXPECT_SYSER(1, waitpid(INT_MIN, &tmp, WNOHANG), -1, ESRCH); break; |
973 | CASE_TEST(waitpid_child); EXPECT_SYSER(1, waitpid(getpid(), &tmp, WNOHANG), -1, ECHILD); break; |
974 | CASE_TEST(write_badf); EXPECT_SYSER(1, write(-1, &tmp, 1), -1, EBADF); break; |
975 | CASE_TEST(write_zero); EXPECT_SYSZR(1, write(1, &tmp, 0)); break; |
976 | CASE_TEST(syscall_noargs); EXPECT_SYSEQ(1, syscall(__NR_getpid), getpid()); break; |
977 | CASE_TEST(syscall_args); EXPECT_SYSER(1, syscall(__NR_statx, 0, NULL, 0, 0, NULL), -1, EFAULT); break; |
978 | case __LINE__: |
979 | return ret; /* must be last */ |
980 | /* note: do not set any defaults so as to permit holes above */ |
981 | } |
982 | } |
983 | return ret; |
984 | } |
985 | |
986 | int run_stdlib(int min, int max) |
987 | { |
988 | int test; |
989 | int ret = 0; |
990 | |
991 | for (test = min; test >= 0 && test <= max; test++) { |
992 | int llen = 0; /* line length */ |
993 | |
994 | /* avoid leaving empty lines below, this will insert holes into |
995 | * test numbers. |
996 | */ |
997 | switch (test + __LINE__ + 1) { |
998 | CASE_TEST(getenv_TERM); EXPECT_STRNZ(1, getenv("TERM" )); break; |
999 | CASE_TEST(getenv_blah); EXPECT_STRZR(1, getenv("blah" )); break; |
1000 | CASE_TEST(setcmp_blah_blah); EXPECT_EQ(1, strcmp("blah" , "blah" ), 0); break; |
1001 | CASE_TEST(setcmp_blah_blah2); EXPECT_NE(1, strcmp("blah" , "blah2" ), 0); break; |
1002 | CASE_TEST(setncmp_blah_blah); EXPECT_EQ(1, strncmp("blah" , "blah" , 10), 0); break; |
1003 | CASE_TEST(setncmp_blah_blah4); EXPECT_EQ(1, strncmp("blah" , "blah4" , 4), 0); break; |
1004 | CASE_TEST(setncmp_blah_blah5); EXPECT_NE(1, strncmp("blah" , "blah5" , 5), 0); break; |
1005 | CASE_TEST(setncmp_blah_blah6); EXPECT_NE(1, strncmp("blah" , "blah6" , 6), 0); break; |
1006 | CASE_TEST(strchr_foobar_o); EXPECT_STREQ(1, strchr("foobar" , 'o'), "oobar" ); break; |
1007 | CASE_TEST(strchr_foobar_z); EXPECT_STRZR(1, strchr("foobar" , 'z')); break; |
1008 | CASE_TEST(strrchr_foobar_o); EXPECT_STREQ(1, strrchr("foobar" , 'o'), "obar" ); break; |
1009 | CASE_TEST(strrchr_foobar_z); EXPECT_STRZR(1, strrchr("foobar" , 'z')); break; |
1010 | CASE_TEST(memcmp_20_20); EXPECT_EQ(1, memcmp("aaa\x20" , "aaa\x20" , 4), 0); break; |
1011 | CASE_TEST(memcmp_20_60); EXPECT_LT(1, memcmp("aaa\x20" , "aaa\x60" , 4), 0); break; |
1012 | CASE_TEST(memcmp_60_20); EXPECT_GT(1, memcmp("aaa\x60" , "aaa\x20" , 4), 0); break; |
1013 | CASE_TEST(memcmp_20_e0); EXPECT_LT(1, memcmp("aaa\x20" , "aaa\xe0" , 4), 0); break; |
1014 | CASE_TEST(memcmp_e0_20); EXPECT_GT(1, memcmp("aaa\xe0" , "aaa\x20" , 4), 0); break; |
1015 | CASE_TEST(memcmp_80_e0); EXPECT_LT(1, memcmp("aaa\x80" , "aaa\xe0" , 4), 0); break; |
1016 | CASE_TEST(memcmp_e0_80); EXPECT_GT(1, memcmp("aaa\xe0" , "aaa\x80" , 4), 0); break; |
1017 | CASE_TEST(limit_int8_max); EXPECT_EQ(1, INT8_MAX, (int8_t) 0x7f); break; |
1018 | CASE_TEST(limit_int8_min); EXPECT_EQ(1, INT8_MIN, (int8_t) 0x80); break; |
1019 | CASE_TEST(limit_uint8_max); EXPECT_EQ(1, UINT8_MAX, (uint8_t) 0xff); break; |
1020 | CASE_TEST(limit_int16_max); EXPECT_EQ(1, INT16_MAX, (int16_t) 0x7fff); break; |
1021 | CASE_TEST(limit_int16_min); EXPECT_EQ(1, INT16_MIN, (int16_t) 0x8000); break; |
1022 | CASE_TEST(limit_uint16_max); EXPECT_EQ(1, UINT16_MAX, (uint16_t) 0xffff); break; |
1023 | CASE_TEST(limit_int32_max); EXPECT_EQ(1, INT32_MAX, (int32_t) 0x7fffffff); break; |
1024 | CASE_TEST(limit_int32_min); EXPECT_EQ(1, INT32_MIN, (int32_t) 0x80000000); break; |
1025 | CASE_TEST(limit_uint32_max); EXPECT_EQ(1, UINT32_MAX, (uint32_t) 0xffffffff); break; |
1026 | CASE_TEST(limit_int64_max); EXPECT_EQ(1, INT64_MAX, (int64_t) 0x7fffffffffffffff); break; |
1027 | CASE_TEST(limit_int64_min); EXPECT_EQ(1, INT64_MIN, (int64_t) 0x8000000000000000); break; |
1028 | CASE_TEST(limit_uint64_max); EXPECT_EQ(1, UINT64_MAX, (uint64_t) 0xffffffffffffffff); break; |
1029 | CASE_TEST(limit_int_least8_max); EXPECT_EQ(1, INT_LEAST8_MAX, (int_least8_t) 0x7f); break; |
1030 | CASE_TEST(limit_int_least8_min); EXPECT_EQ(1, INT_LEAST8_MIN, (int_least8_t) 0x80); break; |
1031 | CASE_TEST(limit_uint_least8_max); EXPECT_EQ(1, UINT_LEAST8_MAX, (uint_least8_t) 0xff); break; |
1032 | CASE_TEST(limit_int_least16_max); EXPECT_EQ(1, INT_LEAST16_MAX, (int_least16_t) 0x7fff); break; |
1033 | CASE_TEST(limit_int_least16_min); EXPECT_EQ(1, INT_LEAST16_MIN, (int_least16_t) 0x8000); break; |
1034 | CASE_TEST(limit_uint_least16_max); EXPECT_EQ(1, UINT_LEAST16_MAX, (uint_least16_t) 0xffff); break; |
1035 | CASE_TEST(limit_int_least32_max); EXPECT_EQ(1, INT_LEAST32_MAX, (int_least32_t) 0x7fffffff); break; |
1036 | CASE_TEST(limit_int_least32_min); EXPECT_EQ(1, INT_LEAST32_MIN, (int_least32_t) 0x80000000); break; |
1037 | CASE_TEST(limit_uint_least32_max); EXPECT_EQ(1, UINT_LEAST32_MAX, (uint_least32_t) 0xffffffffU); break; |
1038 | CASE_TEST(limit_int_least64_min); EXPECT_EQ(1, INT_LEAST64_MIN, (int_least64_t) 0x8000000000000000LL); break; |
1039 | CASE_TEST(limit_int_least64_max); EXPECT_EQ(1, INT_LEAST64_MAX, (int_least64_t) 0x7fffffffffffffffLL); break; |
1040 | CASE_TEST(limit_uint_least64_max); EXPECT_EQ(1, UINT_LEAST64_MAX, (uint_least64_t) 0xffffffffffffffffULL); break; |
1041 | CASE_TEST(limit_int_fast8_max); EXPECT_EQ(1, INT_FAST8_MAX, (int_fast8_t) 0x7f); break; |
1042 | CASE_TEST(limit_int_fast8_min); EXPECT_EQ(1, INT_FAST8_MIN, (int_fast8_t) 0x80); break; |
1043 | CASE_TEST(limit_uint_fast8_max); EXPECT_EQ(1, UINT_FAST8_MAX, (uint_fast8_t) 0xff); break; |
1044 | CASE_TEST(limit_int_fast16_min); EXPECT_EQ(1, INT_FAST16_MIN, (int_fast16_t) SINT_MIN_OF_TYPE(int_fast16_t)); break; |
1045 | CASE_TEST(limit_int_fast16_max); EXPECT_EQ(1, INT_FAST16_MAX, (int_fast16_t) SINT_MAX_OF_TYPE(int_fast16_t)); break; |
1046 | CASE_TEST(limit_uint_fast16_max); EXPECT_EQ(1, UINT_FAST16_MAX, (uint_fast16_t) UINTPTR_MAX); break; |
1047 | CASE_TEST(limit_int_fast32_min); EXPECT_EQ(1, INT_FAST32_MIN, (int_fast32_t) SINT_MIN_OF_TYPE(int_fast32_t)); break; |
1048 | CASE_TEST(limit_int_fast32_max); EXPECT_EQ(1, INT_FAST32_MAX, (int_fast32_t) SINT_MAX_OF_TYPE(int_fast32_t)); break; |
1049 | CASE_TEST(limit_uint_fast32_max); EXPECT_EQ(1, UINT_FAST32_MAX, (uint_fast32_t) UINTPTR_MAX); break; |
1050 | CASE_TEST(limit_int_fast64_min); EXPECT_EQ(1, INT_FAST64_MIN, (int_fast64_t) INT64_MIN); break; |
1051 | CASE_TEST(limit_int_fast64_max); EXPECT_EQ(1, INT_FAST64_MAX, (int_fast64_t) INT64_MAX); break; |
1052 | CASE_TEST(limit_uint_fast64_max); EXPECT_EQ(1, UINT_FAST64_MAX, (uint_fast64_t) UINT64_MAX); break; |
1053 | CASE_TEST(sizeof_long_sane); EXPECT_EQ(1, sizeof(long) == 8 || sizeof(long) == 4, 1); break; |
1054 | CASE_TEST(limit_intptr_min); EXPECT_EQ(1, INTPTR_MIN, sizeof(long) == 8 ? (intptr_t) 0x8000000000000000LL : (intptr_t) 0x80000000); break; |
1055 | CASE_TEST(limit_intptr_max); EXPECT_EQ(1, INTPTR_MAX, sizeof(long) == 8 ? (intptr_t) 0x7fffffffffffffffLL : (intptr_t) 0x7fffffff); break; |
1056 | CASE_TEST(limit_uintptr_max); EXPECT_EQ(1, UINTPTR_MAX, sizeof(long) == 8 ? (uintptr_t) 0xffffffffffffffffULL : (uintptr_t) 0xffffffffU); break; |
1057 | CASE_TEST(limit_ptrdiff_min); EXPECT_EQ(1, PTRDIFF_MIN, sizeof(long) == 8 ? (ptrdiff_t) 0x8000000000000000LL : (ptrdiff_t) 0x80000000); break; |
1058 | CASE_TEST(limit_ptrdiff_max); EXPECT_EQ(1, PTRDIFF_MAX, sizeof(long) == 8 ? (ptrdiff_t) 0x7fffffffffffffffLL : (ptrdiff_t) 0x7fffffff); break; |
1059 | CASE_TEST(limit_size_max); EXPECT_EQ(1, SIZE_MAX, sizeof(long) == 8 ? (size_t) 0xffffffffffffffffULL : (size_t) 0xffffffffU); break; |
1060 | |
1061 | case __LINE__: |
1062 | return ret; /* must be last */ |
1063 | /* note: do not set any defaults so as to permit holes above */ |
1064 | } |
1065 | } |
1066 | return ret; |
1067 | } |
1068 | |
1069 | #define EXPECT_VFPRINTF(c, expected, fmt, ...) \ |
1070 | ret += expect_vfprintf(llen, c, expected, fmt, ##__VA_ARGS__) |
1071 | |
1072 | static int expect_vfprintf(int llen, int c, const char *expected, const char *fmt, ...) |
1073 | { |
1074 | int ret, fd; |
1075 | ssize_t w, r; |
1076 | char buf[100]; |
1077 | FILE *memfile; |
1078 | va_list args; |
1079 | |
1080 | fd = open("/tmp" , O_TMPFILE | O_EXCL | O_RDWR, 0600); |
1081 | if (fd == -1) { |
1082 | result(llen, r: SKIPPED); |
1083 | return 0; |
1084 | } |
1085 | |
1086 | memfile = fdopen(fd, "w+" ); |
1087 | if (!memfile) { |
1088 | result(llen, r: FAIL); |
1089 | return 1; |
1090 | } |
1091 | |
1092 | va_start(args, fmt); |
1093 | w = vfprintf(memfile, fmt, args); |
1094 | va_end(args); |
1095 | |
1096 | if (w != c) { |
1097 | llen += printf(" written(%d) != %d" , (int)w, c); |
1098 | result(llen, r: FAIL); |
1099 | return 1; |
1100 | } |
1101 | |
1102 | fflush(memfile); |
1103 | lseek(fd, 0, SEEK_SET); |
1104 | |
1105 | r = read(fd, buf, sizeof(buf) - 1); |
1106 | |
1107 | fclose(memfile); |
1108 | |
1109 | if (r != w) { |
1110 | llen += printf(" written(%d) != read(%d)" , (int)w, (int)r); |
1111 | result(llen, r: FAIL); |
1112 | return 1; |
1113 | } |
1114 | |
1115 | buf[r] = '\0'; |
1116 | llen += printf(" \"%s\" = \"%s\"" , expected, buf); |
1117 | ret = strncmp(expected, buf, c); |
1118 | |
1119 | result(llen, r: ret ? FAIL : OK); |
1120 | return ret; |
1121 | } |
1122 | |
1123 | static int run_vfprintf(int min, int max) |
1124 | { |
1125 | int test; |
1126 | int ret = 0; |
1127 | |
1128 | for (test = min; test >= 0 && test <= max; test++) { |
1129 | int llen = 0; /* line length */ |
1130 | |
1131 | /* avoid leaving empty lines below, this will insert holes into |
1132 | * test numbers. |
1133 | */ |
1134 | switch (test + __LINE__ + 1) { |
1135 | CASE_TEST(empty); EXPECT_VFPRINTF(0, "" , "" ); break; |
1136 | CASE_TEST(simple); EXPECT_VFPRINTF(3, "foo" , "foo" ); break; |
1137 | CASE_TEST(string); EXPECT_VFPRINTF(3, "foo" , "%s" , "foo" ); break; |
1138 | CASE_TEST(number); EXPECT_VFPRINTF(4, "1234" , "%d" , 1234); break; |
1139 | CASE_TEST(negnumber); EXPECT_VFPRINTF(5, "-1234" , "%d" , -1234); break; |
1140 | CASE_TEST(unsigned); EXPECT_VFPRINTF(5, "12345" , "%u" , 12345); break; |
1141 | CASE_TEST(char); EXPECT_VFPRINTF(1, "c" , "%c" , 'c'); break; |
1142 | CASE_TEST(hex); EXPECT_VFPRINTF(1, "f" , "%x" , 0xf); break; |
1143 | CASE_TEST(pointer); EXPECT_VFPRINTF(3, "0x1" , "%p" , (void *) 0x1); break; |
1144 | case __LINE__: |
1145 | return ret; /* must be last */ |
1146 | /* note: do not set any defaults so as to permit holes above */ |
1147 | } |
1148 | } |
1149 | return ret; |
1150 | } |
1151 | |
1152 | static int smash_stack(void) |
1153 | { |
1154 | char buf[100]; |
1155 | volatile char *ptr = buf; |
1156 | size_t i; |
1157 | |
1158 | for (i = 0; i < 200; i++) |
1159 | ptr[i] = 'P'; |
1160 | |
1161 | return 1; |
1162 | } |
1163 | |
1164 | static int run_protection(int min __attribute__((unused)), |
1165 | int max __attribute__((unused))) |
1166 | { |
1167 | pid_t pid; |
1168 | int llen = 0, status; |
1169 | struct rlimit rlimit = { 0, 0 }; |
1170 | |
1171 | llen += printf("0 -fstackprotector " ); |
1172 | |
1173 | #if !defined(_NOLIBC_STACKPROTECTOR) |
1174 | llen += printf("not supported" ); |
1175 | result(llen, r: SKIPPED); |
1176 | return 0; |
1177 | #endif |
1178 | |
1179 | #if defined(_NOLIBC_STACKPROTECTOR) |
1180 | if (!__stack_chk_guard) { |
1181 | llen += printf("__stack_chk_guard not initialized" ); |
1182 | result(llen, FAIL); |
1183 | return 1; |
1184 | } |
1185 | #endif |
1186 | |
1187 | pid = -1; |
1188 | pid = fork(); |
1189 | |
1190 | switch (pid) { |
1191 | case -1: |
1192 | llen += printf("fork()" ); |
1193 | result(llen, r: FAIL); |
1194 | return 1; |
1195 | |
1196 | case 0: |
1197 | close(STDOUT_FILENO); |
1198 | close(STDERR_FILENO); |
1199 | |
1200 | prctl(PR_SET_DUMPABLE, 0, 0, 0, 0); |
1201 | setrlimit(RLIMIT_CORE, &rlimit); |
1202 | smash_stack(); |
1203 | return 1; |
1204 | |
1205 | default: |
1206 | pid = waitpid(pid, &status, 0); |
1207 | |
1208 | if (pid == -1 || !WIFSIGNALED(status) || WTERMSIG(status) != SIGABRT) { |
1209 | llen += printf("waitpid()" ); |
1210 | result(llen, r: FAIL); |
1211 | return 1; |
1212 | } |
1213 | result(llen, r: OK); |
1214 | return 0; |
1215 | } |
1216 | } |
1217 | |
1218 | /* prepare what needs to be prepared for pid 1 (stdio, /dev, /proc, etc) */ |
1219 | int prepare(void) |
1220 | { |
1221 | struct stat stat_buf; |
1222 | |
1223 | /* It's possible that /dev doesn't even exist or was not mounted, so |
1224 | * we'll try to create it, mount it, or create minimal entries into it. |
1225 | * We want at least /dev/null and /dev/console. |
1226 | */ |
1227 | if (stat("/dev/." , &stat_buf) == 0 || mkdir("/dev" , 0755) == 0) { |
1228 | if (stat("/dev/console" , &stat_buf) != 0 || |
1229 | stat("/dev/null" , &stat_buf) != 0 || |
1230 | stat("/dev/zero" , &stat_buf) != 0) { |
1231 | /* try devtmpfs first, otherwise fall back to manual creation */ |
1232 | if (mount("/dev" , "/dev" , "devtmpfs" , 0, 0) != 0) { |
1233 | mknod("/dev/console" , 0600 | S_IFCHR, makedev(5, 1)); |
1234 | mknod("/dev/null" , 0666 | S_IFCHR, makedev(1, 3)); |
1235 | mknod("/dev/zero" , 0666 | S_IFCHR, makedev(1, 5)); |
1236 | } |
1237 | } |
1238 | } |
1239 | |
1240 | /* If no /dev/console was found before calling init, stdio is closed so |
1241 | * we need to reopen it from /dev/console. If it failed above, it will |
1242 | * still fail here and we cannot emit a message anyway. |
1243 | */ |
1244 | if (close(dup(1)) == -1) { |
1245 | int fd = open("/dev/console" , O_RDWR); |
1246 | |
1247 | if (fd >= 0) { |
1248 | if (fd != 0) |
1249 | dup2(fd, 0); |
1250 | if (fd != 1) |
1251 | dup2(fd, 1); |
1252 | if (fd != 2) |
1253 | dup2(fd, 2); |
1254 | if (fd > 2) |
1255 | close(fd); |
1256 | puts("\nSuccessfully reopened /dev/console." ); |
1257 | } |
1258 | } |
1259 | |
1260 | /* try to mount /proc if not mounted. Silently fail otherwise */ |
1261 | if (stat("/proc/." , &stat_buf) == 0 || mkdir("/proc" , 0755) == 0) { |
1262 | if (stat("/proc/self" , &stat_buf) != 0) { |
1263 | /* If not mountable, remove /proc completely to avoid misuse */ |
1264 | if (mount("none" , "/proc" , "proc" , 0, 0) != 0) |
1265 | rmdir("/proc" ); |
1266 | } |
1267 | } |
1268 | |
1269 | /* some tests rely on a writable /tmp */ |
1270 | mkdir("/tmp" , 0755); |
1271 | |
1272 | return 0; |
1273 | } |
1274 | |
1275 | /* This is the definition of known test names, with their functions */ |
1276 | static const struct test test_names[] = { |
1277 | /* add new tests here */ |
1278 | { .name = "startup" , .func = run_startup }, |
1279 | { .name = "syscall" , .func = run_syscall }, |
1280 | { .name = "stdlib" , .func = run_stdlib }, |
1281 | { .name = "vfprintf" , .func = run_vfprintf }, |
1282 | { .name = "protection" , .func = run_protection }, |
1283 | { 0 } |
1284 | }; |
1285 | |
1286 | static int is_setting_valid(char *test) |
1287 | { |
1288 | int idx, len, test_len, valid = 0; |
1289 | char delimiter; |
1290 | |
1291 | if (!test) |
1292 | return valid; |
1293 | |
1294 | test_len = strlen(test); |
1295 | |
1296 | for (idx = 0; test_names[idx].name; idx++) { |
1297 | len = strlen(test_names[idx].name); |
1298 | if (test_len < len) |
1299 | continue; |
1300 | |
1301 | if (strncmp(test, test_names[idx].name, len) != 0) |
1302 | continue; |
1303 | |
1304 | delimiter = test[len]; |
1305 | if (delimiter != ':' && delimiter != ',' && delimiter != '\0') |
1306 | continue; |
1307 | |
1308 | valid = 1; |
1309 | break; |
1310 | } |
1311 | |
1312 | return valid; |
1313 | } |
1314 | |
1315 | int main(int argc, char **argv, char **envp) |
1316 | { |
1317 | int min = 0; |
1318 | int max = INT_MAX; |
1319 | int ret = 0; |
1320 | int err; |
1321 | int idx; |
1322 | char *test; |
1323 | |
1324 | argv0 = argv[0]; |
1325 | test_argc = argc; |
1326 | test_argv = argv; |
1327 | test_envp = envp; |
1328 | |
1329 | /* when called as init, it's possible that no console was opened, for |
1330 | * example if no /dev file system was provided. We'll check that fd#1 |
1331 | * was opened, and if not we'll attempt to create and open /dev/console |
1332 | * and /dev/null that we'll use for later tests. |
1333 | */ |
1334 | if (getpid() == 1) |
1335 | prepare(); |
1336 | |
1337 | /* the definition of a series of tests comes from either argv[1] or the |
1338 | * "NOLIBC_TEST" environment variable. It's made of a comma-delimited |
1339 | * series of test names and optional ranges: |
1340 | * syscall:5-15[:.*],stdlib:8-10 |
1341 | */ |
1342 | test = argv[1]; |
1343 | if (!is_setting_valid(test)) |
1344 | test = getenv("NOLIBC_TEST" ); |
1345 | |
1346 | if (is_setting_valid(test)) { |
1347 | char *comma, *colon, *dash, *value; |
1348 | |
1349 | do { |
1350 | comma = strchr(test, ','); |
1351 | if (comma) |
1352 | *(comma++) = '\0'; |
1353 | |
1354 | colon = strchr(test, ':'); |
1355 | if (colon) |
1356 | *(colon++) = '\0'; |
1357 | |
1358 | for (idx = 0; test_names[idx].name; idx++) { |
1359 | if (strcmp(test, test_names[idx].name) == 0) |
1360 | break; |
1361 | } |
1362 | |
1363 | if (test_names[idx].name) { |
1364 | /* The test was named, it will be called at least |
1365 | * once. We may have an optional range at <colon> |
1366 | * here, which defaults to the full range. |
1367 | */ |
1368 | do { |
1369 | min = 0; max = INT_MAX; |
1370 | value = colon; |
1371 | if (value && *value) { |
1372 | colon = strchr(value, ':'); |
1373 | if (colon) |
1374 | *(colon++) = '\0'; |
1375 | |
1376 | dash = strchr(value, '-'); |
1377 | if (dash) |
1378 | *(dash++) = '\0'; |
1379 | |
1380 | /* support :val: :min-max: :min-: :-max: */ |
1381 | if (*value) |
1382 | min = atoi(value); |
1383 | if (!dash) |
1384 | max = min; |
1385 | else if (*dash) |
1386 | max = atoi(dash); |
1387 | |
1388 | value = colon; |
1389 | } |
1390 | |
1391 | /* now's time to call the test */ |
1392 | printf("Running test '%s'\n" , test_names[idx].name); |
1393 | err = test_names[idx].func(min, max); |
1394 | ret += err; |
1395 | printf("Errors during this test: %d\n\n" , err); |
1396 | } while (colon && *colon); |
1397 | } else |
1398 | printf("Ignoring unknown test name '%s'\n" , test); |
1399 | |
1400 | test = comma; |
1401 | } while (test && *test); |
1402 | } else { |
1403 | /* no test mentioned, run everything */ |
1404 | for (idx = 0; test_names[idx].name; idx++) { |
1405 | printf("Running test '%s'\n" , test_names[idx].name); |
1406 | err = test_names[idx].func(min, max); |
1407 | ret += err; |
1408 | printf("Errors during this test: %d\n\n" , err); |
1409 | } |
1410 | } |
1411 | |
1412 | printf("Total number of errors: %d\n" , ret); |
1413 | |
1414 | if (getpid() == 1) { |
1415 | /* we're running as init, there's no other process on the |
1416 | * system, thus likely started from a VM for a quick check. |
1417 | * Exiting will provoke a kernel panic that may be reported |
1418 | * as an error by Qemu or the hypervisor, while stopping |
1419 | * cleanly will often be reported as a success. This allows |
1420 | * to use the output of this program for bisecting kernels. |
1421 | */ |
1422 | printf("Leaving init with final status: %d\n" , !!ret); |
1423 | if (ret == 0) |
1424 | reboot(RB_POWER_OFF); |
1425 | #if defined(__x86_64__) |
1426 | /* QEMU started with "-device isa-debug-exit -no-reboot" will |
1427 | * exit with status code 2N+1 when N is written to 0x501. We |
1428 | * hard-code the syscall here as it's arch-dependent. |
1429 | */ |
1430 | else if (syscall(__NR_ioperm, 0x501, 1, 1) == 0) |
1431 | __asm__ volatile ("outb %%al, %%dx" :: "d" (0x501), "a" (0)); |
1432 | /* if it does nothing, fall back to the regular panic */ |
1433 | #endif |
1434 | } |
1435 | |
1436 | printf("Exiting with status %d\n" , !!ret); |
1437 | return !!ret; |
1438 | } |
1439 | |