Dear all, I can reproduce this. Moreover, this has already been patched upstream. I have backported the patch. Please apply by integrating 17-upstream-POLLRDHUP-handling-error-fix.patch into your debian package!
Regards Joachim Falk
Description: Fix Backported premature data truncation problem due to over eager POLLRDHUP handling. Origin: upstream; https://www.stunnel.org/pipermail/stunnel-users/2014-November/004860.html Last-Update: 2015-03-04 Index: stunnel4-5.06/src/client.c =================================================================== --- stunnel4-5.06.orig/src/client.c 2014-10-15 22:55:07.000000000 +0200 +++ stunnel4-5.06/src/client.c 2015-03-04 23:27:01.052295381 +0100 @@ -515,6 +515,11 @@ int write_wants_read=0, write_wants_write=0; /* actual conditions on file descriptors */ int sock_can_rd, sock_can_wr, ssl_can_rd, ssl_can_wr; +#ifdef USE_WIN32 + unsigned long bytes; +#else + int bytes; +#endif c->sock_ptr=c->ssl_ptr=0; @@ -810,32 +815,44 @@ } /****************************** check for hangup conditions */ - if(s_poll_rdhup(c->fds, c->sock_rfd->fd)) { - s_log(LOG_INFO, "Read socket closed (hangup)"); + /* http://marc.info/?l=linux-man&m=128002066306087 */ + /* readsocket() must be the last sock_rfd operation before FIONREAD */ + if(sock_open_rd && s_poll_rdhup(c->fds, c->sock_rfd->fd) && + (ioctlsocket(c->sock_rfd->fd, FIONREAD, &bytes) || !bytes)) { + s_log(LOG_INFO, "Read socket closed (read hangup)"); sock_open_rd=0; } - if(s_poll_hup(c->fds, c->sock_wfd->fd)) { + if(sock_open_wr && s_poll_hup(c->fds, c->sock_wfd->fd)) { if(c->ssl_ptr) { s_log(LOG_ERR, - "Write socket closed (hangup) with %d unsent byte(s)", + "Write socket closed (write hangup) with %d unsent byte(s)", c->ssl_ptr); longjmp(c->err, 1); /* reset the socket */ } - s_log(LOG_INFO, "Write socket closed (hangup)"); + s_log(LOG_INFO, "Write socket closed (write hangup)"); sock_open_wr=0; } - if(s_poll_hup(c->fds, c->ssl_rfd->fd) || - s_poll_hup(c->fds, c->ssl_wfd->fd)) { + /* SSL_read() must be the last ssl_rfd operation before FIONREAD */ + if(!(SSL_get_shutdown(c->ssl)&SSL_RECEIVED_SHUTDOWN) && + s_poll_rdhup(c->fds, c->ssl_rfd->fd) && + (ioctlsocket(c->ssl_rfd->fd, FIONREAD, &bytes) || !bytes)) { /* hangup -> buggy (e.g. Microsoft) peer: * SSL socket closed without close_notify alert */ + s_log(LOG_INFO, "SSL socket closed (read hangup)"); + SSL_set_shutdown(c->ssl, + SSL_get_shutdown(c->ssl)|SSL_RECEIVED_SHUTDOWN); + } + if(!(SSL_get_shutdown(c->ssl)&SSL_SENT_SHUTDOWN) && + s_poll_hup(c->fds, c->ssl_wfd->fd)) { if(c->sock_ptr || write_wants_write) { s_log(LOG_ERR, - "SSL socket closed (hangup) with %d unsent byte(s)", + "SSL socket closed (write hangup) with %d unsent byte(s)", c->sock_ptr); longjmp(c->err, 1); /* reset the socket */ } - s_log(LOG_INFO, "SSL socket closed (hangup)"); - SSL_set_shutdown(c->ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN); + s_log(LOG_INFO, "SSL socket closed (write hangup)"); + SSL_set_shutdown(c->ssl, + SSL_get_shutdown(c->ssl)|SSL_SENT_SHUTDOWN); } /****************************** check write shutdown conditions */
signature.asc
Description: OpenPGP digital signature