]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: mux-h1: Don't block SE_FL_ERROR if EOS is not reported on H1C
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 15 Mar 2023 18:10:55 +0000 (19:10 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 16 Mar 2023 07:54:51 +0000 (08:54 +0100)
When a connection error is encountered during a receive, the error is not
immediatly reported to the SE descriptor. We take care to process all
pending input data first. However, when the error is finally reported, a
fatal error is reported only if a read0 was also received. Otherwise, only a
pending error is reported.

With a raw socket, it is not an issue because shutdowns for read and write
are systematically reported too when a connection error is detected. So in
this case, the fatal error is always reported to the SE descriptor. But with
a SSL socket, in case of pure SSL error, only the connection error is
reported. This prevent the fatal error to go up. And because the connection
is in error, no more receive or send are preformed on the socket. The mux is
blocked till a timeout is triggered at the stream level, looping infinitly
to progress.

To fix the bug, during the demux stage, when there is no longer pending
data, the read error is reported to the SE descriptor, regardless the
shutdown for reads was received or not. No more data are expected, so it is
safe.

This patch should fix the issue #2046. It must be backported to 2.7.

src/mux_h1.c

index 4b071f80ba5e5e1c600e683a549672cf4fa2702c..2390aad3af07408e63bc807fdb8d2de5c0840e6e 100644 (file)
@@ -1930,6 +1930,11 @@ static size_t h1_process_demux(struct h1c *h1c, struct buffer *buf, size_t count
                                TRACE_STATE("Re-enable output processing", H1_EV_TX_DATA|H1_EV_H1S_BLK|H1_EV_STRM_WAKE, h1c->conn, h1s);
                        }
                }
+               if (h1c->flags & H1C_F_ERROR) {
+                       /* Report a terminal error to the SE if a previous read error was detected */
+                       se_fl_set(h1s->sd, SE_FL_ERROR);
+                       TRACE_STATE("report ERROR to SE", H1_EV_RX_DATA|H1_EV_H1S_ERR, h1c->conn, h1s);
+               }
        }
 
   end: