]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MAJOR: http: don't requeue an idle connection that is already queued
authorWilly Tarreau <w@1wt.eu>
Mon, 2 Nov 2015 19:20:11 +0000 (20:20 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 2 Nov 2015 21:28:25 +0000 (22:28 +0100)
Cyril Bonté reported a reproduceable sequence which can lead to a crash
when using backend connection reuse. The problem comes from the fact that
we systematically add the server connection to an idle pool at the end of
the HTTP transaction regardless of the fact that it might already be there.

This is possible for example when processing a request which doesn't use
a server connection (typically a redirect) after a request which used a
connection. Then after the first request, the connection was already in
the idle queue and we're putting it a second time at the end of the second
request, causing a corruption of the idle pool.

Interestingly, the memory debugger in 1.7 immediately detected a suspicious
double free on the connection, leading to a very early detection of the
cause instead of its consequences.

Thanks to Cyril for quickly providing a working reproducer.

This fix must be backported to 1.6 since connection reuse was introduced
there.

src/proto_http.c

index 32b9063a99706ca06078b3e05fc938d510ef2459..2dcac06745f102c1605ee566c6b00ae3ab2007b0 100644 (file)
@@ -5278,8 +5278,8 @@ void http_end_txn_clean_session(struct stream *s)
        channel_auto_read(&s->res);
        channel_auto_close(&s->res);
 
-       /* we're in keep-alive with an idle connection, monitor it */
-       if (srv_conn) {
+       /* we're in keep-alive with an idle connection, monitor it if not already done */
+       if (srv_conn && LIST_ISEMPTY(&srv_conn->list)) {
                srv = objt_server(srv_conn->target);
                if (!srv)
                        si_idle_conn(&s->si[1], NULL);