1 /*
2 * Copyright (c) 2016 Fujitsu Ltd.
3 * Author: Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program.
17 */
18
19 /*
20 * Description:
21 * 1) epoll_wait(2) fails if epfd is not a valid file descriptor
22 * 2) epoll_wait(2) fails if epfd is not an epoll file descriptor
23 * 3) epoll_wait(2) fails if maxevents is less than zero
24 * 4) epoll_wait(2) fails if maxevents is equal to zero
25 * 5) epoll_wait(2) fails if the memory area pointed to by events
26 * is not accessible with write permissions.
27 *
28 * Expected Result:
29 * 1) epoll_wait(2) should return -1 and set errno to EBADF
30 * 2) epoll_wait(2) should return -1 and set errno to EINVAL
31 * 3) epoll_wait(2) should return -1 and set errno to EINVAL
32 * 4) epoll_wait(2) should return -1 and set errno to EINVAL
33 * 5) epoll_wait(2) should return -1 and set errno to EFAULT
34 */
35
36 #include <sys/epoll.h>
37 #include <sys/mman.h>
38 #include <unistd.h>
39 #include <string.h>
40 #include <errno.h>
41
42 #include "test.h"
43 #include "safe_macros.h"
44
45 static int page_size, fds[2], epfd, inv_epfd, bad_epfd = -1;
46
47 static struct epoll_event epevs[1] = {
48 {.events = EPOLLOUT}
49 };
50
51 static struct epoll_event *ev_rdwr = epevs;
52 static struct epoll_event *ev_rdonly;
53
54 static struct test_case_t {
55 int *epfd;
56 struct epoll_event **ev;
57 int maxevents;
58 int exp_errno;
59 } tc[] = {
60 /* test1 */
61 {&bad_epfd, &ev_rdwr, 1, EBADF},
62 /* test2 */
63 {&inv_epfd, &ev_rdwr, 1, EINVAL},
64 /* test3 */
65 {&epfd, &ev_rdwr, -1, EINVAL},
66 /* test4 */
67 {&epfd, &ev_rdwr, 0, EINVAL},
68 /* test5 */
69 {&epfd, &ev_rdonly, 1, EFAULT}
70 };
71
72 char *TCID = "epoll_wait03";
73 int TST_TOTAL = ARRAY_SIZE(tc);
74
75 static void setup(void);
76 static void verify_epoll_wait(struct test_case_t *tc);
77 static void cleanup(void);
78
main(int ac,char ** av)79 int main(int ac, char **av)
80 {
81 int lc, i;
82
83 tst_parse_opts(ac, av, NULL, NULL);
84
85 setup();
86
87 for (lc = 0; TEST_LOOPING(lc); lc++) {
88 tst_count = 0;
89
90 for (i = 0; i < TST_TOTAL; i++)
91 verify_epoll_wait(&tc[i]);
92 }
93
94 cleanup();
95 tst_exit();
96 }
97
setup(void)98 static void setup(void)
99 {
100 tst_sig(NOFORK, DEF_HANDLER, cleanup);
101
102 TEST_PAUSE;
103
104 page_size = getpagesize();
105
106 ev_rdonly = SAFE_MMAP(NULL, NULL, page_size, PROT_READ,
107 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
108
109 SAFE_PIPE(NULL, fds);
110
111 epfd = epoll_create(1);
112 if (epfd == -1) {
113 tst_brkm(TBROK | TERRNO, cleanup,
114 "failed to create epoll instance");
115 }
116
117 epevs[0].data.fd = fds[1];
118
119 if (epoll_ctl(epfd, EPOLL_CTL_ADD, fds[1], &epevs[0])) {
120 tst_brkm(TBROK | TERRNO, cleanup,
121 "failed to register epoll target");
122 }
123 }
124
verify_epoll_wait(struct test_case_t * tc)125 static void verify_epoll_wait(struct test_case_t *tc)
126 {
127 TEST(epoll_wait(*(tc->epfd), *(tc->ev), tc->maxevents, -1));
128 if (TEST_RETURN != -1) {
129 tst_resm(TFAIL, "epoll_wait() succeed unexpectedly");
130 } else {
131 if (tc->exp_errno == TEST_ERRNO) {
132 tst_resm(TPASS | TTERRNO,
133 "epoll_wait() fails as expected");
134 } else {
135 tst_resm(TFAIL | TTERRNO,
136 "epoll_wait() fails unexpectedly, "
137 "expected %d: %s", tc->exp_errno,
138 tst_strerrno(tc->exp_errno));
139 }
140 }
141 }
142
cleanup(void)143 static void cleanup(void)
144 {
145 if (epfd > 0 && close(epfd))
146 tst_resm(TWARN | TERRNO, "failed to close epfd");
147
148 if (close(fds[0]))
149 tst_resm(TWARN | TERRNO, "close(fds[0]) failed");
150
151 if (close(fds[1]))
152 tst_resm(TWARN | TERRNO, "close(fds[1]) failed");
153 }
154