From: Christopher Faulet Date: Thu, 28 Nov 2024 09:01:41 +0000 (+0100) Subject: BUG/MEDIUM: http-ana: Reset request flag about data sent to perform a L7 retry X-Git-Tag: v3.2-dev1~62 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=62f37801c881f68060cedb7a74b5b8cb5fcfec81;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: http-ana: Reset request flag about data sent to perform a L7 retry It is possible to loose the request after several L7 retries, leading to crashes, because the request channel flag stating some data were sent is not properly reset. When a L7 retry is performed, some flags on different entities must be reset to be sure a new connection will be properly retried, just like it was the first one, mainly because there was no connection establishment failure. One of them, on the request channel, is not reset. The flag stating some data were already sent. It is annoying because this flag is used during the connection establishment to know if an error is triggered at the connection level or at the data level. In the last case, the error must be handled by the HTTP response analyzer, to eventually perform another L7 retry. Because CF_WROTE_DATA flag is not removed when a L7 retry is performed, a subsequent connection establishment error may be handled as a L7 error while in fact the request was never sent. It also means the request was never saved in the buffer used to performed L7 retries. Thus, on the next L7 retires, the request is just lost. This forecefully leads to a bunch of undefined behavior. One of them is a crash, when the request is used to perform the load-balancing. This patch should fix issue #2793. It must be backported to all stable versions. --- diff --git a/src/http_ana.c b/src/http_ana.c index 1dae2ee191..24311b1a22 100644 --- a/src/http_ana.c +++ b/src/http_ana.c @@ -1173,7 +1173,7 @@ static __inline int do_l7_retry(struct stream *s, struct stconn *sc) /* Remove any write error from the request, and read error from the response */ s->scf->flags &= ~(SC_FL_EOS|SC_FL_ABRT_DONE|SC_FL_ABRT_WANTED); - req->flags &= ~CF_WRITE_TIMEOUT; + req->flags &= ~(CF_WRITE_TIMEOUT|CF_WROTE_DATA); res->flags &= ~(CF_READ_TIMEOUT | CF_READ_EVENT); res->analysers &= AN_RES_FLT_END; s->conn_err_type = STRM_ET_NONE;