From ea44e2715a504600cbcff4dd9cf31d6ffeaf349c Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Mon, 8 Apr 2024 16:13:19 +0200 Subject: [PATCH] drivers: net: nsos: update unwatched file descriptor with poll() zsock_poll_internal() iterates through all fds to call ZFD_IOCTL_POLL_UPDATE on them. In cases when -EAGAIN is returned from one of such syscalls (which happens for example for TLS sockets when in the middle of a TLS handshake) whole fds array is iterated once again. This means that ZFD_IOCTL_POLL_UPDATE can be called more than once for a single preceding ZFD_IOCTL_POLL_PREPARE operation. This resulted in error in nsos_adapt_poll_remove() call, which was not intended to be called twice. In case ZFD_IOCTL_POLL_UPDATE is called second time, update 'revents' just by calling poll() syscall on the host (Linux) side with 0 timeout. Signed-off-by: Marcin Niestroj --- drivers/net/nsos.h | 1 + drivers/net/nsos_adapt.c | 19 +++++++++++++++++++ drivers/net/nsos_sockets.c | 5 +++++ 3 files changed, 25 insertions(+) diff --git a/drivers/net/nsos.h b/drivers/net/nsos.h index 14b495177c..e7ece3ded7 100644 --- a/drivers/net/nsos.h +++ b/drivers/net/nsos.h @@ -113,6 +113,7 @@ int nsos_adapt_recvfrom(int fd, void *buf, size_t len, int flags, void nsos_adapt_poll_add(struct nsos_mid_pollfd *pollfd); void nsos_adapt_poll_remove(struct nsos_mid_pollfd *pollfd); +void nsos_adapt_poll_update(struct nsos_mid_pollfd *pollfd); int nsos_adapt_fcntl_getfl(int fd); int nsos_adapt_fcntl_setfl(int fd, int flags); diff --git a/drivers/net/nsos_adapt.c b/drivers/net/nsos_adapt.c index 9c8184bd61..5f44b332f6 100644 --- a/drivers/net/nsos_adapt.c +++ b/drivers/net/nsos_adapt.c @@ -533,6 +533,25 @@ void nsos_adapt_poll_remove(struct nsos_mid_pollfd *pollfd) nsos_adapt_nfds--; } +void nsos_adapt_poll_update(struct nsos_mid_pollfd *pollfd) +{ + struct pollfd fds = { + .fd = pollfd->fd, + .events = pollfd->events, + }; + int ret; + + ret = poll(&fds, 1, 0); + if (ret < 0) { + nsi_print_error_and_exit("error in poll(): errno=%d\n", errno); + return; + } + + if (ret > 0) { + pollfd->revents = fds.revents; + } +} + struct nsos_addrinfo_wrap { struct nsos_mid_addrinfo addrinfo_mid; struct nsos_mid_sockaddr_storage addr_storage; diff --git a/drivers/net/nsos_sockets.c b/drivers/net/nsos_sockets.c index 98d6c42990..2e1ff4589d 100644 --- a/drivers/net/nsos_sockets.c +++ b/drivers/net/nsos_sockets.c @@ -298,6 +298,11 @@ static int nsos_poll_update(struct nsos_socket *sock, struct zsock_pollfd *pfd, signaled = 0; flags = 0; + if (!sys_dnode_is_linked(&sock->node)) { + nsos_adapt_poll_update(&sock->pollfd); + return 0; + } + nsos_adapt_poll_remove(&sock->pollfd); sys_dlist_remove(&sock->node);