From: Willy Tarreau Date: Sun, 24 Nov 2019 13:57:53 +0000 (+0100) Subject: BUG/MAJOR: mux-h2: don't try to decode a response HEADERS frame in idle state X-Git-Tag: v2.1.0~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=57a1816faec652d9c7fbd9be48ce25c832be20d9;p=thirdparty%2Fhaproxy.git BUG/MAJOR: mux-h2: don't try to decode a response HEADERS frame in idle state 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(). --- diff --git a/src/mux_h2.c b/src/mux_h2.c index 24543458b7..9502e05513 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -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