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 
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 
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 
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 
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