BUG/MINOR: tcp-rules: Stop content rules eval on read error and end-of-input
authorChristopher Faulet <cfaulet@haproxy.com>
Thu, 30 Sep 2021 12:56:30 +0000 (14:56 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 4 Oct 2021 16:11:39 +0000 (18:11 +0200)
For now, tcp-request and tcp-response content rules evaluation is
interrupted before the inspect-delay when the channel's buffer is full, the
RX path is blocked or when a shutdown for reads was received. To sum up, the
evaluation is interrupted when no more input data are expected. However, it
is not exhaustive. It also happens when end of input is reached (CF_EOI flag
set) or when a read error occurred (CF_READ_ERROR flag set).

Note that, AFAIK, it is only a problem on HAProy 2.3 and prior when a H1 to
H2 upgrade is performed. On newer versions, it works as expected because the
stream is not created at this stage.

This patch must be backported as far as 2.0.

(cherry picked from commit cb59e0bc3cbe48eedd88e91b999a471724a6b709)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit fc553c9f0b9cacd4e0ec10bc9ff56879248a9b1c)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

src/tcp_rules.c

index e22a90d..eadd3a0 100644 (file)
@@ -112,7 +112,7 @@ int tcp_inspect_request(struct stream *s, struct channel *req, int an_bit)
         * - if one rule returns KO, then return KO
         */
 
-       if ((req->flags & CF_SHUTR) || channel_full(req, global.tune.maxrewrite) ||
+       if ((req->flags & (CF_EOI|CF_SHUTR|CF_READ_ERROR)) || channel_full(req, global.tune.maxrewrite) ||
            si_rx_blocked_room(chn_prod(req)) ||
            !s->be->tcp_req.inspect_delay || tick_is_expired(s->rules_exp, now_ms))
                partial = SMP_OPT_FINAL;
@@ -268,7 +268,7 @@ int tcp_inspect_response(struct stream *s, struct channel *rep, int an_bit)
         * - if one rule returns OK, then return OK
         * - if one rule returns KO, then return KO
         */
-       if ((rep->flags & CF_SHUTR) || channel_full(rep, global.tune.maxrewrite) ||
+       if ((rep->flags & (CF_EOI|CF_SHUTR|CF_READ_ERROR)) || channel_full(rep, global.tune.maxrewrite) ||
            si_rx_blocked_room(chn_prod(rep)) ||
            !s->be->tcp_rep.inspect_delay || tick_is_expired(s->rules_exp, now_ms))
                partial = SMP_OPT_FINAL;