1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2015-2016 Cyril Hrubis <chrubis@suse.cz>
4 */
5
6 #include <limits.h>
7 #include <stdio.h>
8 #include <stdarg.h>
9 #include <unistd.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <errno.h>
13 #include <sys/mount.h>
14 #include <sys/types.h>
15 #include <sys/wait.h>
16
17 #define TST_NO_DEFAULT_MAIN
18 #include "tst_test.h"
19 #include "tst_device.h"
20 #include "lapi/futex.h"
21 #include "lapi/syscalls.h"
22 #include "tst_ansi_color.h"
23 #include "tst_safe_stdio.h"
24 #include "tst_timer_test.h"
25 #include "tst_clocks.h"
26 #include "tst_timer.h"
27 #include "tst_wallclock.h"
28 #include "tst_sys_conf.h"
29 #include "tst_kconfig.h"
30
31 #include "old_resource.h"
32 #include "old_device.h"
33 #include "old_tmpdir.h"
34
35 /*
36 * Hack to get TCID defined in newlib tests
37 */
38 const char *TCID __attribute__((weak));
39
40 #define LINUX_GIT_URL "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id="
41 #define CVE_DB_URL "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-"
42
43 struct tst_test *tst_test;
44
45 static const char *tid;
46 static int iterations = 1;
47 static float duration = -1;
48 static float timeout_mul = -1;
49 static pid_t main_pid, lib_pid;
50 static int mntpoint_mounted;
51 static int ovl_mounted;
52 static struct timespec tst_start_time; /* valid only for test pid */
53
54 struct results {
55 int passed;
56 int skipped;
57 int failed;
58 int warnings;
59 unsigned int timeout;
60 };
61
62 static struct results *results;
63
64 static int ipc_fd;
65
66 extern void *tst_futexes;
67 extern unsigned int tst_max_futexes;
68
69 #define IPC_ENV_VAR "LTP_IPC_PATH"
70
71 static char ipc_path[1064];
72 const char *tst_ipc_path = ipc_path;
73
74 static char shm_path[1024];
75
76 int TST_ERR;
77 long TST_RET;
78
79 static void do_cleanup(void);
80 static void do_exit(int ret) __attribute__ ((noreturn));
81
setup_ipc(void)82 static void setup_ipc(void)
83 {
84 size_t size = getpagesize();
85
86 if (access("/dev/shm", F_OK) == 0) {
87 snprintf(shm_path, sizeof(shm_path), "/dev/shm/ltp_%s_%d",
88 tid, getpid());
89 } else {
90 char *tmpdir;
91
92 if (!tst_tmpdir_created())
93 tst_tmpdir();
94
95 tmpdir = tst_get_tmpdir();
96 snprintf(shm_path, sizeof(shm_path), "%s/ltp_%s_%d",
97 tmpdir, tid, getpid());
98 free(tmpdir);
99 }
100
101 ipc_fd = open(shm_path, O_CREAT | O_EXCL | O_RDWR, 0600);
102 if (ipc_fd < 0)
103 tst_brk(TBROK | TERRNO, "open(%s)", shm_path);
104 SAFE_CHMOD(shm_path, 0666);
105
106 SAFE_FTRUNCATE(ipc_fd, size);
107
108 results = SAFE_MMAP(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, ipc_fd, 0);
109
110 /* Checkpoints needs to be accessible from processes started by exec() */
111 if (tst_test->needs_checkpoints || tst_test->child_needs_reinit) {
112 sprintf(ipc_path, IPC_ENV_VAR "=%s", shm_path);
113 putenv(ipc_path);
114 } else {
115 SAFE_UNLINK(shm_path);
116 }
117
118 SAFE_CLOSE(ipc_fd);
119
120 if (tst_test->needs_checkpoints) {
121 tst_futexes = (char*)results + sizeof(struct results);
122 tst_max_futexes = (size - sizeof(struct results))/sizeof(futex_t);
123 }
124 }
125
cleanup_ipc(void)126 static void cleanup_ipc(void)
127 {
128 size_t size = getpagesize();
129
130 if (ipc_fd > 0 && close(ipc_fd))
131 tst_res(TWARN | TERRNO, "close(ipc_fd) failed");
132
133 if (shm_path[0] && !access(shm_path, F_OK) && unlink(shm_path))
134 tst_res(TWARN | TERRNO, "unlink(%s) failed", shm_path);
135
136 if (results) {
137 msync((void*)results, size, MS_SYNC);
138 munmap((void*)results, size);
139 results = NULL;
140 }
141 }
142
tst_reinit(void)143 void tst_reinit(void)
144 {
145 const char *path = getenv(IPC_ENV_VAR);
146 size_t size = getpagesize();
147 int fd;
148
149 if (!path)
150 tst_brk(TBROK, IPC_ENV_VAR" is not defined");
151
152 if (access(path, F_OK))
153 tst_brk(TBROK, "File %s does not exist!", path);
154
155 fd = SAFE_OPEN(path, O_RDWR);
156
157 results = SAFE_MMAP(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
158 tst_futexes = (char*)results + sizeof(struct results);
159 tst_max_futexes = (size - sizeof(struct results))/sizeof(futex_t);
160
161 SAFE_CLOSE(fd);
162 }
163
update_results(int ttype)164 static void update_results(int ttype)
165 {
166 if (!results)
167 return;
168
169 switch (ttype) {
170 case TCONF:
171 tst_atomic_inc(&results->skipped);
172 break;
173 case TPASS:
174 tst_atomic_inc(&results->passed);
175 break;
176 case TWARN:
177 tst_atomic_inc(&results->warnings);
178 break;
179 case TFAIL:
180 tst_atomic_inc(&results->failed);
181 break;
182 }
183 }
184
print_result(const char * file,const int lineno,int ttype,const char * fmt,va_list va)185 static void print_result(const char *file, const int lineno, int ttype,
186 const char *fmt, va_list va)
187 {
188 char buf[1024];
189 char *str = buf;
190 int ret, size = sizeof(buf), ssize, int_errno, buflen;
191 const char *str_errno = NULL;
192 const char *res;
193
194 switch (TTYPE_RESULT(ttype)) {
195 case TPASS:
196 res = "PASS";
197 break;
198 case TFAIL:
199 res = "FAIL";
200 break;
201 case TBROK:
202 res = "BROK";
203 break;
204 case TCONF:
205 res = "CONF";
206 break;
207 case TWARN:
208 res = "WARN";
209 break;
210 case TINFO:
211 res = "INFO";
212 break;
213 default:
214 tst_brk(TBROK, "Invalid ttype value %i", ttype);
215 abort();
216 }
217
218 if (ttype & TERRNO) {
219 str_errno = tst_strerrno(errno);
220 int_errno = errno;
221 }
222
223 if (ttype & TTERRNO) {
224 str_errno = tst_strerrno(TST_ERR);
225 int_errno = TST_ERR;
226 }
227
228 if (ttype & TRERRNO) {
229 int_errno = TST_RET < 0 ? -(int)TST_RET : (int)TST_RET;
230 str_errno = tst_strerrno(int_errno);
231 }
232
233 ret = snprintf(str, size, "%s:%i: ", file, lineno);
234 str += ret;
235 size -= ret;
236
237 if (tst_color_enabled(STDERR_FILENO))
238 ret = snprintf(str, size, "%s%s: %s", tst_ttype2color(ttype),
239 res, ANSI_COLOR_RESET);
240 else
241 ret = snprintf(str, size, "%s: ", res);
242 str += ret;
243 size -= ret;
244
245 ssize = size - 2;
246 ret = vsnprintf(str, size, fmt, va);
247 str += MIN(ret, ssize);
248 size -= MIN(ret, ssize);
249 if (ret >= ssize) {
250 tst_res_(file, lineno, TWARN,
251 "Next message is too long and truncated:");
252 } else if (str_errno) {
253 ssize = size - 2;
254 ret = snprintf(str, size, ": %s (%d)", str_errno, int_errno);
255 str += MIN(ret, ssize);
256 size -= MIN(ret, ssize);
257 if (ret >= ssize)
258 tst_res_(file, lineno, TWARN,
259 "Next message is too long and truncated:");
260 }
261
262 snprintf(str, size, "\n");
263
264 /* we might be called from signal handler, so use write() */
265 buflen = str - buf + 1;
266 str = buf;
267 while (buflen) {
268 ret = write(STDERR_FILENO, str, buflen);
269 if (ret <= 0)
270 break;
271
272 str += ret;
273 buflen -= ret;
274 }
275 }
276
tst_vres_(const char * file,const int lineno,int ttype,const char * fmt,va_list va)277 void tst_vres_(const char *file, const int lineno, int ttype,
278 const char *fmt, va_list va)
279 {
280 print_result(file, lineno, ttype, fmt, va);
281
282 update_results(TTYPE_RESULT(ttype));
283 }
284
285 void tst_vbrk_(const char *file, const int lineno, int ttype,
286 const char *fmt, va_list va);
287
288 static void (*tst_brk_handler)(const char *file, const int lineno, int ttype,
289 const char *fmt, va_list va) = tst_vbrk_;
290
tst_cvres(const char * file,const int lineno,int ttype,const char * fmt,va_list va)291 static void tst_cvres(const char *file, const int lineno, int ttype,
292 const char *fmt, va_list va)
293 {
294 if (TTYPE_RESULT(ttype) == TBROK) {
295 ttype &= ~TTYPE_MASK;
296 ttype |= TWARN;
297 }
298
299 print_result(file, lineno, ttype, fmt, va);
300 update_results(TTYPE_RESULT(ttype));
301 }
302
do_test_cleanup(void)303 static void do_test_cleanup(void)
304 {
305 tst_brk_handler = tst_cvres;
306
307 if (tst_test->cleanup)
308 tst_test->cleanup();
309
310 tst_free_all();
311
312 tst_brk_handler = tst_vbrk_;
313 }
314
tst_vbrk_(const char * file,const int lineno,int ttype,const char * fmt,va_list va)315 void tst_vbrk_(const char *file, const int lineno, int ttype,
316 const char *fmt, va_list va)
317 {
318 print_result(file, lineno, ttype, fmt, va);
319
320 /*
321 * The getpid implementation in some C library versions may cause cloned
322 * test threads to show the same pid as their parent when CLONE_VM is
323 * specified but CLONE_THREAD is not. Use direct syscall to avoid
324 * cleanup running in the child.
325 */
326 if (syscall(SYS_getpid) == main_pid)
327 do_test_cleanup();
328
329 if (getpid() == lib_pid)
330 do_exit(TTYPE_RESULT(ttype));
331
332 exit(TTYPE_RESULT(ttype));
333 }
334
tst_res_(const char * file,const int lineno,int ttype,const char * fmt,...)335 void tst_res_(const char *file, const int lineno, int ttype,
336 const char *fmt, ...)
337 {
338 va_list va;
339
340 va_start(va, fmt);
341 tst_vres_(file, lineno, ttype, fmt, va);
342 va_end(va);
343 }
344
tst_brk_(const char * file,const int lineno,int ttype,const char * fmt,...)345 void tst_brk_(const char *file, const int lineno, int ttype,
346 const char *fmt, ...)
347 {
348 va_list va;
349
350 va_start(va, fmt);
351 tst_brk_handler(file, lineno, ttype, fmt, va);
352 va_end(va);
353 }
354
check_child_status(pid_t pid,int status)355 static void check_child_status(pid_t pid, int status)
356 {
357 int ret;
358
359 if (WIFSIGNALED(status)) {
360 tst_brk(TBROK, "Child (%i) killed by signal %s",
361 pid, tst_strsig(WTERMSIG(status)));
362 }
363
364 if (!(WIFEXITED(status)))
365 tst_brk(TBROK, "Child (%i) exited abnormaly", pid);
366
367 ret = WEXITSTATUS(status);
368 switch (ret) {
369 case TPASS:
370 break;
371 case TBROK:
372 case TCONF:
373 tst_brk(ret, "Reported by child (%i)", pid);
374 break;
375 default:
376 tst_brk(TBROK, "Invalid child (%i) exit value %i", pid, ret);
377 }
378 }
379
tst_reap_children(void)380 void tst_reap_children(void)
381 {
382 int status;
383 pid_t pid;
384
385 for (;;) {
386 pid = wait(&status);
387
388 if (pid > 0) {
389 check_child_status(pid, status);
390 continue;
391 }
392
393 if (errno == ECHILD)
394 break;
395
396 if (errno == EINTR)
397 continue;
398
399 tst_brk(TBROK | TERRNO, "wait() failed");
400 }
401 }
402
403
safe_fork(const char * filename,unsigned int lineno)404 pid_t safe_fork(const char *filename, unsigned int lineno)
405 {
406 pid_t pid;
407
408 if (!tst_test->forks_child)
409 tst_brk(TBROK, "test.forks_child must be set!");
410
411 tst_flush();
412
413 pid = fork();
414 if (pid < 0)
415 tst_brk_(filename, lineno, TBROK | TERRNO, "fork() failed");
416
417 if (!pid)
418 atexit(tst_free_all);
419
420 return pid;
421 }
422
423 static struct option {
424 char *optstr;
425 char *help;
426 } options[] = {
427 {"h", "-h Prints this help"},
428 {"i:", "-i n Execute test n times"},
429 {"I:", "-I x Execute test for n seconds"},
430 {"C:", "-C ARG Run child process with ARG arguments (used internally)"},
431 };
432
print_help(void)433 static void print_help(void)
434 {
435 unsigned int i;
436
437 fprintf(stderr, "Options\n");
438 fprintf(stderr, "-------\n");
439
440 for (i = 0; i < ARRAY_SIZE(options); i++)
441 fprintf(stderr, "%s\n", options[i].help);
442
443 if (!tst_test->options)
444 return;
445
446 for (i = 0; tst_test->options[i].optstr; i++)
447 fprintf(stderr, "%s\n", tst_test->options[i].help);
448 }
449
print_test_tags(void)450 static void print_test_tags(void)
451 {
452 unsigned int i;
453 const struct tst_tag *tags = tst_test->tags;
454
455 if (!tags)
456 return;
457
458 printf("\nTags\n");
459 printf("----\n");
460
461 for (i = 0; tags[i].name; i++) {
462 if (!strcmp(tags[i].name, "CVE"))
463 printf(CVE_DB_URL "%s\n", tags[i].value);
464 else if (!strcmp(tags[i].name, "linux-git"))
465 printf(LINUX_GIT_URL "%s\n", tags[i].value);
466 else
467 printf("%s: %s\n", tags[i].name, tags[i].value);
468 }
469
470 printf("\n");
471 }
472
check_option_collision(void)473 static void check_option_collision(void)
474 {
475 unsigned int i, j;
476 struct tst_option *toptions = tst_test->options;
477
478 if (!toptions)
479 return;
480
481 for (i = 0; toptions[i].optstr; i++) {
482 for (j = 0; j < ARRAY_SIZE(options); j++) {
483 if (toptions[i].optstr[0] == options[j].optstr[0]) {
484 tst_brk(TBROK, "Option collision '%s'",
485 options[j].help);
486 }
487 }
488 }
489 }
490
count_options(void)491 static unsigned int count_options(void)
492 {
493 unsigned int i;
494
495 if (!tst_test->options)
496 return 0;
497
498 for (i = 0; tst_test->options[i].optstr; i++);
499
500 return i;
501 }
502
parse_topt(unsigned int topts_len,int opt,char * optarg)503 static void parse_topt(unsigned int topts_len, int opt, char *optarg)
504 {
505 unsigned int i;
506 struct tst_option *toptions = tst_test->options;
507
508 for (i = 0; i < topts_len; i++) {
509 if (toptions[i].optstr[0] == opt)
510 break;
511 }
512
513 if (i >= topts_len)
514 tst_brk(TBROK, "Invalid option '%c' (should not happen)", opt);
515
516 if (*toptions[i].arg)
517 tst_res(TWARN, "Option -%c passed multiple times", opt);
518
519 *(toptions[i].arg) = optarg ? optarg : "";
520 }
521
522 /* see self_exec.c */
523 #ifdef UCLINUX
524 extern char *child_args;
525 #endif
526
parse_opts(int argc,char * argv[])527 static void parse_opts(int argc, char *argv[])
528 {
529 unsigned int i, topts_len = count_options();
530 char optstr[2 * ARRAY_SIZE(options) + 2 * topts_len];
531 int opt;
532
533 check_option_collision();
534
535 optstr[0] = 0;
536
537 for (i = 0; i < ARRAY_SIZE(options); i++)
538 strcat(optstr, options[i].optstr);
539
540 for (i = 0; i < topts_len; i++)
541 strcat(optstr, tst_test->options[i].optstr);
542
543 while ((opt = getopt(argc, argv, optstr)) > 0) {
544 switch (opt) {
545 case '?':
546 print_help();
547 tst_brk(TBROK, "Invalid option");
548 break;
549 case 'h':
550 print_help();
551 print_test_tags();
552 exit(0);
553 case 'i':
554 iterations = atoi(optarg);
555 break;
556 case 'I':
557 duration = atof(optarg);
558 break;
559 case 'C':
560 #ifdef UCLINUX
561 child_args = optarg;
562 #endif
563 break;
564 default:
565 parse_topt(topts_len, opt, optarg);
566 }
567 }
568
569 if (optind < argc)
570 tst_brk(TBROK, "Unexpected argument(s) '%s'...", argv[optind]);
571 }
572
tst_parse_int(const char * str,int * val,int min,int max)573 int tst_parse_int(const char *str, int *val, int min, int max)
574 {
575 long rval;
576
577 if (!str)
578 return 0;
579
580 int ret = tst_parse_long(str, &rval, min, max);
581
582 if (ret)
583 return ret;
584
585 *val = (int)rval;
586 return 0;
587 }
588
tst_parse_long(const char * str,long * val,long min,long max)589 int tst_parse_long(const char *str, long *val, long min, long max)
590 {
591 long rval;
592 char *end;
593
594 if (!str)
595 return 0;
596
597 errno = 0;
598 rval = strtol(str, &end, 10);
599
600 if (str == end || *end != '\0')
601 return EINVAL;
602
603 if (errno)
604 return errno;
605
606 if (rval > max || rval < min)
607 return ERANGE;
608
609 *val = rval;
610 return 0;
611 }
612
tst_parse_float(const char * str,float * val,float min,float max)613 int tst_parse_float(const char *str, float *val, float min, float max)
614 {
615 double rval;
616 char *end;
617
618 if (!str)
619 return 0;
620
621 errno = 0;
622 rval = strtod(str, &end);
623
624 if (str == end || *end != '\0')
625 return EINVAL;
626
627 if (errno)
628 return errno;
629
630 if (rval > (double)max || rval < (double)min)
631 return ERANGE;
632
633 *val = (float)rval;
634 return 0;
635 }
636
print_colored(const char * str)637 static void print_colored(const char *str)
638 {
639 if (tst_color_enabled(STDOUT_FILENO))
640 printf("%s%s%s", ANSI_COLOR_YELLOW, str, ANSI_COLOR_RESET);
641 else
642 printf("%s", str);
643 }
644
print_failure_hints(void)645 static void print_failure_hints(void)
646 {
647 unsigned int i;
648 const struct tst_tag *tags = tst_test->tags;
649
650 if (!tags)
651 return;
652
653 int hint_printed = 0;
654 for (i = 0; tags[i].name; i++) {
655 if (!strcmp(tags[i].name, "linux-git")) {
656 if (!hint_printed) {
657 hint_printed = 1;
658 printf("\n");
659 print_colored("HINT: ");
660 printf("You _MAY_ be missing kernel fixes, see:\n\n");
661 }
662
663 printf(LINUX_GIT_URL "%s\n", tags[i].value);
664 }
665
666 }
667
668 hint_printed = 0;
669 for (i = 0; tags[i].name; i++) {
670 if (!strcmp(tags[i].name, "CVE")) {
671 if (!hint_printed) {
672 hint_printed = 1;
673 printf("\n");
674 print_colored("HINT: ");
675 printf("You _MAY_ be vunerable to CVE(s), see:\n\n");
676 }
677
678 printf(CVE_DB_URL "%s\n", tags[i].value);
679 }
680 }
681 }
682
do_exit(int ret)683 static void do_exit(int ret)
684 {
685 if (results) {
686 if (results->passed && ret == TCONF)
687 ret = 0;
688
689 if (results->failed) {
690 ret |= TFAIL;
691 print_failure_hints();
692 }
693
694 if (results->skipped && !results->passed)
695 ret |= TCONF;
696
697 if (results->warnings)
698 ret |= TWARN;
699
700 printf("\nSummary:\n");
701 printf("passed %d\n", results->passed);
702 printf("failed %d\n", results->failed);
703 printf("skipped %d\n", results->skipped);
704 printf("warnings %d\n", results->warnings);
705 }
706
707 do_cleanup();
708
709 exit(ret);
710 }
711
check_kver(void)712 void check_kver(void)
713 {
714 int v1, v2, v3;
715
716 if (tst_parse_kver(tst_test->min_kver, &v1, &v2, &v3)) {
717 tst_res(TWARN,
718 "Invalid kernel version %s, expected %%d.%%d.%%d",
719 tst_test->min_kver);
720 }
721
722 if (tst_kvercmp(v1, v2, v3) < 0) {
723 tst_brk(TCONF, "The test requires kernel %s or newer",
724 tst_test->min_kver);
725 }
726 }
727
results_equal(struct results * a,struct results * b)728 static int results_equal(struct results *a, struct results *b)
729 {
730 if (a->passed != b->passed)
731 return 0;
732
733 if (a->failed != b->failed)
734 return 0;
735
736 if (a->skipped != b->skipped)
737 return 0;
738
739 return 1;
740 }
741
needs_tmpdir(void)742 static int needs_tmpdir(void)
743 {
744 return tst_test->needs_tmpdir ||
745 tst_test->needs_device ||
746 tst_test->mntpoint ||
747 tst_test->resource_files ||
748 tst_test->needs_checkpoints;
749 }
750
copy_resources(void)751 static void copy_resources(void)
752 {
753 unsigned int i;
754
755 for (i = 0; tst_test->resource_files[i]; i++)
756 TST_RESOURCE_COPY(NULL, tst_test->resource_files[i], NULL);
757 }
758
get_tid(char * argv[])759 static const char *get_tid(char *argv[])
760 {
761 char *p;
762
763 if (!argv[0] || !argv[0][0]) {
764 tst_res(TINFO, "argv[0] is empty!");
765 return "ltp_empty_argv";
766 }
767
768 p = strrchr(argv[0], '/');
769 if (p)
770 return p+1;
771
772 return argv[0];
773 }
774
775 static struct tst_device tdev;
776 struct tst_device *tst_device;
777
assert_test_fn(void)778 static void assert_test_fn(void)
779 {
780 int cnt = 0;
781
782 if (tst_test->test)
783 cnt++;
784
785 if (tst_test->test_all)
786 cnt++;
787
788 if (tst_test->sample)
789 cnt++;
790
791 if (!cnt)
792 tst_brk(TBROK, "No test function speficied");
793
794 if (cnt != 1)
795 tst_brk(TBROK, "You can define only one test function");
796
797 if (tst_test->test && !tst_test->tcnt)
798 tst_brk(TBROK, "Number of tests (tcnt) must be > 0");
799
800 if (!tst_test->test && tst_test->tcnt)
801 tst_brk(TBROK, "You can define tcnt only for test()");
802 }
803
prepare_and_mount_ro_fs(const char * dev,const char * mntpoint,const char * fs_type)804 static int prepare_and_mount_ro_fs(const char *dev,
805 const char *mntpoint,
806 const char *fs_type)
807 {
808 char buf[PATH_MAX];
809
810 if (mount(dev, mntpoint, fs_type, 0, NULL)) {
811 tst_res(TINFO | TERRNO, "Can't mount %s at %s (%s)",
812 dev, mntpoint, fs_type);
813 return 1;
814 }
815
816 mntpoint_mounted = 1;
817
818 snprintf(buf, sizeof(buf), "%s/dir/", mntpoint);
819 SAFE_MKDIR(buf, 0777);
820
821 snprintf(buf, sizeof(buf), "%s/file", mntpoint);
822 SAFE_FILE_PRINTF(buf, "file content");
823 SAFE_CHMOD(buf, 0777);
824
825 SAFE_MOUNT(dev, mntpoint, fs_type, MS_REMOUNT | MS_RDONLY, NULL);
826
827 return 0;
828 }
829
prepare_and_mount_dev_fs(const char * mntpoint)830 static void prepare_and_mount_dev_fs(const char *mntpoint)
831 {
832 const char *flags[] = {"nodev", NULL};
833 int mounted_nodev;
834
835 mounted_nodev = tst_path_has_mnt_flags(NULL, flags);
836 if (mounted_nodev) {
837 tst_res(TINFO, "tmpdir isn't suitable for creating devices, "
838 "mounting tmpfs without nodev on %s", mntpoint);
839 SAFE_MOUNT(NULL, mntpoint, "tmpfs", 0, NULL);
840 mntpoint_mounted = 1;
841 }
842 }
843
prepare_device(void)844 static void prepare_device(void)
845 {
846 if (tst_test->format_device) {
847 SAFE_MKFS(tdev.dev, tdev.fs_type, tst_test->dev_fs_opts,
848 tst_test->dev_extra_opts);
849 }
850
851 if (tst_test->needs_rofs) {
852 prepare_and_mount_ro_fs(tdev.dev, tst_test->mntpoint,
853 tdev.fs_type);
854 return;
855 }
856
857 if (tst_test->mount_device) {
858 SAFE_MOUNT(tdev.dev, tst_test->mntpoint, tdev.fs_type,
859 tst_test->mnt_flags, tst_test->mnt_data);
860 mntpoint_mounted = 1;
861 }
862 }
863
do_setup(int argc,char * argv[])864 static void do_setup(int argc, char *argv[])
865 {
866 if (!tst_test)
867 tst_brk(TBROK, "No tests to run");
868
869 if (tst_test->tconf_msg)
870 tst_brk(TCONF, "%s", tst_test->tconf_msg);
871
872 if (tst_test->needs_kconfigs)
873 tst_kconfig_check(tst_test->needs_kconfigs);
874
875 assert_test_fn();
876
877 tid = get_tid(argv);
878
879 if (tst_test->sample)
880 tst_test = tst_timer_test_setup(tst_test);
881
882 parse_opts(argc, argv);
883
884 if (tst_test->needs_root && geteuid() != 0)
885 tst_brk(TCONF, "Test needs to be run as root");
886
887 if (tst_test->min_kver)
888 check_kver();
889
890 if (tst_test->needs_cmds) {
891 const char *cmd;
892 char path[PATH_MAX];
893 int i;
894
895 for (i = 0; (cmd = tst_test->needs_cmds[i]); ++i)
896 if (tst_get_path(cmd, path, sizeof(path)))
897 tst_brk(TCONF, "Couldn't find '%s' in $PATH", cmd);
898 }
899
900 if (tst_test->needs_drivers) {
901 const char *name;
902 int i;
903
904 for (i = 0; (name = tst_test->needs_drivers[i]); ++i)
905 if (tst_check_driver(name))
906 tst_brk(TCONF, "%s driver not available", name);
907 }
908
909 if (tst_test->format_device)
910 tst_test->needs_device = 1;
911
912 if (tst_test->mount_device) {
913 tst_test->needs_device = 1;
914 tst_test->format_device = 1;
915 }
916
917 if (tst_test->all_filesystems)
918 tst_test->needs_device = 1;
919
920 if (tst_test->request_hugepages)
921 tst_request_hugepages(tst_test->request_hugepages);
922
923 setup_ipc();
924
925 if (tst_test->bufs)
926 tst_buffers_alloc(tst_test->bufs);
927
928 if (needs_tmpdir() && !tst_tmpdir_created())
929 tst_tmpdir();
930
931 if (tst_test->save_restore) {
932 const char * const *name = tst_test->save_restore;
933
934 while (*name) {
935 tst_sys_conf_save(*name);
936 name++;
937 }
938 }
939
940 if (tst_test->mntpoint)
941 SAFE_MKDIR(tst_test->mntpoint, 0777);
942
943 if ((tst_test->needs_devfs || tst_test->needs_rofs ||
944 tst_test->mount_device || tst_test->all_filesystems) &&
945 !tst_test->mntpoint) {
946 tst_brk(TBROK, "tst_test->mntpoint must be set!");
947 }
948
949 if (!!tst_test->needs_rofs + !!tst_test->needs_devfs +
950 !!tst_test->needs_device > 1) {
951 tst_brk(TBROK,
952 "Two or more of needs_{rofs, devfs, device} are set");
953 }
954
955 if (tst_test->needs_devfs)
956 prepare_and_mount_dev_fs(tst_test->mntpoint);
957
958 if (tst_test->needs_rofs) {
959 /* If we failed to mount read-only tmpfs. Fallback to
960 * using a device with read-only filesystem.
961 */
962 if (prepare_and_mount_ro_fs(NULL, tst_test->mntpoint, "tmpfs")) {
963 tst_res(TINFO, "Can't mount tmpfs read-only, "
964 "falling back to block device...");
965 tst_test->needs_device = 1;
966 tst_test->format_device = 1;
967 }
968 }
969
970 if (tst_test->needs_device && !mntpoint_mounted) {
971 tdev.dev = tst_acquire_device_(NULL, tst_test->dev_min_size);
972
973 if (!tdev.dev)
974 tst_brk(TCONF, "Failed to acquire device");
975
976 tst_device = &tdev;
977
978 if (tst_test->dev_fs_type)
979 tdev.fs_type = tst_test->dev_fs_type;
980 else
981 tdev.fs_type = tst_dev_fs_type();
982
983 if (!tst_test->all_filesystems)
984 prepare_device();
985 }
986
987 if (tst_test->needs_overlay && !tst_test->mount_device) {
988 tst_brk(TBROK, "tst_test->mount_device must be set");
989 }
990 if (tst_test->needs_overlay && !mntpoint_mounted) {
991 tst_brk(TBROK, "tst_test->mntpoint must be mounted");
992 }
993 if (tst_test->needs_overlay && !ovl_mounted) {
994 SAFE_MOUNT_OVERLAY();
995 ovl_mounted = 1;
996 }
997
998 if (tst_test->resource_files)
999 copy_resources();
1000
1001 if (tst_test->restore_wallclock)
1002 tst_wallclock_save();
1003 }
1004
do_test_setup(void)1005 static void do_test_setup(void)
1006 {
1007 main_pid = getpid();
1008
1009 if (tst_test->caps)
1010 tst_cap_setup(tst_test->caps, TST_CAP_REQ);
1011
1012 if (tst_test->setup)
1013 tst_test->setup();
1014
1015 if (main_pid != getpid())
1016 tst_brk(TBROK, "Runaway child in setup()!");
1017
1018 if (tst_test->caps)
1019 tst_cap_setup(tst_test->caps, TST_CAP_DROP);
1020 }
1021
do_cleanup(void)1022 static void do_cleanup(void)
1023 {
1024 if (ovl_mounted)
1025 SAFE_UMOUNT(OVL_MNT);
1026
1027 if (mntpoint_mounted)
1028 tst_umount(tst_test->mntpoint);
1029
1030 if (tst_test->needs_device && tdev.dev)
1031 tst_release_device(tdev.dev);
1032
1033 if (tst_tmpdir_created()) {
1034 /* avoid munmap() on wrong pointer in tst_rmdir() */
1035 tst_futexes = NULL;
1036 tst_rmdir();
1037 }
1038
1039 tst_sys_conf_restore(0);
1040
1041 if (tst_test->restore_wallclock)
1042 tst_wallclock_restore();
1043
1044 cleanup_ipc();
1045 }
1046
run_tests(void)1047 static void run_tests(void)
1048 {
1049 unsigned int i;
1050 struct results saved_results;
1051
1052 if (!tst_test->test) {
1053 saved_results = *results;
1054 tst_test->test_all();
1055
1056 if (getpid() != main_pid) {
1057 exit(0);
1058 }
1059
1060 tst_reap_children();
1061
1062 if (results_equal(&saved_results, results))
1063 tst_brk(TBROK, "Test haven't reported results!");
1064 return;
1065 }
1066
1067 for (i = 0; i < tst_test->tcnt; i++) {
1068 saved_results = *results;
1069 tst_test->test(i);
1070
1071 if (getpid() != main_pid) {
1072 exit(0);
1073 }
1074
1075 tst_reap_children();
1076
1077 if (results_equal(&saved_results, results))
1078 tst_brk(TBROK, "Test %i haven't reported results!", i);
1079 }
1080 }
1081
get_time_ms(void)1082 static unsigned long long get_time_ms(void)
1083 {
1084 struct timespec ts;
1085
1086 if (tst_clock_gettime(CLOCK_MONOTONIC, &ts))
1087 tst_brk(TBROK | TERRNO, "tst_clock_gettime()");
1088
1089 return tst_timespec_to_ms(ts);
1090 }
1091
add_paths(void)1092 static void add_paths(void)
1093 {
1094 char *old_path = getenv("PATH");
1095 const char *start_dir;
1096 char *new_path;
1097
1098 start_dir = tst_get_startwd();
1099
1100 if (old_path)
1101 SAFE_ASPRINTF(&new_path, "%s::%s", old_path, start_dir);
1102 else
1103 SAFE_ASPRINTF(&new_path, "::%s", start_dir);
1104
1105 SAFE_SETENV("PATH", new_path, 1);
1106 free(new_path);
1107 }
1108
heartbeat(void)1109 static void heartbeat(void)
1110 {
1111 if (tst_clock_gettime(CLOCK_MONOTONIC, &tst_start_time))
1112 tst_res(TWARN | TERRNO, "tst_clock_gettime() failed");
1113
1114 kill(getppid(), SIGUSR1);
1115 }
1116
testrun(void)1117 static void testrun(void)
1118 {
1119 unsigned int i = 0;
1120 unsigned long long stop_time = 0;
1121 int cont = 1;
1122
1123 heartbeat();
1124 add_paths();
1125 do_test_setup();
1126
1127 if (duration > 0)
1128 stop_time = get_time_ms() + (unsigned long long)(duration * 1000);
1129
1130 for (;;) {
1131 cont = 0;
1132
1133 if (i < (unsigned int)iterations) {
1134 i++;
1135 cont = 1;
1136 }
1137
1138 if (stop_time && get_time_ms() < stop_time)
1139 cont = 1;
1140
1141 if (!cont)
1142 break;
1143
1144 run_tests();
1145 heartbeat();
1146 }
1147
1148 do_test_cleanup();
1149 exit(0);
1150 }
1151
1152 static pid_t test_pid;
1153
1154
1155 static volatile sig_atomic_t sigkill_retries;
1156
1157 #define WRITE_MSG(msg) do { \
1158 if (write(2, msg, sizeof(msg) - 1)) { \
1159 /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425 */ \
1160 } \
1161 } while (0)
1162
alarm_handler(int sig LTP_ATTRIBUTE_UNUSED)1163 static void alarm_handler(int sig LTP_ATTRIBUTE_UNUSED)
1164 {
1165 WRITE_MSG("Test timeouted, sending SIGKILL!\n");
1166 kill(-test_pid, SIGKILL);
1167 alarm(5);
1168
1169 if (++sigkill_retries > 10) {
1170 WRITE_MSG("Cannot kill test processes!\n");
1171 WRITE_MSG("Congratulation, likely test hit a kernel bug.\n");
1172 WRITE_MSG("Exitting uncleanly...\n");
1173 _exit(TFAIL);
1174 }
1175 }
1176
heartbeat_handler(int sig LTP_ATTRIBUTE_UNUSED)1177 static void heartbeat_handler(int sig LTP_ATTRIBUTE_UNUSED)
1178 {
1179 alarm(results->timeout);
1180 sigkill_retries = 0;
1181 }
1182
sigint_handler(int sig LTP_ATTRIBUTE_UNUSED)1183 static void sigint_handler(int sig LTP_ATTRIBUTE_UNUSED)
1184 {
1185 if (test_pid > 0) {
1186 WRITE_MSG("Sending SIGKILL to test process...\n");
1187 kill(-test_pid, SIGKILL);
1188 }
1189 }
1190
tst_timeout_remaining(void)1191 unsigned int tst_timeout_remaining(void)
1192 {
1193 static struct timespec now;
1194 unsigned int elapsed;
1195
1196 if (tst_clock_gettime(CLOCK_MONOTONIC, &now))
1197 tst_res(TWARN | TERRNO, "tst_clock_gettime() failed");
1198
1199 elapsed = (tst_timespec_diff_ms(now, tst_start_time) + 500) / 1000;
1200 if (results->timeout > elapsed)
1201 return results->timeout - elapsed;
1202
1203 return 0;
1204 }
1205
tst_multiply_timeout(unsigned int timeout)1206 unsigned int tst_multiply_timeout(unsigned int timeout)
1207 {
1208 char *mul;
1209 int ret;
1210
1211 if (timeout_mul == -1) {
1212 mul = getenv("LTP_TIMEOUT_MUL");
1213 if (mul) {
1214 if ((ret = tst_parse_float(mul, &timeout_mul, 1, 10000))) {
1215 tst_brk(TBROK, "Failed to parse LTP_TIMEOUT_MUL: %s",
1216 tst_strerrno(ret));
1217 }
1218 } else {
1219 timeout_mul = 1;
1220 }
1221 }
1222 if (timeout_mul < 1)
1223 tst_brk(TBROK, "LTP_TIMEOUT_MUL must to be int >= 1! (%.2f)",
1224 timeout_mul);
1225
1226 if (timeout < 1)
1227 tst_brk(TBROK, "timeout must to be >= 1! (%d)", timeout);
1228
1229 return timeout * timeout_mul;
1230 }
1231
tst_set_timeout(int timeout)1232 void tst_set_timeout(int timeout)
1233 {
1234 if (timeout == -1) {
1235 tst_res(TINFO, "Timeout per run is disabled");
1236 return;
1237 }
1238
1239 if (timeout < 1)
1240 tst_brk(TBROK, "timeout must to be >= 1! (%d)", timeout);
1241
1242 results->timeout = tst_multiply_timeout(timeout);
1243
1244 tst_res(TINFO, "Timeout per run is %uh %02um %02us",
1245 results->timeout/3600, (results->timeout%3600)/60,
1246 results->timeout % 60);
1247
1248 if (getpid() == lib_pid)
1249 alarm(results->timeout);
1250 else
1251 heartbeat();
1252 }
1253
fork_testrun(void)1254 static int fork_testrun(void)
1255 {
1256 int status;
1257
1258 if (tst_test->timeout)
1259 tst_set_timeout(tst_test->timeout);
1260 else
1261 tst_set_timeout(300);
1262
1263 SAFE_SIGNAL(SIGINT, sigint_handler);
1264
1265 test_pid = fork();
1266 if (test_pid < 0)
1267 tst_brk(TBROK | TERRNO, "fork()");
1268
1269 if (!test_pid) {
1270 SAFE_SIGNAL(SIGALRM, SIG_DFL);
1271 SAFE_SIGNAL(SIGUSR1, SIG_DFL);
1272 SAFE_SIGNAL(SIGINT, SIG_DFL);
1273 SAFE_SETPGID(0, 0);
1274 testrun();
1275 }
1276
1277 SAFE_WAITPID(test_pid, &status, 0);
1278 alarm(0);
1279 SAFE_SIGNAL(SIGINT, SIG_DFL);
1280
1281 if (WIFEXITED(status) && WEXITSTATUS(status))
1282 return WEXITSTATUS(status);
1283
1284 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL) {
1285 tst_res(TINFO, "If you are running on slow machine, "
1286 "try exporting LTP_TIMEOUT_MUL > 1");
1287 tst_brk(TBROK, "Test killed! (timeout?)");
1288 }
1289
1290 if (WIFSIGNALED(status))
1291 tst_brk(TBROK, "Test killed by %s!", tst_strsig(WTERMSIG(status)));
1292
1293 return 0;
1294 }
1295
run_tcases_per_fs(void)1296 static int run_tcases_per_fs(void)
1297 {
1298 int ret = 0;
1299 unsigned int i;
1300 const char *const *filesystems = tst_get_supported_fs_types(tst_test->dev_fs_flags);
1301
1302 if (!filesystems[0])
1303 tst_brk(TCONF, "There are no supported filesystems");
1304
1305 for (i = 0; filesystems[i]; i++) {
1306
1307 tst_res(TINFO, "Testing on %s", filesystems[i]);
1308 tdev.fs_type = filesystems[i];
1309
1310 prepare_device();
1311
1312 ret = fork_testrun();
1313
1314 if (mntpoint_mounted) {
1315 tst_umount(tst_test->mntpoint);
1316 mntpoint_mounted = 0;
1317 }
1318
1319 if (ret == TCONF) {
1320 update_results(ret);
1321 continue;
1322 }
1323
1324 if (ret == 0)
1325 continue;
1326
1327 do_exit(ret);
1328 }
1329
1330 return ret;
1331 }
1332
1333 unsigned int tst_variant;
1334
tst_run_tcases(int argc,char * argv[],struct tst_test * self)1335 void tst_run_tcases(int argc, char *argv[], struct tst_test *self)
1336 {
1337 int ret = 0;
1338 unsigned int test_variants = 1;
1339
1340 lib_pid = getpid();
1341 tst_test = self;
1342
1343 do_setup(argc, argv);
1344
1345 TCID = tid;
1346
1347 SAFE_SIGNAL(SIGALRM, alarm_handler);
1348 SAFE_SIGNAL(SIGUSR1, heartbeat_handler);
1349
1350 if (tst_test->test_variants)
1351 test_variants = tst_test->test_variants;
1352
1353 for (tst_variant = 0; tst_variant < test_variants; tst_variant++) {
1354 if (tst_test->all_filesystems)
1355 ret |= run_tcases_per_fs();
1356 else
1357 ret |= fork_testrun();
1358
1359 if (ret & ~(TCONF))
1360 goto exit;
1361 }
1362
1363 exit:
1364 do_exit(ret);
1365 }
1366
1367
tst_flush(void)1368 void tst_flush(void)
1369 {
1370 int rval;
1371
1372 rval = fflush(stderr);
1373 if (rval != 0)
1374 tst_brk(TBROK | TERRNO, "fflush(stderr) failed");
1375
1376 rval = fflush(stderr);
1377 if (rval != 0)
1378 tst_brk(TBROK | TERRNO, "fflush(stdout) failed");
1379
1380 }
1381