1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) Linux Test Project, 2021
4 * Author: Xie Ziyao <[email protected]>
5 */
6
7 /*\
8 * [Description]
9 *
10 * Verify that epoll_ctl() fails with ELOOP if fd refers to an epoll instance
11 * and this EPOLL_CTL_ADD operation would result in a circular loop of epoll
12 * instances monitoring one another.
13 */
14
15 #include <poll.h>
16 #include <sys/epoll.h>
17
18 #include "tst_test.h"
19
20 #define MAX_DEPTH 5
21
22 static int epfd, origin_epfd, new_epfd;
23 static int fd[2];
24
25 static struct epoll_event events = {.events = EPOLLIN};
26
setup(void)27 static void setup(void)
28 {
29 int i;
30
31 SAFE_PIPE(fd);
32
33 for (i = 0, epfd = fd[0]; i < MAX_DEPTH; i++, epfd = new_epfd) {
34 new_epfd = epoll_create(1);
35 if (new_epfd == -1)
36 tst_brk(TBROK | TERRNO, "fail to create epoll instance");
37
38 if (i == 0)
39 origin_epfd = new_epfd;
40
41 events.data.fd = epfd;
42 if (epoll_ctl(new_epfd, EPOLL_CTL_ADD, epfd, &events))
43 tst_brk(TBROK | TERRNO, "epoll_ctl(..., EPOLL_CTL_ADD, ...)");
44 }
45
46 events.data.fd = fd[0];
47 if (epoll_ctl(origin_epfd, EPOLL_CTL_DEL, fd[0], &events))
48 tst_brk(TBROK | TERRNO, "epoll_ctl(..., EPOLL_CTL_DEL, ...)");
49 }
50
cleanup(void)51 static void cleanup(void)
52 {
53 if (fd[0])
54 SAFE_CLOSE(fd[0]);
55
56 if (fd[1])
57 SAFE_CLOSE(fd[1]);
58 }
59
verify_epoll_ctl(void)60 static void verify_epoll_ctl(void)
61 {
62 events.data.fd = epfd;
63 TST_EXP_FAIL(epoll_ctl(origin_epfd, EPOLL_CTL_ADD, epfd, &events),
64 ELOOP, "epoll_ctl(..., EPOLL_CTL_ADD, ...)");
65 }
66
67 static struct tst_test test = {
68 .setup = setup,
69 .cleanup = cleanup,
70 .test_all = verify_epoll_ctl,
71 };
72