mirror of
https://github.com/apache/httpd.git
synced 2025-08-08 15:02:10 +03:00
mod_proxy: Fix potential tunneling infinite loop and spurious timeout.
PRs 65521 and 65519. * modules/proxy/proxy_util.c(ap_proxy_tunnel_run): Avoid an infinite loop by shutting down the connection for write when poll() returns POLLHUP and read is already down. PR 65521. * modules/proxy/proxy_util.c(ap_proxy_tunnel_run): When write completion is finished don't check for ap_filter_input_pending() before proxy_tunnel_forward() to flush input data, this is a nonblocking read already which will do the same thing implicitely. ap_filter_input_pending() is broken in 2.4.x without the whole pending data mechanism (not backported yet), so let's align here. PR 65519. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1892740 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -4890,12 +4890,16 @@ PROXY_DECLARE(int) ap_proxy_tunnel_run(proxy_tunnel_rec *tunnel)
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
/* Write if we asked for POLLOUT, and got it or POLLERR
|
||||
* alone (i.e. not with POLLIN|HUP). We want the output filters
|
||||
* to know about the socket error if any, by failing the write.
|
||||
/* We want to write if we asked for POLLOUT and got:
|
||||
* - POLLOUT: the socket is ready for write;
|
||||
* - !POLLIN: the socket is in error state (POLLERR) so we let
|
||||
* the user know by failing the write and log, OR the socket
|
||||
* is shutdown for read already (POLLHUP) so we have to
|
||||
* shutdown for write.
|
||||
*/
|
||||
if ((tc->pfd->reqevents & APR_POLLOUT)
|
||||
&& ((pfd->rtnevents & APR_POLLOUT)
|
||||
|| !(tc->pfd->reqevents & APR_POLLIN)
|
||||
|| !(pfd->rtnevents & (APR_POLLIN | APR_POLLHUP)))) {
|
||||
struct proxy_tunnel_conn *out = tc, *in = tc->other;
|
||||
|
||||
@@ -4944,12 +4948,25 @@ PROXY_DECLARE(int) ap_proxy_tunnel_run(proxy_tunnel_rec *tunnel)
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
/* Flush any pending input data now, we don't know when
|
||||
* the next POLLIN will trigger and retaining data might
|
||||
* deadlock the underlying protocol. We don't check for
|
||||
* pending data first with ap_filter_input_pending() since
|
||||
* the read from proxy_tunnel_forward() is nonblocking
|
||||
* anyway and returning OK if there's no data.
|
||||
*/
|
||||
rc = proxy_tunnel_forward(tunnel, in);
|
||||
if (rc != OK) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Read if we asked for POLLIN|HUP, and got it or POLLERR
|
||||
* alone (i.e. not with POLLOUT). We want the input filters
|
||||
* to know about the socket error if any, by failing the read.
|
||||
/* We want to read if we asked for POLLIN|HUP and got:
|
||||
* - POLLIN|HUP: the socket is ready for read or EOF (POLLHUP);
|
||||
* - !POLLOUT: the socket is in error state (POLLERR) so we let
|
||||
* the user know by failing the read and log.
|
||||
*/
|
||||
if ((tc->pfd->reqevents & APR_POLLIN)
|
||||
&& ((pfd->rtnevents & (APR_POLLIN | APR_POLLHUP))
|
||||
|
Reference in New Issue
Block a user