Skip to content
Permalink
Browse files Browse the repository at this point in the history
Fix loop in blocking read on transport timeout
The loop was cased by an incorrect errno if the transport read in
mgs_transport_read() fails with an APR TIMEUP status, as happens when
mod_reqtimeout limits are exceeded. Setting the transport errno to
EGAIN meant that a blocking read would be retried endlessly, setting
ETIMEDOUT instead makes the read fail as it should.

The bug was introduced in commit 92cb0cc,
first release to include it was 0.9.0.

Many thanks to Félix Arreola Rodríguez for the detailed analysis [1]
on the Debian bug tracker!

[1] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=942737#25
  • Loading branch information
airtower-luna committed Feb 23, 2023
1 parent 3855d9e commit d7eec4e
Showing 1 changed file with 7 additions and 2 deletions.
9 changes: 7 additions & 2 deletions src/gnutls_io.c
Expand Up @@ -2,7 +2,7 @@
* Copyright 2004-2005 Paul Querna
* Copyright 2008 Nikos Mavrogiannopoulos
* Copyright 2011 Dash Shendy
* Copyright 2015-2020 Fiona Klute
* Copyright 2015-2022 Fiona Klute
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -277,6 +277,11 @@ static apr_status_t gnutls_io_input_read(mgs_handle_t * ctxt,
gnutls_alert_get_name(rc));
ctxt->input_rc = APR_EGENERAL;
break;
} else if (rc == GNUTLS_E_PULL_ERROR
&& APR_STATUS_IS_TIMEUP(ctxt->input_rc)) {
ap_log_cerror(
APLOG_MARK, APLOG_TRACE2, ctxt->input_rc, ctxt->c,
"%s: transport read timed out", __func__);
} else {
/* Some Other Error. Report it. Die. */
if (gnutls_error_is_fatal(rc)) {
Expand Down Expand Up @@ -1003,7 +1008,7 @@ ssize_t mgs_transport_read(gnutls_transport_ptr_t ptr,
&& APR_BRIGADE_EMPTY(ctxt->input_bb))
{
ctxt->input_rc = rc;
gnutls_transport_set_errno(ctxt->session, EAGAIN);
gnutls_transport_set_errno(ctxt->session, ETIMEDOUT);
return -1;
}

Expand Down

0 comments on commit d7eec4e

Please sign in to comment.