2 * Copyright (C) 2016 Julien Desfossez <jdesfossez@efficios.com>
4 * SPDX-License-Identifier: GPL-2.0-only
9 * This test voluntarily does buffer overflows and stack overruns, disable
10 * source fortification.
12 #ifdef _FORTIFY_SOURCE
13 #undef _FORTIFY_SOURCE
26 #include <sys/epoll.h>
28 #include <sys/resource.h>
29 #include <sys/select.h>
31 #include <sys/syscall.h>
33 #include <sys/types.h>
36 #include <common/compat/time.hpp>
37 #include <common/error.hpp>
42 #define NR_ITER 1000 /* for stress-tests */
44 #define MIN_NR_FDS 5 /* the minimum number of open FDs required for the test to run */
45 #define BIG_SELECT_FD 1022
47 #define MSEC_PER_USEC 1000
48 #define MSEC_PER_NSEC (MSEC_PER_USEC * 1000)
50 static int timeout
; /* seconds, -1 to disable */
51 static volatile int stop_thread
;
54 /* Used by logging utils. */
55 int lttng_opt_quiet
, lttng_opt_verbose
, lttng_opt_mi
;
57 static void run_working_cases(FILE *validation_output_file
);
58 static void pselect_invalid_fd(FILE *validation_output_file
);
59 static void test_ppoll_big(FILE *validation_output_file
);
60 static void ppoll_fds_buffer_overflow(FILE *validation_output_file
);
61 static void pselect_invalid_pointer(FILE *validation_output_file
);
62 static void ppoll_fds_ulong_max(FILE *validation_output_file
);
63 static void epoll_pwait_invalid_pointer(FILE *validation_output_file
);
64 static void epoll_pwait_int_max(FILE *validation_output_file
);
65 static void ppoll_concurrent_write(FILE *validation_output_file
);
66 static void epoll_pwait_concurrent_munmap(FILE *validation_output_file
);
68 typedef void (*test_case_cb
)(FILE *output_file
);
71 const struct test_case
{
73 bool produces_validation_info
;
77 { .run
= run_working_cases
, .produces_validation_info
= true, .timeout
= -1 },
78 { .run
= run_working_cases
, .produces_validation_info
= true, .timeout
= 1 },
79 { .run
= pselect_invalid_fd
, .produces_validation_info
= false, .timeout
= 0 },
80 { .run
= test_ppoll_big
, .produces_validation_info
= false, .timeout
= 0 },
81 { .run
= ppoll_fds_buffer_overflow
, .produces_validation_info
= false, .timeout
= 0 },
82 { .run
= pselect_invalid_pointer
, .produces_validation_info
= false, .timeout
= 0 },
83 { .run
= ppoll_fds_ulong_max
, .produces_validation_info
= false, .timeout
= 0 },
84 { .run
= epoll_pwait_invalid_pointer
, .produces_validation_info
= true, .timeout
= 0 },
85 { .run
= epoll_pwait_int_max
, .produces_validation_info
= true, .timeout
= 0 },
86 { .run
= ppoll_concurrent_write
, .produces_validation_info
= false, .timeout
= 0 },
87 { .run
= epoll_pwait_concurrent_munmap
, .produces_validation_info
= true, .timeout
= 0 },
90 struct ppoll_thread_data
{
97 void test_select_big(void)
99 fd_set rfds
, wfds
, exfds
;
109 fd2
= dup2(wait_fd
, BIG_SELECT_FD
);
117 tv
.tv_usec
= timeout
* MSEC_PER_USEC
;
120 ret
= select(fd2
+ 1, &rfds
, &wfds
, &exfds
, &tv
);
122 ret
= select(fd2
+ 1, &rfds
, &wfds
, &exfds
, NULL
);
128 ret
= read(wait_fd
, buf
, BUF_SIZE
);
130 PERROR("[select] read");
134 ret
= close(BIG_SELECT_FD
);
144 void test_pselect(void)
152 FD_SET(wait_fd
, &rfds
);
155 tv
.tv_nsec
= timeout
* MSEC_PER_NSEC
;
158 ret
= pselect(1, &rfds
, NULL
, NULL
, &tv
, NULL
);
160 ret
= pselect(1, &rfds
, NULL
, NULL
, NULL
, NULL
);
166 ret
= read(wait_fd
, buf
, BUF_SIZE
);
168 PERROR("[pselect] read");
174 void test_select(void)
182 FD_SET(wait_fd
, &rfds
);
185 tv
.tv_usec
= timeout
* MSEC_PER_USEC
;
188 ret
= select(1, &rfds
, NULL
, NULL
, &tv
);
190 ret
= select(1, &rfds
, NULL
, NULL
, NULL
);
196 ret
= read(wait_fd
, buf
, BUF_SIZE
);
198 PERROR("[select] read");
206 struct pollfd ufds
[NB_FD
];
210 ufds
[0].fd
= wait_fd
;
211 ufds
[0].events
= POLLIN
|POLLPRI
;
213 ret
= poll(ufds
, 1, timeout
);
217 } else if (ret
> 0) {
218 ret
= read(wait_fd
, buf
, BUF_SIZE
);
220 PERROR("[poll] read");
226 void test_ppoll(void)
228 struct pollfd ufds
[NB_FD
];
233 ufds
[0].fd
= wait_fd
;
234 ufds
[0].events
= POLLIN
|POLLPRI
;
238 ts
.tv_nsec
= timeout
* MSEC_PER_NSEC
;
239 ret
= ppoll(ufds
, 1, &ts
, NULL
);
241 ret
= ppoll(ufds
, 1, NULL
, NULL
);
247 } else if (ret
> 0) {
248 ret
= read(wait_fd
, buf
, BUF_SIZE
);
250 PERROR("[ppoll] read");
256 void test_ppoll_big(FILE *validation_output_file
__attribute__((unused
)))
258 struct pollfd ufds
[MAX_FDS
];
260 int ret
, i
, fds
[MAX_FDS
];
262 for (i
= 0; i
< MAX_FDS
; i
++) {
263 fds
[i
] = dup(wait_fd
);
268 ufds
[i
].events
= POLLIN
|POLLPRI
;
271 ret
= ppoll(ufds
, MAX_FDS
, NULL
, NULL
);
275 } else if (ret
> 0) {
276 ret
= read(wait_fd
, buf
, BUF_SIZE
);
278 PERROR("[ppoll] read");
282 for (i
= 0; i
< MAX_FDS
; i
++) {
293 void test_epoll(FILE *validation_output_file
)
297 struct epoll_event epoll_event
;
299 epollfd
= epoll_create(NB_FD
);
301 PERROR("[epoll] create");
305 ret
= fprintf(validation_output_file
,
306 ", \"epoll_wait_fd\": %i", epollfd
);
308 PERROR("[epoll] Failed to write test validation output");
312 epoll_event
.events
= EPOLLIN
| EPOLLPRI
| EPOLLET
;
313 epoll_event
.data
.fd
= wait_fd
;
314 ret
= epoll_ctl(epollfd
, EPOLL_CTL_ADD
, wait_fd
, &epoll_event
);
316 PERROR("[epoll] add");
321 ret
= epoll_wait(epollfd
, &epoll_event
, 1, timeout
);
323 ret
= epoll_wait(epollfd
, &epoll_event
, 1, -1);
327 ret
= read(wait_fd
, buf
, BUF_SIZE
);
329 PERROR("[epoll] read");
331 } else if (ret
!= 0) {
332 PERROR("epoll_wait");
336 ret
= close(epollfd
);
345 void test_epoll_pwait(FILE *validation_output_file
)
349 struct epoll_event epoll_event
;
351 epollfd
= epoll_create(NB_FD
);
353 PERROR("[epoll_pwait] create");
357 ret
= fprintf(validation_output_file
,
358 ", \"epoll_pwait_fd\": %i", epollfd
);
360 PERROR("[epoll_pwait] Failed to write test validation output");
364 epoll_event
.events
= EPOLLIN
| EPOLLPRI
| EPOLLET
;
365 epoll_event
.data
.fd
= wait_fd
;
366 ret
= epoll_ctl(epollfd
, EPOLL_CTL_ADD
, wait_fd
, &epoll_event
);
368 PERROR("[epoll_pwait] add");
373 ret
= epoll_pwait(epollfd
, &epoll_event
, 1, timeout
, NULL
);
375 ret
= epoll_pwait(epollfd
, &epoll_event
, 1, -1, NULL
);
379 ret
= read(wait_fd
, buf
, BUF_SIZE
);
381 PERROR("[epoll_pwait] read");
383 } else if (ret
!= 0) {
384 PERROR("epoll_pwait");
388 ret
= close(epollfd
);
397 void run_working_cases(FILE *validation_output_file
)
404 * We need an input pipe for some cases and stdin might
405 * have random data, so we create a dummy pipe for this
406 * test to make sure we are running under clean conditions.
408 ret
= pipe(pipe_fds
);
413 wait_fd
= pipe_fds
[0];
421 ret
= fprintf(validation_output_file
, "{ \"pid\": %i", getpid());
423 PERROR("Failed to write pid to test validation file");
427 test_epoll(validation_output_file
);
428 test_epoll_pwait(validation_output_file
);
431 ret
= close(pipe_fds
[0]);
435 ret
= close(pipe_fds
[1]);
441 ret
= fputs(" }", validation_output_file
);
443 PERROR("Failed to close JSON dictionary in test validation file");
452 * Ask for 100 FDs in a buffer for allocated for only 1 FD, should
453 * segfault (eventually with a "*** stack smashing detected ***" message).
454 * The event should contain an array of 100 FDs filled with garbage.
457 void ppoll_fds_buffer_overflow(
458 FILE *validation_output_file
__attribute__((unused
)))
460 struct pollfd ufds
[NB_FD
];
464 ufds
[0].fd
= wait_fd
;
465 ufds
[0].events
= POLLIN
|POLLPRI
;
467 ret
= syscall(SYS_ppoll
, ufds
, 100, NULL
, NULL
);
471 } else if (ret
> 0) {
472 ret
= read(wait_fd
, buf
, BUF_SIZE
);
474 PERROR("[ppoll] read");
480 * Ask for ULONG_MAX FDs in a buffer for allocated for only 1 FD, should
481 * cleanly fail with a "Invalid argument".
482 * The event should contain an empty array of FDs and overflow = 1.
485 void ppoll_fds_ulong_max(FILE *validation_output_file
__attribute__((unused
)))
487 struct pollfd ufds
[NB_FD
];
491 ufds
[0].fd
= wait_fd
;
492 ufds
[0].events
= POLLIN
|POLLPRI
;
494 ret
= syscall(SYS_ppoll
, ufds
, ULONG_MAX
, NULL
, NULL
);
496 /* Expected error. */
497 } else if (ret
> 0) {
498 ret
= read(wait_fd
, buf
, BUF_SIZE
);
500 PERROR("[ppoll] read");
506 * Pass an invalid file descriptor to pselect6(). The syscall should return
507 * -EBADF. The recorded event should contain a "ret = -EBADF (-9)".
510 void pselect_invalid_fd(FILE *validation_output_file
__attribute__((unused
)))
518 * Open a file, close it and use the closed FD in the pselect6 call.
520 fd
= open("/dev/null", O_RDONLY
);
535 ret
= syscall(SYS_pselect6
, fd
+ 1, &rfds
, NULL
, NULL
, NULL
, NULL
);
537 /* Expected error. */
539 ret
= read(wait_fd
, buf
, BUF_SIZE
);
541 PERROR("[pselect] read");
549 * Invalid pointer as writefds, should output a ppoll event
553 void pselect_invalid_pointer(
554 FILE *validation_output_file
__attribute__((unused
)))
559 void *invalid
= (void *) 0x42;
562 FD_SET(wait_fd
, &rfds
);
564 ret
= syscall(SYS_pselect6
, 1, &rfds
, (fd_set
*) invalid
, NULL
, NULL
,
567 /* Expected error. */
569 ret
= read(wait_fd
, buf
, BUF_SIZE
);
571 PERROR("[pselect] read");
577 * Pass an invalid pointer to epoll_pwait, should fail with
578 * "Bad address", the event returns 0 FDs.
581 void epoll_pwait_invalid_pointer(FILE *validation_output_file
)
585 struct epoll_event epoll_event
;
586 void *invalid
= (void *) 0x42;
588 epollfd
= epoll_create(NB_FD
);
590 PERROR("[epoll_pwait] create");
594 ret
= fprintf(validation_output_file
,
595 "{ \"epollfd\": %i, \"pid\": %i }", epollfd
,
598 PERROR("[epoll_pwait] Failed to write test validation output");
602 epoll_event
.events
= EPOLLIN
| EPOLLPRI
| EPOLLET
;
603 epoll_event
.data
.fd
= wait_fd
;
604 ret
= epoll_ctl(epollfd
, EPOLL_CTL_ADD
, wait_fd
, &epoll_event
);
606 PERROR("[epoll_pwait] add");
610 ret
= syscall(SYS_epoll_pwait
, epollfd
,
611 (struct epoll_event
*) invalid
, 1, -1, NULL
);
614 ret
= read(wait_fd
, buf
, BUF_SIZE
);
616 PERROR("[epoll_pwait] read");
618 } else if (ret
!= 0) {
619 /* Expected error. */
623 ret
= close(epollfd
);
632 * Set maxevents to INT_MAX, should output "Invalid argument"
633 * The event should return an empty array.
636 void epoll_pwait_int_max(FILE *validation_output_file
)
640 struct epoll_event epoll_event
;
642 epollfd
= epoll_create(NB_FD
);
644 PERROR("[epoll_pwait] create");
648 ret
= fprintf(validation_output_file
,
649 "{ \"epollfd\": %i, \"pid\": %i }", epollfd
,
652 PERROR("[epoll_pwait] Failed to write test validation output");
656 epoll_event
.events
= EPOLLIN
| EPOLLPRI
| EPOLLET
;
657 epoll_event
.data
.fd
= wait_fd
;
658 ret
= epoll_ctl(epollfd
, EPOLL_CTL_ADD
, wait_fd
, &epoll_event
);
660 PERROR("[epoll_pwait] add");
664 ret
= syscall(SYS_epoll_pwait
, epollfd
, &epoll_event
, INT_MAX
, -1,
668 ret
= read(wait_fd
, buf
, BUF_SIZE
);
670 PERROR("[epoll_pwait] read");
672 } else if (ret
!= 0) {
673 /* Expected error. */
677 ret
= close(epollfd
);
686 void *ppoll_writer(void *arg
)
688 struct ppoll_thread_data
*data
= (struct ppoll_thread_data
*) arg
;
690 while (!stop_thread
) {
691 memset(data
->ufds
, data
->value
,
692 MAX_FDS
* sizeof(struct pollfd
));
700 void do_ppoll(int *fds
, struct pollfd
*ufds
)
707 ts
.tv_nsec
= 1 * MSEC_PER_NSEC
;
709 for (i
= 0; i
< MAX_FDS
; i
++) {
711 ufds
[i
].events
= POLLIN
|POLLPRI
;
714 ret
= ppoll(ufds
, MAX_FDS
, &ts
, NULL
);
718 } else if (ret
> 0) {
719 ret
= read(wait_fd
, buf
, BUF_SIZE
);
721 PERROR("[ppoll] read");
727 void stress_ppoll(int *fds
, int value
)
731 struct ppoll_thread_data thread_data
;
732 struct pollfd ufds
[MAX_FDS
];
734 thread_data
.ufds
= ufds
;
735 thread_data
.value
= value
;
738 ret
= pthread_create(&writer
, NULL
, &ppoll_writer
, (void *) &thread_data
);
740 fprintf(stderr
, "[error] pthread_create\n");
743 for (iter
= 0; iter
< NR_ITER
; iter
++) {
747 ret
= pthread_join(writer
, NULL
);
749 fprintf(stderr
, "[error] pthread_join\n");
757 * 3 rounds of NR_ITER iterations with concurrent updates of the pollfd
761 * - memset to INT_MAX
762 * Waits for input, but also set a timeout in case the input FD is overwritten
763 * before entering in the syscall. We use MAX_FDS FDs (dup of stdin), so the
764 * resulting trace is big (20MB).
766 * ppoll should work as expected and the trace should be readable at the end.
769 void ppoll_concurrent_write(
770 FILE *validation_output_file
__attribute__((unused
)))
772 int i
, ret
, fds
[MAX_FDS
];
774 for (i
= 0; i
< MAX_FDS
; i
++) {
775 fds
[i
] = dup(wait_fd
);
781 stress_ppoll(fds
, 0);
782 stress_ppoll(fds
, 1);
783 stress_ppoll(fds
, INT_MAX
);
785 for (i
= 0; i
< MAX_FDS
; i
++) {
796 void *epoll_pwait_writer(void *addr
)
800 while (!stop_thread
) {
802 munmap(addr
, MAX_FDS
* sizeof(struct epoll_event
));
809 * epoll_pwait on MAX_FDS fds while a concurrent thread munmaps the
810 * buffer allocated for the returned data. This should randomly segfault.
811 * The trace should be readable and no kernel OOPS should occur.
814 void epoll_pwait_concurrent_munmap(FILE *validation_output_file
)
816 int ret
, epollfd
, i
, fds
[MAX_FDS
];
818 struct epoll_event
*epoll_event
;
821 for (i
= 0; i
< MAX_FDS
; i
++) {
824 epollfd
= epoll_create(MAX_FDS
);
826 PERROR("[epoll_pwait] create");
830 ret
= fprintf(validation_output_file
,
831 "{ \"epollfd\": %i, \"pid\": %i }", epollfd
,
834 PERROR("[epoll_pwait] Failed to write test validation output");
838 epoll_event
= (struct epoll_event
*) mmap(NULL
,
839 MAX_FDS
* sizeof(struct epoll_event
),
840 PROT_READ
| PROT_WRITE
, MAP_PRIVATE
| MAP_ANONYMOUS
, -1,
842 if (epoll_event
== MAP_FAILED
) {
847 for (i
= 0; i
< MAX_FDS
; i
++) {
848 fds
[i
] = dup(wait_fd
);
852 epoll_event
[i
].events
= EPOLLIN
| EPOLLPRI
| EPOLLET
;
853 epoll_event
[i
].data
.fd
= fds
[i
];
854 ret
= epoll_ctl(epollfd
, EPOLL_CTL_ADD
, fds
[i
], epoll_event
);
856 PERROR("[epoll_pwait] add");
861 ret
= pthread_create(&writer
, NULL
, &epoll_pwait_writer
,
862 (void *) epoll_event
);
864 fprintf(stderr
, "[error] pthread_create\n");
868 ret
= epoll_pwait(epollfd
, epoll_event
, 1, 1, NULL
);
871 ret
= read(wait_fd
, buf
, BUF_SIZE
);
873 PERROR("[epoll_pwait] read");
875 } else if (ret
!= 0) {
876 /* Expected error. */
880 ret
= pthread_join(writer
, NULL
);
882 fprintf(stderr
, "[error] pthread_join\n");
886 for (i
= 0; i
< MAX_FDS
; i
++) {
893 ret
= munmap(epoll_event
, MAX_FDS
* sizeof(struct epoll_event
));
899 ret
= close(epollfd
);
908 void print_list(void)
910 fprintf(stderr
, "Test list (-t X):\n");
911 fprintf(stderr
, "\t1: Working cases for select, pselect6, poll, ppoll "
912 "and epoll, waiting for input\n");
913 fprintf(stderr
, "\t2: Timeout cases (1ms) for select, pselect6, poll, "
914 "ppoll and epoll\n");
915 fprintf(stderr
, "\t3: pselect with an invalid fd\n");
916 fprintf(stderr
, "\t4: ppoll with %d FDs\n", MAX_FDS
);
917 fprintf(stderr
, "\t5: ppoll buffer overflow, should segfault, waits "
919 fprintf(stderr
, "\t6: pselect with an invalid pointer, waits for "
921 fprintf(stderr
, "\t7: ppoll with ulong_max fds, waits for input\n");
922 fprintf(stderr
, "\t8: epoll_pwait with an invalid pointer, waits for "
924 fprintf(stderr
, "\t9: epoll_pwait with maxevents set to INT_MAX, "
925 "waits for input\n");
926 fprintf(stderr
, "\t10: ppoll with concurrent updates of the structure "
927 "from user-space, stress test (3000 iterations), "
928 "waits for input + timeout 1ms\n");
929 fprintf(stderr
, "\t11: epoll_pwait with concurrent munmap of the buffer "
930 "from user-space, should randomly segfault, run "
931 "multiple times, waits for input + timeout 1ms\n");
934 int main(int argc
, const char **argv
)
936 int c
, ret
, test
= -1;
938 struct rlimit open_lim
;
939 FILE *test_validation_output_file
= NULL
;
940 const char *test_validation_output_file_path
= NULL
;
941 struct poptOption optionsTable
[] = {
942 { "test", 't', POPT_ARG_INT
, &test
, 0,
943 "Test to run", NULL
},
944 { "list", 'l', 0, 0, 'l',
945 "List of tests (-t X)", NULL
},
946 { "validation-file", 'o', POPT_ARG_STRING
, &test_validation_output_file_path
, 0,
947 "Test case output", NULL
},
949 { NULL
, 0, 0, NULL
, 0, NULL
, NULL
}
951 const struct test_case
*test_case
;
953 optCon
= poptGetContext(NULL
, argc
, argv
, optionsTable
, 0);
956 poptPrintUsage(optCon
, stderr
, 0);
963 while ((c
= poptGetNextOpt(optCon
)) >= 0) {
971 if (!test_validation_output_file_path
) {
972 fprintf(stderr
, "A test validation file path is required (--validation-file/-o)\n");
977 test_validation_output_file
= fopen(test_validation_output_file_path
, "w+");
978 if (!test_validation_output_file
) {
979 PERROR("Failed to create test validation output file at '%s'",
980 test_validation_output_file_path
);
985 open_lim
.rlim_cur
= MAX_FDS
+ MIN_NR_FDS
;
986 open_lim
.rlim_max
= MAX_FDS
+ MIN_NR_FDS
;
988 ret
= setrlimit(RLIMIT_NOFILE
, &open_lim
);
995 * Some tests might segfault, but we need the getpid() to be output
996 * for the validation, disabling the buffering on the validation file
999 setbuf(test_validation_output_file
, NULL
);
1000 wait_fd
= STDIN_FILENO
;
1002 /* Test case id is 1-based. */
1003 if (test
< 1 || test
> ARRAY_SIZE(test_cases
)) {
1004 poptPrintUsage(optCon
, stderr
, 0);
1008 test_case
= &test_cases
[test
- 1];
1010 timeout
= test_case
->timeout
;
1011 if (!test_case
->produces_validation_info
) {
1013 * All test cases need to provide, at minimum, the pid of the
1016 ret
= fprintf(test_validation_output_file
, "{ \"pid\": %i }", getpid());
1018 PERROR("Failed to write application pid to test validation file");
1023 test_case
->run(test_validation_output_file
);
1026 if (test_validation_output_file
) {
1027 const int close_ret
= fclose(test_validation_output_file
);
1030 PERROR("Failed to close test output file");
1033 poptFreeContext(optCon
);