]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: connection: properly leave stopping list on error
authorWilly Tarreau <w@1wt.eu>
Wed, 12 Jan 2022 16:24:26 +0000 (17:24 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 12 Jan 2022 16:31:01 +0000 (17:31 +0100)
The stopping-list management introduced by commit d3a88c1c3 ("MEDIUM:
connection: close front idling connection on soft-stop") missed two
error paths in the H1 and H2 muxes. The effect is that if a stream
or HPACK table couldn't be allocated for these incoming connections,
we would leave with the connection freed still attached to the
stopping_list and it would never leave it, resulting in use-after-free
hence either a crash or a data corruption.

This is marked as medium as it only happens under extreme memory pressure
or when playing with tune.fail-alloc. Other stability issues remain in
such a case so that abnormal behaviors cannot be explained by this bug
alone.

This must be backported to 2.4.

src/mux_h1.c
src/mux_h2.c

index a00ac60f29f494d76b9ba6ff106357d870af72f0..1f8cad2452d37d279e26e0ec5793dd17651e62f1 100644 (file)
@@ -990,6 +990,8 @@ static int h1_init(struct connection *conn, struct proxy *proxy, struct session
                tasklet_free(h1c->wait_event.tasklet);
        pool_free(pool_head_h1c, h1c);
  fail_h1c:
+       if (!conn_is_back(conn))
+               LIST_DEL_INIT(&conn->stopping_list);
        conn->ctx = conn_ctx; // restore saved context
        TRACE_DEVEL("leaving in error", H1_EV_H1C_NEW|H1_EV_H1C_END|H1_EV_H1C_ERR);
        return -1;
index 6338cf02c0e93bd9bb09e7e1895eefa7f95330b0..ddc19c176958ede15a17ae49456d10ae81945e3a 100644 (file)
@@ -1042,6 +1042,8 @@ static int h2_init(struct connection *conn, struct proxy *prx, struct session *s
                tasklet_free(h2c->wait_event.tasklet);
        pool_free(pool_head_h2c, h2c);
   fail_no_h2c:
+       if (!conn_is_back(conn))
+               LIST_DEL_INIT(&conn->stopping_list);
        conn->ctx = conn_ctx; /* restore saved ctx */
        TRACE_DEVEL("leaving in error", H2_EV_H2C_NEW|H2_EV_H2C_END|H2_EV_H2C_ERR);
        return -1;