From 6a6735ece442298e000de43f5325842a442c263d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 11 Aug 2023 15:12:22 +1000 Subject: epoll: Always use epoll_ref for the epoll data variable epoll_ref contains a variety of information useful when handling epoll events on our sockets, and we place it in the epoll_event data field returned by epoll. However, for a few other things we use the 'fd' field in the standard union of types for that data field. This actually introduces a bug which is vanishingly unlikely to hit in practice, but very nasty if it ever did: theoretically if we had a very large file descriptor number for fd_tap or fd_tap_listen it could overflow into bits that overlap with the 'proto' field in epoll_ref. With some very bad luck this could mean that we mistakenly think an event on a regular socket is an event on fd_tap or fd_tap_listen. More practically, using different (but overlapping) fields of the epoll_data means we can't unify dispatch for the various different objects in the epoll. Therefore use the same epoll_ref as the data for the tap fds and the netns quit fd, adding new fd type values to describe them. Signed-off-by: David Gibson Signed-off-by: Stefano Brivio --- pasta.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'pasta.c') diff --git a/pasta.c b/pasta.c index 1e84680..dbe8e8c 100644 --- a/pasta.c +++ b/pasta.c @@ -365,7 +365,10 @@ void pasta_ns_conf(struct ctx *c) int pasta_netns_quit_init(struct ctx *c) { int flags = O_NONBLOCK | O_CLOEXEC; - struct epoll_event ev = { .events = EPOLLIN }; + union epoll_ref ref = { .type = EPOLL_TYPE_NSQUIT }; + struct epoll_event ev = { + .events = EPOLLIN + }; int inotify_fd; if (c->mode != MODE_PASTA || c->no_netns_quit || !*c->netns_base) @@ -381,7 +384,8 @@ int pasta_netns_quit_init(struct ctx *c) return -1; } - ev.data.fd = inotify_fd; + ref.fd = inotify_fd; + ev.data.u64 = ref.u64; epoll_ctl(c->epollfd, EPOLL_CTL_ADD, inotify_fd, &ev); return inotify_fd; -- cgit v1.2.3