From b0177a0828fe3f516326c1b63340ff153cc8beac Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 18 Oct 2022 15:48:31 -0700 Subject: [PATCH] init/epoll: Fix a potential use-after-free If UnregisterHandler() is called from inside a handler for an event that has not yet been processed then that will result in a use-after-free. Fix this by passing file descriptors to epoll_ctl() instead of pointers to map elements. Bug: 213617178 Change-Id: Ie62e3a299af964271ec24cd8fc2e794042b77ee6 Signed-off-by: Bart Van Assche --- init/epoll.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/init/epoll.cpp b/init/epoll.cpp index 24d356da1..dc2104313 100644 --- a/init/epoll.cpp +++ b/init/epoll.cpp @@ -54,9 +54,7 @@ Result Epoll::RegisterHandler(int fd, Handler handler, uint32_t events) { } epoll_event ev; ev.events = events; - // std::map's iterators do not get invalidated until erased, so we use the - // pointer to the std::function in the map directly for epoll_ctl. - ev.data.ptr = reinterpret_cast(&it->second); + ev.data.fd = fd; if (epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &ev) == -1) { Result result = ErrnoError() << "epoll_ctl failed to add fd"; epoll_handlers_.erase(fd); @@ -96,7 +94,11 @@ Result>> Epoll::Wait( } std::vector> pending_functions; for (int i = 0; i < num_events; ++i) { - auto& info = *reinterpret_cast(ev[i].data.ptr); + const auto it = epoll_handlers_.find(ev[i].data.fd); + if (it == epoll_handlers_.end()) { + continue; + } + const Info& info = it->second; if ((info.events & (EPOLLIN | EPOLLPRI)) == (EPOLLIN | EPOLLPRI) && (ev[i].events & EPOLLIN) != ev[i].events) { // This handler wants to know about exception events, and just got one.