]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MAJOR: mux-h2: don't try to decode a response HEADERS frame in idle state
authorWilly Tarreau <w@1wt.eu>
Sun, 24 Nov 2019 13:57:53 +0000 (14:57 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 25 Nov 2019 10:34:20 +0000 (11:34 +0100)
Christopher found another issue in the H2 backend implementation that
results from a miss in the H2 spec: the processing of a HEADERS frame
is always permitted in IDLE state, but this doesn't make sense on the
response path! And here when facing such a frame, we try to decode it
while we didn't allocate any stream, so we end up trying to fill the
idle stream's buffer (read-only) and crash.

What we're doing here is that if we get a HEADERS frame in IDLE state
from a server, we terminate the connection with a PROTOCOL_ERROR. No
such transition seems to be permitted by the spec but it seems to be
the only sane solution.

This fix must be backported as far as 1.9. Note that in 2.0 and earlier
there's no h2_frame_check_vs_state() function, instead the check is
inlined in h2_process_demux().

src/mux_h2.c

index 24543458b72bdace3fda38e89ea8991de4cd5e5f..9502e05513223963856f91a70915a471441c334b 100644 (file)
@@ -2775,6 +2775,13 @@ static int h2_frame_check_vs_state(struct h2c *h2c, struct h2s *h2s)
                return 0;
        }
 
+       if (h2s->st == H2_SS_IDLE && (h2c->flags & H2_CF_IS_BACK)) {
+               /* only PUSH_PROMISE would be permitted here */
+               h2c_error(h2c, H2_ERR_PROTOCOL_ERROR);
+               TRACE_DEVEL("leaving in error (idle&back)", H2_EV_RX_FRAME|H2_EV_RX_FHDR|H2_EV_PROTO_ERR, h2c->conn, h2s);
+               return 0;
+       }
+
        if (h2s->st == H2_SS_HREM && h2c->dft != H2_FT_WINDOW_UPDATE &&
            h2c->dft != H2_FT_RST_STREAM && h2c->dft != H2_FT_PRIORITY) {
                /* RFC7540#5.1: any frame other than WU/PRIO/RST in