2 * Copyright (C) 2016 Julien Desfossez <jdesfossez@efficios.com>
4 * SPDX-License-Identifier: GPL-2.0-only
18 #include <sys/epoll.h>
20 #include <sys/resource.h>
21 #include <sys/select.h>
23 #include <sys/syscall.h>
25 #include <sys/types.h>
28 #include <common/compat/time.hpp>
29 #include <common/error.hpp>
34 #define NR_ITER 1000 /* for stress-tests */
36 #define MIN_NR_FDS 5 /* the minimum number of open FDs required for the test to run */
37 #define BIG_SELECT_FD 1022
39 #define MSEC_PER_USEC 1000
40 #define MSEC_PER_NSEC (MSEC_PER_USEC * 1000)
42 static int timeout
; /* seconds, -1 to disable */
43 static volatile int stop_thread
;
46 /* Used by logging utils. */
47 int lttng_opt_quiet
, lttng_opt_verbose
, lttng_opt_mi
;
49 static void run_working_cases(FILE *validation_output_file
);
50 static void pselect_invalid_fd(FILE *validation_output_file
);
51 static void test_ppoll_big(FILE *validation_output_file
);
52 static void ppoll_fds_buffer_overflow(FILE *validation_output_file
);
53 static void pselect_invalid_pointer(FILE *validation_output_file
);
54 static void ppoll_fds_ulong_max(FILE *validation_output_file
);
55 static void epoll_pwait_invalid_pointer(FILE *validation_output_file
);
56 static void epoll_pwait_int_max(FILE *validation_output_file
);
57 static void ppoll_concurrent_write(FILE *validation_output_file
);
58 static void epoll_pwait_concurrent_munmap(FILE *validation_output_file
);
60 typedef void (*test_case_cb
)(FILE *output_file
);
63 const struct test_case
{
65 bool produces_validation_info
;
69 { .run
= run_working_cases
, .produces_validation_info
= true, .timeout
= -1 },
70 { .run
= run_working_cases
, .produces_validation_info
= true, .timeout
= 1 },
71 { .run
= pselect_invalid_fd
, .produces_validation_info
= false, .timeout
= 0 },
72 { .run
= test_ppoll_big
, .produces_validation_info
= false, .timeout
= 0 },
73 { .run
= ppoll_fds_buffer_overflow
, .produces_validation_info
= false, .timeout
= 0 },
74 { .run
= pselect_invalid_pointer
, .produces_validation_info
= false, .timeout
= 0 },
75 { .run
= ppoll_fds_ulong_max
, .produces_validation_info
= false, .timeout
= 0 },
76 { .run
= epoll_pwait_invalid_pointer
, .produces_validation_info
= true, .timeout
= 0 },
77 { .run
= epoll_pwait_int_max
, .produces_validation_info
= true, .timeout
= 0 },
78 { .run
= ppoll_concurrent_write
, .produces_validation_info
= false, .timeout
= 0 },
79 { .run
= epoll_pwait_concurrent_munmap
, .produces_validation_info
= true, .timeout
= 0 },
82 struct ppoll_thread_data
{
89 void test_select_big(void)
91 fd_set rfds
, wfds
, exfds
;
101 fd2
= dup2(wait_fd
, BIG_SELECT_FD
);
109 tv
.tv_usec
= timeout
* MSEC_PER_USEC
;
112 ret
= select(fd2
+ 1, &rfds
, &wfds
, &exfds
, &tv
);
114 ret
= select(fd2
+ 1, &rfds
, &wfds
, &exfds
, NULL
);
120 ret
= read(wait_fd
, buf
, BUF_SIZE
);
122 PERROR("[select] read");
126 ret
= close(BIG_SELECT_FD
);
136 void test_pselect(void)
144 FD_SET(wait_fd
, &rfds
);
147 tv
.tv_nsec
= timeout
* MSEC_PER_NSEC
;
150 ret
= pselect(1, &rfds
, NULL
, NULL
, &tv
, NULL
);
152 ret
= pselect(1, &rfds
, NULL
, NULL
, NULL
, NULL
);
158 ret
= read(wait_fd
, buf
, BUF_SIZE
);
160 PERROR("[pselect] read");
166 void test_select(void)
174 FD_SET(wait_fd
, &rfds
);
177 tv
.tv_usec
= timeout
* MSEC_PER_USEC
;
180 ret
= select(1, &rfds
, NULL
, NULL
, &tv
);
182 ret
= select(1, &rfds
, NULL
, NULL
, NULL
);
188 ret
= read(wait_fd
, buf
, BUF_SIZE
);
190 PERROR("[select] read");
198 struct pollfd ufds
[NB_FD
];
202 ufds
[0].fd
= wait_fd
;
203 ufds
[0].events
= POLLIN
|POLLPRI
;
205 ret
= poll(ufds
, 1, timeout
);
209 } else if (ret
> 0) {
210 ret
= read(wait_fd
, buf
, BUF_SIZE
);
212 PERROR("[poll] read");
218 void test_ppoll(void)
220 struct pollfd ufds
[NB_FD
];
225 ufds
[0].fd
= wait_fd
;
226 ufds
[0].events
= POLLIN
|POLLPRI
;
230 ts
.tv_nsec
= timeout
* MSEC_PER_NSEC
;
231 ret
= ppoll(ufds
, 1, &ts
, NULL
);
233 ret
= ppoll(ufds
, 1, NULL
, NULL
);
239 } else if (ret
> 0) {
240 ret
= read(wait_fd
, buf
, BUF_SIZE
);
242 PERROR("[ppoll] read");
248 void test_ppoll_big(FILE *validation_output_file
__attribute__((unused
)))
250 struct pollfd ufds
[MAX_FDS
];
252 int ret
, i
, fds
[MAX_FDS
];
254 for (i
= 0; i
< MAX_FDS
; i
++) {
255 fds
[i
] = dup(wait_fd
);
260 ufds
[i
].events
= POLLIN
|POLLPRI
;
263 ret
= ppoll(ufds
, MAX_FDS
, NULL
, NULL
);
267 } else if (ret
> 0) {
268 ret
= read(wait_fd
, buf
, BUF_SIZE
);
270 PERROR("[ppoll] read");
274 for (i
= 0; i
< MAX_FDS
; i
++) {
285 void test_epoll(FILE *validation_output_file
)
289 struct epoll_event epoll_event
;
291 epollfd
= epoll_create(NB_FD
);
293 PERROR("[epoll] create");
297 ret
= fprintf(validation_output_file
,
298 ", \"epoll_wait_fd\": %i", epollfd
);
300 PERROR("[epoll] Failed to write test validation output");
304 epoll_event
.events
= EPOLLIN
| EPOLLPRI
| EPOLLET
;
305 epoll_event
.data
.fd
= wait_fd
;
306 ret
= epoll_ctl(epollfd
, EPOLL_CTL_ADD
, wait_fd
, &epoll_event
);
308 PERROR("[epoll] add");
313 ret
= epoll_wait(epollfd
, &epoll_event
, 1, timeout
);
315 ret
= epoll_wait(epollfd
, &epoll_event
, 1, -1);
319 ret
= read(wait_fd
, buf
, BUF_SIZE
);
321 PERROR("[epoll] read");
323 } else if (ret
!= 0) {
324 PERROR("epoll_wait");
328 ret
= close(epollfd
);
337 void test_epoll_pwait(FILE *validation_output_file
)
341 struct epoll_event epoll_event
;
343 epollfd
= epoll_create(NB_FD
);
345 PERROR("[epoll_pwait] create");
349 ret
= fprintf(validation_output_file
,
350 ", \"epoll_pwait_fd\": %i", epollfd
);
352 PERROR("[epoll_pwait] Failed to write test validation output");
356 epoll_event
.events
= EPOLLIN
| EPOLLPRI
| EPOLLET
;
357 epoll_event
.data
.fd
= wait_fd
;
358 ret
= epoll_ctl(epollfd
, EPOLL_CTL_ADD
, wait_fd
, &epoll_event
);
360 PERROR("[epoll_pwait] add");
365 ret
= epoll_pwait(epollfd
, &epoll_event
, 1, timeout
, NULL
);
367 ret
= epoll_pwait(epollfd
, &epoll_event
, 1, -1, NULL
);
371 ret
= read(wait_fd
, buf
, BUF_SIZE
);
373 PERROR("[epoll_pwait] read");
375 } else if (ret
!= 0) {
376 PERROR("epoll_pwait");
380 ret
= close(epollfd
);
389 void run_working_cases(FILE *validation_output_file
)
396 * We need an input pipe for some cases and stdin might
397 * have random data, so we create a dummy pipe for this
398 * test to make sure we are running under clean conditions.
400 ret
= pipe(pipe_fds
);
405 wait_fd
= pipe_fds
[0];
413 ret
= fprintf(validation_output_file
, "{ \"pid\": %i", getpid());
415 PERROR("Failed to write pid to test validation file");
419 test_epoll(validation_output_file
);
420 test_epoll_pwait(validation_output_file
);
423 ret
= close(pipe_fds
[0]);
427 ret
= close(pipe_fds
[1]);
433 ret
= fputs(" }", validation_output_file
);
435 PERROR("Failed to close JSON dictionary in test validation file");
444 * Ask for 100 FDs in a buffer for allocated for only 1 FD, should
445 * segfault (eventually with a "*** stack smashing detected ***" message).
446 * The event should contain an array of 100 FDs filled with garbage.
449 void ppoll_fds_buffer_overflow(
450 FILE *validation_output_file
__attribute__((unused
)))
452 struct pollfd ufds
[NB_FD
];
456 ufds
[0].fd
= wait_fd
;
457 ufds
[0].events
= POLLIN
|POLLPRI
;
459 ret
= syscall(SYS_ppoll
, ufds
, 100, NULL
, NULL
);
463 } else if (ret
> 0) {
464 ret
= read(wait_fd
, buf
, BUF_SIZE
);
466 PERROR("[ppoll] read");
472 * Ask for ULONG_MAX FDs in a buffer for allocated for only 1 FD, should
473 * cleanly fail with a "Invalid argument".
474 * The event should contain an empty array of FDs and overflow = 1.
477 void ppoll_fds_ulong_max(FILE *validation_output_file
__attribute__((unused
)))
479 struct pollfd ufds
[NB_FD
];
483 ufds
[0].fd
= wait_fd
;
484 ufds
[0].events
= POLLIN
|POLLPRI
;
486 ret
= syscall(SYS_ppoll
, ufds
, ULONG_MAX
, NULL
, NULL
);
488 /* Expected error. */
489 } else if (ret
> 0) {
490 ret
= read(wait_fd
, buf
, BUF_SIZE
);
492 PERROR("[ppoll] read");
498 * Pass an invalid file descriptor to pselect6(). The syscall should return
499 * -EBADF. The recorded event should contain a "ret = -EBADF (-9)".
502 void pselect_invalid_fd(FILE *validation_output_file
__attribute__((unused
)))
510 * Open a file, close it and use the closed FD in the pselect6 call.
512 fd
= open("/dev/null", O_RDONLY
);
527 ret
= syscall(SYS_pselect6
, fd
+ 1, &rfds
, NULL
, NULL
, NULL
, NULL
);
529 /* Expected error. */
531 ret
= read(wait_fd
, buf
, BUF_SIZE
);
533 PERROR("[pselect] read");
541 * Invalid pointer as writefds, should output a ppoll event
545 void pselect_invalid_pointer(
546 FILE *validation_output_file
__attribute__((unused
)))
551 void *invalid
= (void *) 0x42;
554 FD_SET(wait_fd
, &rfds
);
556 ret
= syscall(SYS_pselect6
, 1, &rfds
, (fd_set
*) invalid
, NULL
, NULL
,
559 /* Expected error. */
561 ret
= read(wait_fd
, buf
, BUF_SIZE
);
563 PERROR("[pselect] read");
569 * Pass an invalid pointer to epoll_pwait, should fail with
570 * "Bad address", the event returns 0 FDs.
573 void epoll_pwait_invalid_pointer(FILE *validation_output_file
)
577 struct epoll_event epoll_event
;
578 void *invalid
= (void *) 0x42;
580 epollfd
= epoll_create(NB_FD
);
582 PERROR("[epoll_pwait] create");
586 ret
= fprintf(validation_output_file
,
587 "{ \"epollfd\": %i, \"pid\": %i }", epollfd
,
590 PERROR("[epoll_pwait] Failed to write test validation output");
594 epoll_event
.events
= EPOLLIN
| EPOLLPRI
| EPOLLET
;
595 epoll_event
.data
.fd
= wait_fd
;
596 ret
= epoll_ctl(epollfd
, EPOLL_CTL_ADD
, wait_fd
, &epoll_event
);
598 PERROR("[epoll_pwait] add");
602 ret
= syscall(SYS_epoll_pwait
, epollfd
,
603 (struct epoll_event
*) invalid
, 1, -1, NULL
);
606 ret
= read(wait_fd
, buf
, BUF_SIZE
);
608 PERROR("[epoll_pwait] read");
610 } else if (ret
!= 0) {
611 /* Expected error. */
615 ret
= close(epollfd
);
624 * Set maxevents to INT_MAX, should output "Invalid argument"
625 * The event should return an empty array.
628 void epoll_pwait_int_max(FILE *validation_output_file
)
632 struct epoll_event epoll_event
;
634 epollfd
= epoll_create(NB_FD
);
636 PERROR("[epoll_pwait] create");
640 ret
= fprintf(validation_output_file
,
641 "{ \"epollfd\": %i, \"pid\": %i }", epollfd
,
644 PERROR("[epoll_pwait] Failed to write test validation output");
648 epoll_event
.events
= EPOLLIN
| EPOLLPRI
| EPOLLET
;
649 epoll_event
.data
.fd
= wait_fd
;
650 ret
= epoll_ctl(epollfd
, EPOLL_CTL_ADD
, wait_fd
, &epoll_event
);
652 PERROR("[epoll_pwait] add");
656 ret
= syscall(SYS_epoll_pwait
, epollfd
, &epoll_event
, INT_MAX
, -1,
660 ret
= read(wait_fd
, buf
, BUF_SIZE
);
662 PERROR("[epoll_pwait] read");
664 } else if (ret
!= 0) {
665 /* Expected error. */
669 ret
= close(epollfd
);
678 void *ppoll_writer(void *arg
)
680 struct ppoll_thread_data
*data
= (struct ppoll_thread_data
*) arg
;
682 while (!stop_thread
) {
683 memset(data
->ufds
, data
->value
,
684 MAX_FDS
* sizeof(struct pollfd
));
692 void do_ppoll(int *fds
, struct pollfd
*ufds
)
699 ts
.tv_nsec
= 1 * MSEC_PER_NSEC
;
701 for (i
= 0; i
< MAX_FDS
; i
++) {
703 ufds
[i
].events
= POLLIN
|POLLPRI
;
706 ret
= ppoll(ufds
, MAX_FDS
, &ts
, NULL
);
710 } else if (ret
> 0) {
711 ret
= read(wait_fd
, buf
, BUF_SIZE
);
713 PERROR("[ppoll] read");
719 void stress_ppoll(int *fds
, int value
)
723 struct ppoll_thread_data thread_data
;
724 struct pollfd ufds
[MAX_FDS
];
726 thread_data
.ufds
= ufds
;
727 thread_data
.value
= value
;
730 ret
= pthread_create(&writer
, NULL
, &ppoll_writer
, (void *) &thread_data
);
732 fprintf(stderr
, "[error] pthread_create\n");
735 for (iter
= 0; iter
< NR_ITER
; iter
++) {
739 ret
= pthread_join(writer
, NULL
);
741 fprintf(stderr
, "[error] pthread_join\n");
749 * 3 rounds of NR_ITER iterations with concurrent updates of the pollfd
753 * - memset to INT_MAX
754 * Waits for input, but also set a timeout in case the input FD is overwritten
755 * before entering in the syscall. We use MAX_FDS FDs (dup of stdin), so the
756 * resulting trace is big (20MB).
758 * ppoll should work as expected and the trace should be readable at the end.
761 void ppoll_concurrent_write(
762 FILE *validation_output_file
__attribute__((unused
)))
764 int i
, ret
, fds
[MAX_FDS
];
766 for (i
= 0; i
< MAX_FDS
; i
++) {
767 fds
[i
] = dup(wait_fd
);
773 stress_ppoll(fds
, 0);
774 stress_ppoll(fds
, 1);
775 stress_ppoll(fds
, INT_MAX
);
777 for (i
= 0; i
< MAX_FDS
; i
++) {
788 void *epoll_pwait_writer(void *addr
)
792 while (!stop_thread
) {
794 munmap(addr
, MAX_FDS
* sizeof(struct epoll_event
));
801 * epoll_pwait on MAX_FDS fds while a concurrent thread munmaps the
802 * buffer allocated for the returned data. This should randomly segfault.
803 * The trace should be readable and no kernel OOPS should occur.
806 void epoll_pwait_concurrent_munmap(FILE *validation_output_file
)
808 int ret
, epollfd
, i
, fds
[MAX_FDS
];
810 struct epoll_event
*epoll_event
;
813 for (i
= 0; i
< MAX_FDS
; i
++) {
816 epollfd
= epoll_create(MAX_FDS
);
818 PERROR("[epoll_pwait] create");
822 ret
= fprintf(validation_output_file
,
823 "{ \"epollfd\": %i, \"pid\": %i }", epollfd
,
826 PERROR("[epoll_pwait] Failed to write test validation output");
830 epoll_event
= (struct epoll_event
*) mmap(NULL
,
831 MAX_FDS
* sizeof(struct epoll_event
),
832 PROT_READ
| PROT_WRITE
, MAP_PRIVATE
| MAP_ANONYMOUS
, -1,
834 if (epoll_event
== MAP_FAILED
) {
839 for (i
= 0; i
< MAX_FDS
; i
++) {
840 fds
[i
] = dup(wait_fd
);
844 epoll_event
[i
].events
= EPOLLIN
| EPOLLPRI
| EPOLLET
;
845 epoll_event
[i
].data
.fd
= fds
[i
];
846 ret
= epoll_ctl(epollfd
, EPOLL_CTL_ADD
, fds
[i
], epoll_event
);
848 PERROR("[epoll_pwait] add");
853 ret
= pthread_create(&writer
, NULL
, &epoll_pwait_writer
,
854 (void *) epoll_event
);
856 fprintf(stderr
, "[error] pthread_create\n");
860 ret
= epoll_pwait(epollfd
, epoll_event
, 1, 1, NULL
);
863 ret
= read(wait_fd
, buf
, BUF_SIZE
);
865 PERROR("[epoll_pwait] read");
867 } else if (ret
!= 0) {
868 /* Expected error. */
872 ret
= pthread_join(writer
, NULL
);
874 fprintf(stderr
, "[error] pthread_join\n");
878 for (i
= 0; i
< MAX_FDS
; i
++) {
885 ret
= munmap(epoll_event
, MAX_FDS
* sizeof(struct epoll_event
));
891 ret
= close(epollfd
);
900 void print_list(void)
902 fprintf(stderr
, "Test list (-t X):\n");
903 fprintf(stderr
, "\t1: Working cases for select, pselect6, poll, ppoll "
904 "and epoll, waiting for input\n");
905 fprintf(stderr
, "\t2: Timeout cases (1ms) for select, pselect6, poll, "
906 "ppoll and epoll\n");
907 fprintf(stderr
, "\t3: pselect with an invalid fd\n");
908 fprintf(stderr
, "\t4: ppoll with %d FDs\n", MAX_FDS
);
909 fprintf(stderr
, "\t5: ppoll buffer overflow, should segfault, waits "
911 fprintf(stderr
, "\t6: pselect with an invalid pointer, waits for "
913 fprintf(stderr
, "\t7: ppoll with ulong_max fds, waits for input\n");
914 fprintf(stderr
, "\t8: epoll_pwait with an invalid pointer, waits for "
916 fprintf(stderr
, "\t9: epoll_pwait with maxevents set to INT_MAX, "
917 "waits for input\n");
918 fprintf(stderr
, "\t10: ppoll with concurrent updates of the structure "
919 "from user-space, stress test (3000 iterations), "
920 "waits for input + timeout 1ms\n");
921 fprintf(stderr
, "\t11: epoll_pwait with concurrent munmap of the buffer "
922 "from user-space, should randomly segfault, run "
923 "multiple times, waits for input + timeout 1ms\n");
926 int main(int argc
, const char **argv
)
928 int c
, ret
, test
= -1;
930 struct rlimit open_lim
;
931 FILE *test_validation_output_file
= NULL
;
932 const char *test_validation_output_file_path
= NULL
;
933 struct poptOption optionsTable
[] = {
934 { "test", 't', POPT_ARG_INT
, &test
, 0,
935 "Test to run", NULL
},
936 { "list", 'l', 0, 0, 'l',
937 "List of tests (-t X)", NULL
},
938 { "validation-file", 'o', POPT_ARG_STRING
, &test_validation_output_file_path
, 0,
939 "Test case output", NULL
},
941 { NULL
, 0, 0, NULL
, 0, NULL
, NULL
}
943 const struct test_case
*test_case
;
945 optCon
= poptGetContext(NULL
, argc
, argv
, optionsTable
, 0);
948 poptPrintUsage(optCon
, stderr
, 0);
955 while ((c
= poptGetNextOpt(optCon
)) >= 0) {
963 if (!test_validation_output_file_path
) {
964 fprintf(stderr
, "A test validation file path is required (--validation-file/-o)\n");
969 test_validation_output_file
= fopen(test_validation_output_file_path
, "w+");
970 if (!test_validation_output_file
) {
971 PERROR("Failed to create test validation output file at '%s'",
972 test_validation_output_file_path
);
977 open_lim
.rlim_cur
= MAX_FDS
+ MIN_NR_FDS
;
978 open_lim
.rlim_max
= MAX_FDS
+ MIN_NR_FDS
;
980 ret
= setrlimit(RLIMIT_NOFILE
, &open_lim
);
987 * Some tests might segfault, but we need the getpid() to be output
988 * for the validation, disabling the buffering on the validation file
991 setbuf(test_validation_output_file
, NULL
);
992 wait_fd
= STDIN_FILENO
;
994 /* Test case id is 1-based. */
995 if (test
< 1 || test
> ARRAY_SIZE(test_cases
)) {
996 poptPrintUsage(optCon
, stderr
, 0);
1000 test_case
= &test_cases
[test
- 1];
1002 timeout
= test_case
->timeout
;
1003 if (!test_case
->produces_validation_info
) {
1005 * All test cases need to provide, at minimum, the pid of the
1008 ret
= fprintf(test_validation_output_file
, "{ \"pid\": %i }", getpid());
1010 PERROR("Failed to write application pid to test validation file");
1015 test_case
->run(test_validation_output_file
);
1018 if (test_validation_output_file
) {
1019 const int close_ret
= fclose(test_validation_output_file
);
1022 PERROR("Failed to close test output file");
1025 poptFreeContext(optCon
);