From 3c562d042dee1e6d943062ba6648a96de86a6ac8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Thu, 8 Nov 2012 16:57:58 +0100 Subject: [PATCH] Noux: fix resetting wrong number of fds Since the number of the fds in the select call is not necassarily equal to the number of fds SYSCALL_SELECT returns we have to reset the number of fds given as argument to select(). This keeps OpenSSH from reading from a non-ready socket. Fixes #494. --- ports/src/lib/libc_noux/plugin.cc | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/ports/src/lib/libc_noux/plugin.cc b/ports/src/lib/libc_noux/plugin.cc index 693087592f..39eb88c7f1 100644 --- a/ports/src/lib/libc_noux/plugin.cc +++ b/ports/src/lib/libc_noux/plugin.cc @@ -237,7 +237,7 @@ static size_t marshal_fds(fd_set *src_fds, int nfds, /** * Unmarshal result of select syscall into fd set */ -static void unmarshal_fds(int *src_fds, size_t src_fds_len, fd_set *dst_fds) +static void unmarshal_fds(int nfds, int *src_fds, size_t src_fds_len, fd_set *dst_fds) { if (!dst_fds) return; @@ -247,8 +247,13 @@ static void unmarshal_fds(int *src_fds, size_t src_fds_len, fd_set *dst_fds) * it was allocated dynamically. So we will reset the fd_set manually which * will work fine as long as we are using FreeBSDs libc - another libc however * might use a different struct. + * + * Note: The fds are actually stored in a bit-array. So we need to calculate + * how many array entries we have to reset. sizeof (fd_mask) will return the + * size of one entry in bytes. */ - for (size_t i = 0; i < src_fds_len; i++) + int _ = nfds / (sizeof (fd_mask) * 8) + 1; + for (int i = 0; i < _; i++) dst_fds->__fds_bits[i] = 0; for (size_t i = 0; i < src_fds_len; i++) @@ -329,19 +334,19 @@ extern "C" int select(int nfds, fd_set *readfds, fd_set *writefds, int total_fds = 0; if (readfds != NULL) { - unmarshal_fds(src, out_fds.num_rd, readfds); + unmarshal_fds(nfds, src, out_fds.num_rd, readfds); src += out_fds.num_rd; total_fds += out_fds.num_rd; } if (writefds != NULL) { - unmarshal_fds(src, out_fds.num_wr, writefds); + unmarshal_fds(nfds, src, out_fds.num_wr, writefds); src += out_fds.num_wr; total_fds += out_fds.num_wr; } if (exceptfds != NULL) { - unmarshal_fds(src, out_fds.num_ex, exceptfds); + unmarshal_fds(nfds, src, out_fds.num_ex, exceptfds); /* exceptfds are currently ignored */ }