2 * Copyright (C) 2016 Julien Desfossez <jdesfossez@efficios.com>
4 * SPDX-License-Identifier: GPL-2.0-only
12 #include <sys/syscall.h>
13 #include <sys/types.h>
19 #include <sys/select.h>
20 #include <sys/epoll.h>
23 #include <sys/resource.h>
27 #include <common/compat/time.h>
32 #define NR_ITER 1000 /* for stress-tests */
34 #define MIN_NR_FDS 5 /* the minimum number of open FDs required for the test to run */
35 #define BIG_SELECT_FD 1022
37 #define MSEC_PER_USEC 1000
38 #define MSEC_PER_NSEC (MSEC_PER_USEC * 1000)
40 static int timeout
; /* seconds, -1 to disable */
41 static volatile int stop_thread
;
44 struct ppoll_thread_data
{
50 void test_select_big(void)
52 fd_set rfds
, wfds
, exfds
;
62 fd2
= dup2(wait_fd
, BIG_SELECT_FD
);
70 tv
.tv_usec
= timeout
* MSEC_PER_USEC
;
73 ret
= select(fd2
+ 1, &rfds
, &wfds
, &exfds
, &tv
);
75 ret
= select(fd2
+ 1, &rfds
, &wfds
, &exfds
, NULL
);
81 printf("# [select] data available\n");
82 ret
= read(wait_fd
, buf
, BUF_SIZE
);
84 perror("[select] read");
87 printf("# [select] timeout\n");
90 ret
= close(BIG_SELECT_FD
);
100 void test_pselect(void)
108 FD_SET(wait_fd
, &rfds
);
111 tv
.tv_nsec
= timeout
* MSEC_PER_NSEC
;
114 ret
= pselect(1, &rfds
, NULL
, NULL
, &tv
, NULL
);
116 ret
= pselect(1, &rfds
, NULL
, NULL
, NULL
, NULL
);
122 printf("# [pselect] data available\n");
123 ret
= read(wait_fd
, buf
, BUF_SIZE
);
125 perror("[pselect] read");
128 printf("# [pselect] timeout\n");
134 void test_select(void)
142 FD_SET(wait_fd
, &rfds
);
145 tv
.tv_usec
= timeout
* MSEC_PER_USEC
;
148 ret
= select(1, &rfds
, NULL
, NULL
, &tv
);
150 ret
= select(1, &rfds
, NULL
, NULL
, NULL
);
156 printf("# [select] data available\n");
157 ret
= read(wait_fd
, buf
, BUF_SIZE
);
159 perror("[select] read");
162 printf("# [select] timeout\n");
170 struct pollfd ufds
[NB_FD
];
174 ufds
[0].fd
= wait_fd
;
175 ufds
[0].events
= POLLIN
|POLLPRI
;
177 ret
= poll(ufds
, 1, timeout
);
181 } else if (ret
> 0) {
182 printf("# [poll] data available\n");
183 ret
= read(wait_fd
, buf
, BUF_SIZE
);
185 perror("[poll] read");
188 printf("# [poll] timeout\n");
193 void test_ppoll(void)
195 struct pollfd ufds
[NB_FD
];
200 ufds
[0].fd
= wait_fd
;
201 ufds
[0].events
= POLLIN
|POLLPRI
;
205 ts
.tv_nsec
= timeout
* MSEC_PER_NSEC
;
206 ret
= ppoll(ufds
, 1, &ts
, NULL
);
208 ret
= ppoll(ufds
, 1, NULL
, NULL
);
214 } else if (ret
> 0) {
215 printf("# [ppoll] data available\n");
216 ret
= read(wait_fd
, buf
, BUF_SIZE
);
218 perror("[ppoll] read");
221 printf("# [ppoll] timeout\n");
226 void test_ppoll_big(void)
228 struct pollfd ufds
[MAX_FDS
];
230 int ret
, i
, fds
[MAX_FDS
];
232 for (i
= 0; i
< MAX_FDS
; i
++) {
233 fds
[i
] = dup(wait_fd
);
238 ufds
[i
].events
= POLLIN
|POLLPRI
;
241 ret
= ppoll(ufds
, MAX_FDS
, NULL
, NULL
);
245 } else if (ret
> 0) {
246 printf("# [ppoll] data available\n");
247 ret
= read(wait_fd
, buf
, BUF_SIZE
);
249 perror("[ppoll] read");
252 printf("# [ppoll] timeout\n");
255 for (i
= 0; i
< MAX_FDS
; i
++) {
266 void test_epoll(void)
270 struct epoll_event epoll_event
;
272 epollfd
= epoll_create(NB_FD
);
274 perror("[epoll] create");
278 epoll_event
.events
= EPOLLIN
| EPOLLPRI
| EPOLLET
;
279 epoll_event
.data
.fd
= wait_fd
;
280 ret
= epoll_ctl(epollfd
, EPOLL_CTL_ADD
, wait_fd
, &epoll_event
);
282 perror("[epoll] add");
287 ret
= epoll_wait(epollfd
, &epoll_event
, 1, timeout
);
289 ret
= epoll_wait(epollfd
, &epoll_event
, 1, -1);
293 printf("# [epoll] data available\n");
294 ret
= read(wait_fd
, buf
, BUF_SIZE
);
296 perror("[epoll] read");
298 } else if (ret
== 0) {
299 printf("# [epoll] timeout\n");
301 perror("epoll_wait");
311 void test_pepoll(void)
315 struct epoll_event epoll_event
;
317 epollfd
= epoll_create(NB_FD
);
319 perror("[eppoll] create");
323 epoll_event
.events
= EPOLLIN
| EPOLLPRI
| EPOLLET
;
324 epoll_event
.data
.fd
= wait_fd
;
325 ret
= epoll_ctl(epollfd
, EPOLL_CTL_ADD
, wait_fd
, &epoll_event
);
327 perror("[eppoll] add");
332 ret
= epoll_pwait(epollfd
, &epoll_event
, 1, timeout
, NULL
);
334 ret
= epoll_pwait(epollfd
, &epoll_event
, 1, -1, NULL
);
338 printf("# [eppoll] data available\n");
339 ret
= read(wait_fd
, buf
, BUF_SIZE
);
341 perror("[eppoll] read");
343 } else if (ret
== 0) {
344 printf("# [eppoll] timeout\n");
346 perror("epoll_pwait");
356 void run_working_cases(void)
363 * We need an input pipe for some cases and stdin might
364 * have random data, so we create a dummy pipe for this
365 * test to make sure we are running under clean conditions.
367 ret
= pipe(pipe_fds
);
372 wait_fd
= pipe_fds
[0];
383 ret
= close(pipe_fds
[0]);
387 ret
= close(pipe_fds
[1]);
398 * Ask for 100 FDs in a buffer for allocated for only 1 FD, should
399 * segfault (eventually with a "*** stack smashing detected ***" message).
400 * The event should contain an array of 100 FDs filled with garbage.
403 void ppoll_fds_buffer_overflow(void)
405 struct pollfd ufds
[NB_FD
];
409 ufds
[0].fd
= wait_fd
;
410 ufds
[0].events
= POLLIN
|POLLPRI
;
412 ret
= syscall(SYS_ppoll
, ufds
, 100, NULL
, NULL
);
416 } else if (ret
> 0) {
417 printf("# [ppoll] data available\n");
418 ret
= read(wait_fd
, buf
, BUF_SIZE
);
420 perror("[ppoll] read");
423 printf("# [ppoll] timeout\n");
430 * Ask for ULONG_MAX FDs in a buffer for allocated for only 1 FD, should
431 * cleanly fail with a "Invalid argument".
432 * The event should contain an empty array of FDs and overflow = 1.
435 void ppoll_fds_ulong_max(void)
437 struct pollfd ufds
[NB_FD
];
441 ufds
[0].fd
= wait_fd
;
442 ufds
[0].events
= POLLIN
|POLLPRI
;
444 ret
= syscall(SYS_ppoll
, ufds
, ULONG_MAX
, NULL
, NULL
);
448 } else if (ret
> 0) {
449 printf("# [ppoll] data available\n");
450 ret
= read(wait_fd
, buf
, BUF_SIZE
);
452 perror("[ppoll] read");
455 printf("# [ppoll] timeout\n");
462 * Pass an invalid file descriptor to pselect6(). The syscall should return
463 * -EBADF. The recorded event should contain a "ret = -EBADF (-9)".
466 void pselect_invalid_fd(void)
474 * Open a file, close it and use the closed FD in the pselect6 call.
477 fd
= open("/dev/null", O_RDONLY
);
492 ret
= syscall(SYS_pselect6
, fd
+ 1, &rfds
, NULL
, NULL
, NULL
, NULL
);
494 perror("# pselect()");
496 printf("# [pselect] data available\n");
497 ret
= read(wait_fd
, buf
, BUF_SIZE
);
499 perror("[pselect] read");
502 printf("# [pselect] timeout\n");
509 * Invalid pointer as writefds, should output a ppoll event
513 void pselect_invalid_pointer(void)
518 void *invalid
= (void *) 0x42;
521 FD_SET(wait_fd
, &rfds
);
523 ret
= syscall(SYS_pselect6
, 1, &rfds
, (fd_set
*) invalid
, NULL
, NULL
,
527 perror("# pselect()");
529 printf("# [pselect] data available\n");
530 ret
= read(wait_fd
, buf
, BUF_SIZE
);
532 perror("[pselect] read");
535 printf("# [pselect] timeout\n");
541 * Pass an invalid pointer to epoll_pwait, should fail with
542 * "Bad address", the event returns 0 FDs.
545 void epoll_pwait_invalid_pointer(void)
549 struct epoll_event epoll_event
;
550 void *invalid
= (void *) 0x42;
552 epollfd
= epoll_create(NB_FD
);
554 perror("[eppoll] create");
558 epoll_event
.events
= EPOLLIN
| EPOLLPRI
| EPOLLET
;
559 epoll_event
.data
.fd
= wait_fd
;
560 ret
= epoll_ctl(epollfd
, EPOLL_CTL_ADD
, wait_fd
, &epoll_event
);
562 perror("[eppoll] add");
566 ret
= syscall(SYS_epoll_pwait
, epollfd
,
567 (struct epoll_event
*) invalid
, 1, -1, NULL
);
570 printf("# [eppoll] data available\n");
571 ret
= read(wait_fd
, buf
, BUF_SIZE
);
573 perror("[eppoll] read");
575 } else if (ret
== 0) {
576 printf("# [eppoll] timeout\n");
578 perror("# epoll_pwait");
588 * Set maxevents to INT_MAX, should output "Invalid argument"
589 * The event should return an empty array.
592 void epoll_pwait_int_max(void)
596 struct epoll_event epoll_event
;
598 epollfd
= epoll_create(NB_FD
);
600 perror("[eppoll] create");
604 epoll_event
.events
= EPOLLIN
| EPOLLPRI
| EPOLLET
;
605 epoll_event
.data
.fd
= wait_fd
;
606 ret
= epoll_ctl(epollfd
, EPOLL_CTL_ADD
, wait_fd
, &epoll_event
);
608 perror("[eppoll] add");
612 ret
= syscall(SYS_epoll_pwait
, epollfd
, &epoll_event
, INT_MAX
, -1,
616 printf("# [eppoll] data available\n");
617 ret
= read(wait_fd
, buf
, BUF_SIZE
);
619 perror("[eppoll] read");
621 } else if (ret
== 0) {
622 printf("# [eppoll] timeout\n");
624 perror("# epoll_pwait");
634 void *ppoll_writer(void *arg
)
636 struct ppoll_thread_data
*data
= (struct ppoll_thread_data
*) arg
;
638 while (!stop_thread
) {
639 memset(data
->ufds
, data
->value
,
640 MAX_FDS
* sizeof(struct pollfd
));
648 void do_ppoll(int *fds
, struct pollfd
*ufds
)
655 ts
.tv_nsec
= 1 * MSEC_PER_NSEC
;
657 for (i
= 0; i
< MAX_FDS
; i
++) {
659 ufds
[i
].events
= POLLIN
|POLLPRI
;
662 ret
= ppoll(ufds
, MAX_FDS
, &ts
, NULL
);
666 } else if (ret
> 0) {
667 printf("# [ppoll] data available\n");
668 ret
= read(wait_fd
, buf
, BUF_SIZE
);
670 perror("[ppoll] read");
673 printf("# [ppoll] timeout\n");
678 void stress_ppoll(int *fds
, int value
)
682 struct ppoll_thread_data thread_data
;
683 struct pollfd ufds
[MAX_FDS
];
685 thread_data
.ufds
= ufds
;
686 thread_data
.value
= value
;
689 ret
= pthread_create(&writer
, NULL
, &ppoll_writer
, (void *) &thread_data
);
691 fprintf(stderr
, "[error] pthread_create\n");
694 for (iter
= 0; iter
< NR_ITER
; iter
++) {
698 ret
= pthread_join(writer
, NULL
);
700 fprintf(stderr
, "[error] pthread_join\n");
708 * 3 rounds of NR_ITER iterations with concurrent updates of the pollfd
712 * - memset to INT_MAX
713 * Waits for input, but also set a timeout in case the input FD is overwritten
714 * before entering in the syscall. We use MAX_FDS FDs (dup of stdin), so the
715 * resulting trace is big (20MB).
717 * ppoll should work as expected and the trace should be readable at the end.
720 void ppoll_concurrent_write(void)
722 int i
, ret
, fds
[MAX_FDS
];
724 for (i
= 0; i
< MAX_FDS
; i
++) {
725 fds
[i
] = dup(wait_fd
);
731 stress_ppoll(fds
, 0);
732 stress_ppoll(fds
, 1);
733 stress_ppoll(fds
, INT_MAX
);
735 for (i
= 0; i
< MAX_FDS
; i
++) {
746 void *epoll_pwait_writer(void *addr
)
750 while (!stop_thread
) {
752 munmap(addr
, MAX_FDS
* sizeof(struct epoll_event
));
759 * epoll_pwait on MAX_FDS fds while a concurrent thread munmaps the
760 * buffer allocated for the returned data. This should randomly segfault.
761 * The trace should be readable and no kernel OOPS should occur.
764 void epoll_pwait_concurrent_munmap(void)
766 int ret
, epollfd
, i
, fds
[MAX_FDS
];
768 struct epoll_event
*epoll_event
;
771 for (i
= 0; i
< MAX_FDS
; i
++) {
774 epollfd
= epoll_create(MAX_FDS
);
776 perror("[eppoll] create");
780 epoll_event
= mmap(NULL
, MAX_FDS
* sizeof(struct epoll_event
),
781 PROT_READ
| PROT_WRITE
, MAP_PRIVATE
| MAP_ANONYMOUS
,
783 if (epoll_event
== MAP_FAILED
) {
788 for (i
= 0; i
< MAX_FDS
; i
++) {
789 fds
[i
] = dup(wait_fd
);
793 epoll_event
[i
].events
= EPOLLIN
| EPOLLPRI
| EPOLLET
;
794 epoll_event
[i
].data
.fd
= fds
[i
];
795 ret
= epoll_ctl(epollfd
, EPOLL_CTL_ADD
, fds
[i
], epoll_event
);
797 perror("[eppoll] add");
802 ret
= pthread_create(&writer
, NULL
, &epoll_pwait_writer
,
803 (void *) epoll_event
);
805 fprintf(stderr
, "[error] pthread_create\n");
809 ret
= epoll_pwait(epollfd
, epoll_event
, 1, 1, NULL
);
812 printf("# [eppoll] data available\n");
813 ret
= read(wait_fd
, buf
, BUF_SIZE
);
815 perror("[eppoll] read");
817 } else if (ret
== 0) {
818 printf("# [eppoll] timeout\n");
820 perror("# epoll_pwait");
824 ret
= pthread_join(writer
, NULL
);
826 fprintf(stderr
, "[error] pthread_join\n");
830 for (i
= 0; i
< MAX_FDS
; i
++) {
837 ret
= munmap(epoll_event
, MAX_FDS
* sizeof(struct epoll_event
));
849 void print_list(void)
851 fprintf(stderr
, "Test list (-t X):\n");
852 fprintf(stderr
, "\t1: Working cases for select, pselect6, poll, ppoll "
853 "and epoll, waiting for input\n");
854 fprintf(stderr
, "\t2: Timeout cases (1ms) for select, pselect6, poll, "
855 "ppoll and epoll\n");
856 fprintf(stderr
, "\t3: pselect with an invalid fd\n");
857 fprintf(stderr
, "\t4: ppoll with %d FDs\n", MAX_FDS
);
858 fprintf(stderr
, "\t5: ppoll buffer overflow, should segfault, waits "
860 fprintf(stderr
, "\t6: pselect with an invalid pointer, waits for "
862 fprintf(stderr
, "\t7: ppoll with ulong_max fds, waits for input\n");
863 fprintf(stderr
, "\t8: epoll_pwait with an invalid pointer, waits for "
865 fprintf(stderr
, "\t9: epoll_pwait with maxevents set to INT_MAX, "
866 "waits for input\n");
867 fprintf(stderr
, "\t10: ppoll with concurrent updates of the structure "
868 "from user-space, stress test (3000 iterations), "
869 "waits for input + timeout 1ms\n");
870 fprintf(stderr
, "\t11: epoll_pwait with concurrent munmap of the buffer "
871 "from user-space, should randomly segfault, run "
872 "multiple times, waits for input + timeout 1ms\n");
875 int main(int argc
, const char **argv
)
877 int c
, ret
, test
= -1;
879 struct rlimit open_lim
;
881 struct poptOption optionsTable
[] = {
882 { "test", 't', POPT_ARG_INT
, &test
, 0,
883 "Test to run", NULL
},
884 { "list", 'l', 0, 0, 'l',
885 "List of tests (-t X)", NULL
},
887 { NULL
, 0, 0, NULL
, 0 }
890 optCon
= poptGetContext(NULL
, argc
, argv
, optionsTable
, 0);
893 poptPrintUsage(optCon
, stderr
, 0);
900 while ((c
= poptGetNextOpt(optCon
)) >= 0) {
908 open_lim
.rlim_cur
= MAX_FDS
+ MIN_NR_FDS
;
909 open_lim
.rlim_max
= MAX_FDS
+ MIN_NR_FDS
;
911 ret
= setrlimit(RLIMIT_NOFILE
, &open_lim
);
918 * Some tests might segfault, but we need the getpid() to be output
919 * for the validation, disabling the buffering on stdout works.
921 setbuf(stdout
, NULL
);
922 printf("%d\n", getpid());
924 wait_fd
= STDIN_FILENO
;
936 pselect_invalid_fd();
942 ppoll_fds_buffer_overflow();
945 pselect_invalid_pointer();
948 ppoll_fds_ulong_max();
951 epoll_pwait_invalid_pointer();
954 epoll_pwait_int_max();
957 ppoll_concurrent_write();
960 epoll_pwait_concurrent_munmap();
963 poptPrintUsage(optCon
, stderr
, 0);
969 poptFreeContext(optCon
);