From: Christopher Faulet Date: Fri, 16 May 2025 12:19:52 +0000 (+0200) Subject: BUG/MEDIUM: stconn: Disable 0-copy forwarding for filters altering the payload X-Git-Tag: v3.2-dev17~41 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f45a632bad6fbcdadeba41038103a5738f8d709d;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: stconn: Disable 0-copy forwarding for filters altering the payload It is especially a problem with Lua filters, but it is important to disable the 0-copy forwarding if a filter alters the payload, or at least to be able to disable it. While the filter is registered on the data filtering, it is not an issue (and it is the common case) because, there is now way to fast-forward data at all. But it may be an issue if a filter decides to alter the payload and to unregister from data filtering. In that case, the 0-copy forwarding can be re-enabled in a hardly precdictable state. To fix the issue, a SC flags was added to do so. The HTTP compression filter set it and lua filters too if the body length is changed (via HTTPMessage.set_body_len()). Note that it is an issue because of a bad design about the HTX. Many info about the message are stored in the HTX structure itself. It must be refactored to move several info to the stream-endpoint descriptor. This should ease modifications at the stream level, from filter or a TCP/HTTP rules. This should be backported as far as 3.0. If necessary, it may be backported on lower versions, as far as 2.6. In that case, it must be reviewed and adapted. --- diff --git a/include/haproxy/stconn-t.h b/include/haproxy/stconn-t.h index 52fa3e88e..08326df91 100644 --- a/include/haproxy/stconn-t.h +++ b/include/haproxy/stconn-t.h @@ -206,6 +206,7 @@ enum sc_flags { SC_FL_EOS = 0x00040000, /* End of stream was reached (from down side to up side) */ SC_FL_HAVE_BUFF = 0x00080000, /* A buffer is ready, flag will be cleared once allocated */ + SC_FL_NO_FASTFWD = 0x00100000, /* disable data fast-forwarding */ }; /* This function is used to report flags in debugging tools. Please reflect diff --git a/src/flt_http_comp.c b/src/flt_http_comp.c index 43e320284..265e47280 100644 --- a/src/flt_http_comp.c +++ b/src/flt_http_comp.c @@ -515,6 +515,7 @@ set_compression_header(struct comp_state *st, struct stream *s, struct http_msg goto error; } + chn_prod(msg->chn)->flags |= SC_FL_NO_FASTFWD; return 1; error: diff --git a/src/hlua.c b/src/hlua.c index 9bb1fe930..7ac8fc604 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -7262,6 +7262,7 @@ __LJMP static int hlua_http_msg_set_body_len(lua_State *L) } success: + chn_prod(msg->chn)->flags |= SC_FL_NO_FASTFWD; lua_pushboolean(L, 1); return 1; diff --git a/src/stconn.c b/src/stconn.c index ddb56eff8..be6264477 100644 --- a/src/stconn.c +++ b/src/stconn.c @@ -604,6 +604,7 @@ static inline int sc_cond_forward_shut(struct stconn *sc) static inline int sc_is_fastfwd_supported(struct stconn *sc) { return (!(global.tune.no_zero_copy_fwd & NO_ZERO_COPY_FWD) && + !(sc->flags & SC_FL_NO_FASTFWD) && sc_ep_test(sc, SE_FL_MAY_FASTFWD_PROD) && sc_ep_test(sc_opposite(sc), SE_FL_MAY_FASTFWD_CONS) && sc_ic(sc)->to_forward);