From a67d90d0975d138e03ffc7a442354a63a66ddc3d Mon Sep 17 00:00:00 2001 From: Andrew Yourtchenko Date: Fri, 4 Jul 2025 18:07:27 +0200 Subject: [PATCH] memif: avoid double-close of the socket on client abort with un-read data In some cases, there are two times the clib_file_del is called: 1) from memif_disconnect -> memif_socket_close call site in memif_master_conn_fd_error 2) the supposedly defensive code at the end of memif_master_conn_fd_error. This was observed upon using of an artisanal memif client, which did not correctly drain the data written by VPP to the notification socket - a simple Ctrl-C in the client was enough to trivially reproduce the issue. In real world scenario using the stock client this is expected to be a fairly narrow race condition. The issue can be demonstrated as follows: diff --git a/src/vlib/file.c b/src/vlib/file.c index 286b0d1f2..29138f485 100644 --- a/src/vlib/file.c +++ b/src/vlib/file.c @@ -200,6 +200,8 @@ epoll: { clib_file_t *f = e->data.ptr; clib_error_t *err; + clib_warning("EPOLL: count %d, fd index: %d, events: %x", n_fds_ready, f->index, e->events); + if (PREDICT_FALSE (!f->active)) { vlib_file_poll:203: EPOLL: count 1, fd index: 6, events: 1 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 1 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 4 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 1 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 4 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 1 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 4 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 1 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 4 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 1 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 4 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 1 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 4 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 11 memif_plugin [error ]: memif0/0: default_socket_recvmsg: disconnected Failing case, where the client did not drain the data sent to it: DBGvpp# create interface memif master DBGvpp# set int ip address memif0/0 192.0.2.1/24 DBGvpp# set interface state memif0/0 up DBGvpp# vlib_file_poll:203: EPOLL: count 1, fd index: 6, events: 1 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 1 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 4 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 1 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 4 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 1 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 4 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 1 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 4 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 1 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 4 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 1 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 4 vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 19 memif_plugin [warn ]: Error on unknown file descriptor 21 vlib/file [error ]: vlib_file_update: epoll_ctl() failed, errno 9 /home/ayourtch/vpp/src/vppinfra/pool.h:291 (_pool_put_index) assertion `!pool_is_free_index (p, index)' fails received signal SIGABRT, PC 0xffffa7f10a50 Type: fix Change-Id: I13247c431605470c6a59d7d4630cefa999733107 Signed-off-by: Andrew Yourtchenko --- src/plugins/memif/socket.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/memif/socket.c b/src/plugins/memif/socket.c index c2b11fc2ecb..5890e2d91f2 100644 --- a/src/plugins/memif/socket.c +++ b/src/plugins/memif/socket.c @@ -629,6 +629,7 @@ memif_master_conn_fd_error (clib_file_t * uf) err = clib_error_return (0, "connection fd error"); memif_disconnect (mif, err); clib_error_free (err); + return 0; } else { -- 2.16.6