From 8adae7c15ffb5df8fcbb41496735fef25d6c4df3 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Thu, 22 Mar 2018 17:37:05 +0100 Subject: [PATCH] BUG/MINOR: h2: ensure we can never send an RST_STREAM in response to an RST_STREAM There are some corner cases where this could happen by accident. Since the spec explicitly forbids this (RFC7540#5.4.2), let's add a test in the two only functions which make the RST to avoid this. Thanks to user klzgrad for reporting this problem. Usually it is expected to be harmless but may result in browsers issuing a warning. This fix must be backported to 1.8. --- src/mux_h2.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/mux_h2.c b/src/mux_h2.c index d15b0e33b..7b2f53818 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -844,6 +844,14 @@ static int h2s_send_rst_stream(struct h2c *h2c, struct h2s *h2s) if (!h2s || h2s->st == H2_SS_CLOSED) return 1; + /* RFC7540#5.4.2: To avoid looping, an endpoint MUST NOT send a + * RST_STREAM in response to a RST_STREAM frame. + */ + if (h2c->dft == H2_FT_RST_STREAM) { + ret = 1; + goto ignore; + } + if (h2c_mux_busy(h2c, h2s)) { h2s->flags |= H2_SF_BLK_MBUSY; return 0; @@ -874,6 +882,7 @@ static int h2s_send_rst_stream(struct h2c *h2c, struct h2s *h2s) } } + ignore: h2s->flags |= H2_SF_RST_SENT; h2s_close(h2s); return ret; @@ -896,6 +905,14 @@ static int h2c_send_rst_stream(struct h2c *h2c, struct h2s *h2s) char str[13]; int ret; + /* RFC7540#5.4.2: To avoid looping, an endpoint MUST NOT send a + * RST_STREAM in response to a RST_STREAM frame. + */ + if (h2c->dft == H2_FT_RST_STREAM) { + ret = 1; + goto ignore; + } + if (h2c_mux_busy(h2c, h2s)) { h2c->flags |= H2_CF_DEM_MBUSY; return 0; @@ -928,6 +945,7 @@ static int h2c_send_rst_stream(struct h2c *h2c, struct h2s *h2s) } } + ignore: if (h2s->st > H2_SS_IDLE && h2s->st < H2_SS_CLOSED) { h2s->flags |= H2_SF_RST_SENT; h2s_close(h2s);