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 <m.niestroj@emb.dev>
This commit is contained in:
Marcin Niestroj 2024-04-08 16:13:19 +02:00 committed by Anas Nashif
parent 7c506fad6b
commit ea44e2715a
3 changed files with 25 additions and 0 deletions

View file

@ -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);

View file

@ -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;

View file

@ -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);