diff options
author | Steven <sluong@cisco.com> | 2018-09-08 14:06:16 -0700 |
---|---|---|
committer | Steven <sluong@cisco.com> | 2018-09-08 14:22:08 -0700 |
commit | aec7297ba012e1fe4bbf85cdaec8e810aa476cea (patch) | |
tree | 8e07827b19b0be5bc0e56e2499ef6bfebc9e8720 | |
parent | d783d1d6bf869169df7f3cfc44f110f7869806f3 (diff) |
vlib: crash in linux_epoll_input_inline for accessing free file index [VPP-1412]
Under rare scenario, epoll may still post an event to VPP although the file
descriptor is already deleted via epoll_ctl (EPOLL_CTL_DEL) and the file
descriptor is close. VPP tries to access the free file index entry and crash.
The fix is to throw away the events which the file descriptor is already deleted.
Change-Id: Ieca3a1873aecb28630c3abc42c40341f27c2faa7
Signed-off-by: Steven <sluong@cisco.com>
-rw-r--r-- | src/vlib/unix/input.c | 33 |
1 files changed, 31 insertions, 2 deletions
diff --git a/src/vlib/unix/input.c b/src/vlib/unix/input.c index 0a61c05d471..8be0770bfd3 100644 --- a/src/vlib/unix/input.c +++ b/src/vlib/unix/input.c @@ -247,11 +247,40 @@ linux_epoll_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, for (e = em->epoll_events; e < em->epoll_events + n_fds_ready; e++) { u32 i = e->data.u32; - clib_file_t *f = pool_elt_at_index (fm->file_pool, i); + clib_file_t *f = fm->file_pool + i; clib_error_t *errors[4]; int n_errors = 0; - if (PREDICT_TRUE (!(e->events & EPOLLERR))) + if (PREDICT_FALSE (pool_is_free (fm->file_pool, f))) + { + /* + * Under rare scenerop, epoll may still post us events for the + * deleted file descriptor. We just deal with it and throw away the + * events for the corresponding file descriptor. + */ + if (e->events & EPOLLIN) + { + errors[n_errors] = + clib_error_return (0, "epoll event EPOLLIN dropped due " + "to free index %u", i); + n_errors++; + } + if (e->events & EPOLLOUT) + { + errors[n_errors] = + clib_error_return (0, "epoll event EPOLLOUT dropped due " + "to free index %u", i); + n_errors++; + } + if (e->events & EPOLLERR) + { + errors[n_errors] = + clib_error_return (0, "epoll event EPOLLERR dropped due " + "to free index %u", i); + n_errors++; + } + } + else if (PREDICT_TRUE (!(e->events & EPOLLERR))) { if (e->events & EPOLLIN) { |