aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven <sluong@cisco.com>2018-09-08 14:06:16 -0700
committerDamjan Marion <dmarion@me.com>2018-09-09 20:26:40 +0000
commit97f592f474ebaeba0c9a0f50db8f5627cc444aca (patch)
treedde4cf9004ddf5844493747f387b9473383dafac
parentd4d7e8ad84cb24cee31f10d5bfedab715df65754 (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> (cherry picked from commit aec7297ba012e1fe4bbf85cdaec8e810aa476cea)
-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)
{