aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven <sluong@cisco.com>2018-09-08 14:06:16 -0700
committerSteven <sluong@cisco.com>2018-09-08 14:22:08 -0700
commitaec7297ba012e1fe4bbf85cdaec8e810aa476cea (patch)
tree8e07827b19b0be5bc0e56e2499ef6bfebc9e8720
parentd783d1d6bf869169df7f3cfc44f110f7869806f3 (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.c33
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)
{