Commit graph

20723 commits

Author SHA1 Message Date
Aurelien DARRAGON
2a2989bb23 CLEANUP: flt_http_comp: comp_state doesn't bother about the direction anymore
Some checks failed
Contrib / build (push) Has been cancelled
alpine/musl / gcc (push) Has been cancelled
VTest / Generate Build Matrix (push) Has been cancelled
Windows / Windows, gcc, all features (push) Has been cancelled
VTest / (push) Has been cancelled
no need to have duplicated comp_ctx and comp_algo for request vs response
in comp_state struct, because thanks to previous commit compression filter
is either oriented on the request or the response, and 2 distinct filters
are instanciated when we need to handle both requests and responses
compression.

Thus we can save us from duplicated struct members and related operations.
2026-03-06 13:55:41 +01:00
Aurelien DARRAGON
cbebdb4ba8 MEDIUM: flt_http_comp: split "compression" filter in 2 distinct filters
Existing "compression" filter is a multi-purpose filter that will try
to compress both requests and responses according to "compression"
settings, such as "compression direction".

One of the pre-requisite work identified to implement decompression
filter is that we needed a way to manually define the sequence of
enabled filters to chain them in the proper order to make
compression and decompression chains work as expected in regard
to the intended use-case.

Due to the current nature of the "compression" filter this was not
possible, because the filter has a combined action as it will try
to compress both requests and responses, and as we are about to
implement "filter-sequence" directive, we will not be able to
change the order of execution of the compression filter between
requests and responses.

A possible solution we identified to solve this issue is to split the
existing "compression" filter into 2 distinct filters, one which is
request-oriented, "comp-req", and another one which is response-oriented
"comp-res". This is what we are doing in this commit. Compression logic
in itself is unchanged, "comp-req" will only aim to compress the request
while "comp-res" will try to compress the response. Both filters will
still be invoked on request and responses hooks, but they only do their
part of the job.

From now on, to compress both requests and responses, both filters have
to be enabled on the proxy. To preserve original behavior, the "compression"
filter is still supported, what it does is that it instantiates both
"comp-req" and "comp-res" filters implicitly, as the compression filter is
now effectively split into 2 separate filters under the hood.

When using "comp-res" and "comp-req" filters explicitly, the use of the
"compression direction" setting is not relevant anymore. Indeed, the
compression direction is assumed as soon as one or both filters are
enabled. Thus "compression direction" is kept as a legacy option in
order to configure the "compression" generic filter.

Documentation was updated.
2026-03-06 13:55:31 +01:00
Aurelien DARRAGON
9549b05b94 MINOR: flt_http_comp: define and use proxy_get_comp() helper function
proxy_get_comp() function can be used to retrieve proxy->comp options or
allocate and initialize it if missing

For now, it is solely used by parse_compression_options(), but the goal is
to be able to use this helper from multiple origins.
2026-03-06 13:55:24 +01:00
Remi Tricot-Le Breton
5e14904fef BUG/MINOR: jwt: Missing 'jwt_tokenize' return value check
Some checks are pending
Contrib / build (push) Waiting to run
alpine/musl / gcc (push) Waiting to run
VTest / Generate Build Matrix (push) Waiting to run
VTest / (push) Blocked by required conditions
Windows / Windows, gcc, all features (push) Waiting to run
There was a "jwt_tokenize" call whose return value was not checked.

This was found by coverity and raised in GitHub #3277.
This patch can be backported to all stable branches.
2026-03-06 09:52:19 +01:00
Christopher Faulet
af6b9a0967 BUG/MINOR: backend: Don't get proto to use for webscoket if there is no server
In connect_server(), it is possible to have no server defined (dispatch mode
or transparent backend). In that case, we must be carefull to check the srv
variable in all calls involving the server. It was not perform at one place,
when the protocol to use for websocket is retrieved. This must not be done
when there is no server.

This patch should fix the first report in #3144. It must be backported to
all stable version.
2026-03-06 09:24:32 +01:00
Christopher Faulet
bfe5a2c3d7 BUG/MINOR: ssl-sample: Fix sample_conv_sha2() by checking EVP_Digest* failures
In sample_conv_sha2(), calls to EVP_Digest* can fail. So we must check
return value of each call and report a error on failure and release the
digest context.

This patch should fix the issue #3274. It should be backported as far as
2.6.
2026-03-06 09:07:16 +01:00
Olivier Houchard
5d02d33ee1 MINOR: stats: Add an option to disable the calculation of max counters
Add a new option, "stats calculate-max-counters [on|off]".
It makes it possible to disable the calculation of max counters, as they
can have a performance cost.
2026-03-05 15:39:42 +01:00
Olivier Houchard
1544842801 MINOR: proxies: Update beconn separately
Update beconn separately from the call to COUNTERS_UPDATE_MAX(), as soon
there will be an option to get COUNTERS_UPDATE_MAX() to do nothing, and
we still want beconn to be properly updated, as it is used for other
purposes.
2026-03-05 15:39:42 +01:00
Olivier Houchard
88bc2bdfc9 MINOR: listeners: Update the frequency counters separately when needed
Update the frequency counters that are exported to the stats page
outside of the call to COUNTERS_UPDATE_MAX(), so that they will
happen even if COUNTERS_UPDATE_MAX() ends up doing nothing.
2026-03-05 15:39:42 +01:00
Olivier Houchard
0087651128 MINOR: counters: Introduce COUNTERS_UPDATE_MAX()
Introduce COUNTERS_UPDATE_MAX(), and use it instead of using
HA_ATOMIC_UPDATE_MAX() directly.
For now it just calls HA_ATOMIC_UPDATE_MAX(), but will later be modified
so that we can disable max calculation.
This can be backported up to 2.8 if the usage of COUNTERS_UPDATE_MAX()
generates too many conflicts.
2026-03-05 15:39:42 +01:00
Frederic Lecaille
65d3416da5 CLEANUP: qpack: simplify length checks in qpack_decode_fs()
This patch simplifies the decoding loop by merging the variable-length
integer truncation check (len == -1) with the subsequent buffer
availability check (len < length).

This removes redundant code blocks and improves readability without
changing the decoding logic.

Note that the second removal is correct, as the check was duplicate and
unnecessary."
2026-03-05 15:42:02 +01:00
Christopher Faulet
7d48e80da5 MINOR: mux-fcgi: Use a dedicated function to resume streams eligible for sending
The same code was duplicated in fcgi_process_mux() and fcgi_sedn(). So let's
move it in a dedicated function.
2026-03-05 15:35:36 +01:00
Christopher Faulet
9b22f22858 BUG/MEDIUM: mux-fcgi: Use a safe loop to resume each stream eligible for sending
At the end of fcgi_send(), if the connection is not full anymore, we loop on
the send list to resume FCGI stream for sending. But a streams may be
removed from the this list during the loop. So a safe loop must be used.

This patch should be backported to all stable versions.
2026-03-05 15:35:36 +01:00
Christopher Faulet
25d6e65aae BUG/MAJOR: resolvers: Properly lowered the names found in DNS response
Names found in DNS responses are lowered to be compared. A name is composed
of several labels, strings precedeed by their length on one byte. For
instance:

 3www7haproxy3org

There is an bug when labels are lowered. The label length is not skipped and
tolower() function is called on it. So for label length in the range [65-90]
(uppercase char), 32 is added to the label length due to the conversion of a
uppercase char to lowercase. This bugs can lead to OOB read later in the
resolvers code.

The fix is quite obvious, the label length must be skipped when the label is
lowered.

Thank you to Kamil Frankowicz for having reported this.

This patch must be backported to all stable versions.
2026-03-05 15:35:31 +01:00
Christopher Faulet
96286b2a84 BUG/MAJOR: fcgi: Fix param decoding by properly checking its size
In functions used to decode a FCGI parameter, the test on the data length
before reading the parameter's name and value did not consider the offset
value used to skip already parsed data. So it was possible to read more data
than available (OOB read). To do so, a malicious FCGI server must send a
forged GET_VALUES_RESULT record containing a parameter with wrong name/value
length.

Thank you to Kamil Frankowicz for having reported this.

This patch must be backported to all stable versions.
2026-03-05 15:35:21 +01:00
Christopher Faulet
306931dfb1 BUG/MINOR: http-ana: Increment scf bytes_out value if an haproxy error is sent
When an HAproxy error is sent, we must not forget to increment bytes_out
value on the front stconn.

This patch must be backport to 3.3.
2026-03-05 15:34:47 +01:00
Christopher Faulet
4791501011 BUG/MINOR: sample: Fix sample to retrieve the number of bytes received and sent
There was an issue in the if/else statement in smp_fetch_bytes() function.
When req.bytes_in or req.bytes_out was requested, res.bytes_in was always
returned. It is now fixed.

This patch must be backported to 3.3.
2026-03-05 15:34:47 +01:00
Christopher Faulet
50fb37e5fe MINOR: stream: Display the currently running filter per channel in stream dump
Since the 3.1, when stream's info are dump, it is possible to print the
yielding filter on each channel, if any. It was useful to detect buggy
filter on spinning loop. But it is not possible to detect a filter consuming
too much CPU per-execution. We can see a filter was executing in the
backtrace reported by the watchdog, but we are unable to spot the specific
one.

Thanks to this patch, it is now possible. When a dump is emitted, the
running or yield filters on each channel are now displayed with their
current state (RUNNING or YIELDING).

This patch could be backported as far as 3.2 because it could be useful to
spot issues. But the filter API was slightly refactored in 3.4, so this
patch should be adapted.
2026-03-05 15:34:47 +01:00
Christopher Faulet
cd9f159210 MINOR: filters: Set last_entity when a filter fails on stream_start callback
On the stream, the last_entity should reference the last rule or the last
filter evaluated during the stream processing. However, this info was not
saved when a filter failed on strem_start callback function. It is now
fixed.

This patch could be backported as far as 3.1.
2026-03-05 15:34:47 +01:00
Christopher Faulet
3eadf887f7 MINOR: filters: Use filter API as far as poissible to break loops on filters
When the filters API was refactored to improve loops on filters, some places
were not updated (or not fully updated). Some loops were not relying on
resume_filter_list_break() while it was possible. So let's do so with this
patch.
2026-03-05 15:34:47 +01:00
Christopher Faulet
9f1e9ee0ed DEBUG: stream: Display the currently running rule in stream dump
Since the 2.5, when stream's info are dump, it is possible to print the
yielding rule, if any. It was useful to detect buggy rules on spinning
loop. But it is not possible to detect a rule consuming too much CPU
per-execution. We can see a rule was executing in the backtrace reported by
the watchdog, but we are unable to spot the specific rule.

Thanks to this patch, it is now possible. When a dump is emitted, the
running or yield rule is now displayed with its current state (RUNNING or
YIELDING).

This patch could be backported as far as 3.2 because it could be useful to
spot issues.
2026-03-05 15:34:47 +01:00
Christopher Faulet
4939f18ff7 MEDIUM: http-ana: Use the version of the opposite side for internal messages
When the response is send by HAProxy, from a applet or for the analyzers,
The request version is used for the response. The main reason is that there
is not real version for the response when this happens. "HTTP/1.1" is used,
but it is in fact just an HTX response. So the version of the request is
used.

In the same manner, when the request is sent from an applet (httpclient),
the response version is used, once available.

The purpose of this change is to return the most accurate version from the
user point of view.
2026-03-05 15:34:46 +01:00
Christopher Faulet
b2ba3c6662 MEDIUM: http-fetch: Rework how HTTP message version is retrieved
Thanks to previous patches, we can now rely on the version stored in the
http_msg structure to get the request or the response version.

"req.ver" and "res.ver" sample fetch functions returns the string
representation of the version, without the prefix, so "<major>.<minor>", but
only if the version is valid. For the response, "res.ver" may be added from
a health-check context, in that case, the HTX message is used.

"capture.req.ver" and "capture.res.ver" does the same but the "HTTP/" prefix
is added to the result. And "capture.res.ver" cannot be called from a
health-check.

To ease the version formatting and avoid code duplication, an helper
function was added. So these samples are now relying on "get_msg_version()".
2026-03-05 15:34:46 +01:00
Christopher Faulet
7bfb66d2b1 MINOR: http-ana: Save the message version in the http_msg structure
When the request or the response is received, the numerical value of the
message version is now saved. To do so, the field "vsn" was added in the
http_msg structure. It is an unsigned char. The 4 MSB bits are used for the
major digit and the 4 LSB bits for the minor one.

Of couse, the version must be valid. the HTX_SL_F_NOT_HTTP flag of the
start-line is used to be sure the version is valid. But because this flag is
quite new, we also take care the string representation of the version is 8
bytes length. 0 means the version is not valid.
2026-03-05 15:34:46 +01:00
Christopher Faulet
7a474855b4 BUG/MINOR: h1-htx: Be sure that H1 response version starts by "HTTP/"
When the response is parsed, we test the version to be sure it is
valid. However, the protocol was not tested. Now we take care that the
response version starts by "HTTP/", otherwise an error is returned.

Of course, it is still possible to by-pass this test with
"accept-unsafe-violations-in-http-response" option.

This patch could be backported to all stable versions.
2026-03-05 15:34:46 +01:00
Christopher Faulet
88765b69e0 MINOR: h1-htx: Reports non-HTTP version via dedicated flags
Now, when the HTTP version format is not strictly valid, flags are set on
the h1 parser and the HTX start-line. H1_MF_NOT_HTTP is set on the H1 parser
and HTX_SL_F_NOT_HTTP is set on the HTX start-line. These flags were
introduced to avoid parsing again and again the version to know if it is a
valid version or not, escpecially because it is most of time valid.
2026-03-05 15:34:46 +01:00
Christopher Faulet
e6a8ef5521 BUG/MINOR: hlua: Properly enable/disable receives for TCP applets
From a lua TCP applet, in functions used to retrieve data (receive,
try_receive and getline), we must take care to disable receives when data
are returned (or on failure) and to restart receives when these functions
are called again. In addition, when an applet execution is finished, we must
restart receives to properly drain the request.

This patch should be backported to 3.3. On older version, no bug was
reported so we can wait a report first.
2026-03-05 15:34:46 +01:00
Christopher Faulet
7fe1a92bb3 BUG/MEDIUM: hlua: Fix end of request detection when retrieving payload
When the lua HTTP applet was refactored to use its own buffers, a bug was
introduced in receive() and getline() function. We rely on HTX_FL_EOM flag
to detect the end of the request. But there is nothing preventing extra
calls to these function, when the whole request was consumed. If this
happens, the call will yield waiting for more data with no way to stop it.

To fix the issue, APPLET_REQ_RECV flag was added to know the whole request
was received.

This patch should fix #3293. It must be backported to 3.3.
2026-03-05 15:34:46 +01:00
Christopher Faulet
a779d0d23a BUG/MINOR: hlua: Properly enable/disable line receives from HTTP applet
From a lua HTTP applet, in the getline() function, we must take care to
disable receives when a line is retrieved and to restart receives when the
function is called again. In addition, when an applet execution is finished,
we must restart receives to properly drain the request.

This patch could help to fix #3293. It must be backported to 3.3. On older
version, no bug was reported so we can wait a report first. But in that
case, hlua_applet_http_recv() should also be fixed (on 3.3 it was fixed
during the applets refactoring).
2026-03-05 15:34:46 +01:00
Frederic Lecaille
0a02acecf3 BUG/MEDIUM: qpack: correctly deal with too large decoded numbers
Same fix as this one for hpack:

	7315428615 ("BUG/MEDIUM: hpack: correctly deal with too large decoded numbers")

Indeed, the encoding of integers for QPACK is the same as for HPACK but for 64 bits
integers.

Must be backported as far as 2.6.
2026-03-05 15:02:02 +01:00
Frederic Lecaille
cdcdc016cc BUG/MINOR: quic: fix OOB read in preferred_address transport parameter
This bug impacts only the QUIC backend. A QUIC server does receive
a server preferred address transport parameter.

In quic_transport_param_dec_pref_addr(), the boundary check for the
connection ID was inverted and incorrect. This could lead to an
out-of-bounds read during the following memcpy.

This patch fixes the comparison to ensure the buffer has enough input data
for both the CID and the mandatory Stateless Reset Token.

Thank you to Kamil Frankowicz for having reported this.

Must be backported to 3.3.
2026-03-05 15:02:02 +01:00
Frederic Lecaille
54b614d2b5 BUG/MINOR: qpack: fix 1-byte OOB read in qpack_decode_fs_pfx()
In qpack_decode_fs_pfx(), if the first qpack_get_varint() call
consumes the entire buffer, the code would perform a 1-byte
out-of-bounds read when accessing the sign bit via **raw.

This patch adds an explicit length check at the beginning of
qpack_get_varint(), which systematically secures all other callers
against empty inputs. It also adds a necessary check before the
second varint call in qpack_decode_fs_pfx() to ensure data is still
available before dereferencing the pointer to extract the sign bit,
returning QPACK_RET_TRUNCATED if the buffer is exhausted.

Thank you to Kamil Frankowicz for having reported this.

Must be backported as far as 2.6.
2026-03-05 15:02:02 +01:00
Frederic Lecaille
e38b86e72c BUG/MAJOR: qpack: unchecked length passed to huffman decoder
A call to huffman decoder function (huff_dec()) is made from qpack_decode_fs()
without checking the buffer length passed to this function, leading to OOB read
which can crash the process.

Thank you to Kamil Frankowicz for having reported this.

Must be backport as far as 2.6.
2026-03-05 15:02:02 +01:00
Willy Tarreau
7315428615 BUG/MEDIUM: hpack: correctly deal with too large decoded numbers
The varint hpack decoder supports unbounded numbers but returns 32-bit
results. This means that possible truncation my happen on some field
lengths or indexes that would be emitted as quantities that do not fit
in a 32-bit number. The final value will also depend on how the left
shift operation behaves on the target architecture (e.g. whether bits
are lost or used modulo 31). This could lead to a desynchronization of
the HPACK stream decoding compared to what an external observer would
see (e.g. from a network traffic capture). However, there isn't any
impact between streams, HPACK is performed at the connection level,
not at the stream level, so no stream may try to leverage this
limitation to have any effect on another one.

For the fix, instead of adding checks everywhere in the loop and for
the final stage, let's rewrite the decoder to compare the read value
to a max value that is shifted by 7 bits for every 7 bits read. This
allows a sender to continue to emit zeroes for higher bits without
being blocked, while detecting that a received value would overflow.
The loop is now simpler as it deals both with values with the higher
bit set and the final ones, and stops once the final value was recorded.

A test on non-zero before performing the shift was added to please
ubsan, though in practice zero shifted by any quantity remains zero.
But the test is cheap so that's OK.

Thanks to Guillaume Meunier, Head of Vulnerability Operations Center
France at Orange Cyberdefense, for reporting this bug.

This should be backported to all stable versions.
2026-03-05 14:33:21 +01:00
Amaury Denoyelle
b1441c6440 MINOR: quic: use server cache for ALPN on BE side
Some checks failed
Contrib / build (push) Has been cancelled
alpine/musl / gcc (push) Has been cancelled
VTest / Generate Build Matrix (push) Has been cancelled
Windows / Windows, gcc, all features (push) Has been cancelled
VTest / (push) Has been cancelled
On the backend side, QUIC MUX may be started preemptively before the
ALPN negotiation. This is useful notably for 0-RTT implementation.

However, this was a source of crashes. ALPN was expected to be retrieved
from the server cache, however QUIC MUX still used the ALPN from the
transport layer. This could cause a crash, especially when several
connections runs in parallel as the server cache is shared among
threads.

Thanks to the previous patch which reworks QUIC MUX init, this solution
can now be fixed. Indeed, if conn_get_alpn() is not successful, MUX can
look at the server cache again to use the expected value.

Note that this could still prevent the MUX to work as expected if the
server cache is resetted between connect_server() and MUX init. Thus,
the ultimate solution would be to copy the cached ALPN into the
connection. This problem is not specific to QUIC though, and must be
fixed in a separate patch.
2026-03-03 16:23:03 +01:00
Amaury Denoyelle
940e1820f6 MEDIUM: quic/mux-quic: adjust app-ops install
This patch reworks the installation of app-ops layer by QUIC MUX.
Previously, app_ops field was stored directly into the quic_conn
structure. Then the MUX reused it directly during its qmux_init().

This patch removes app_ops field from quic_conn and replaces it with a
copy of the negotiated ALPN. By using quic_alpn_to_app_ops(), it ensures
it remains compatible with a known application layer.

On the MUX layer, qcc_install_app_ops() now uses the standard
conn_get_alpn() to retrieve the ALPN from the transport layer. This is
done via the newly defined <get_alpn> QUIC xprt callback.

This new architecture should be cleaner as it better highlights the
responsibility of each layers in the ALPN/app negotiation.
2026-03-03 16:22:57 +01:00
Amaury Denoyelle
9c7cf1c684 MINOR: mux-quic: add function for ALPN to app-ops conversion
Extract the conversion from ALPN to qcc_app_ops type from quic_conn
source file into QUIC MUX. The newly created function is named
quic_alpn_to_app_ops(). This will serve as a central point to identify
which ALPNs are currently supported in our QUIC stack.

This patch is purely a small refactoring. It will be useful for the next
one which rework MUX app-ops layer init. The current cleanup allows
notably to remove H3/hq-interop headers from quic_conn source file.
2026-03-03 16:20:16 +01:00
Amaury Denoyelle
4120faf289 MINOR: quic/h3: reorganize stream reject after MUX closure
The QUIC MUX layer is closed after its transport counterpart. This may
be necessary then to reject any new streams opened by the remote peer.
This operation is dependent however from the application protocol.

Previously, a function qc_h3_request_reject() was directly implemented
in quic_conn source file for use when HTTP/3 was previously negotiated.
However, this solution was not evolutive and broke layering.

This patch introduces a new proper separation with a <strm_reject>
callback defined in quic_conn structure. When set, it will be used to
preemptively close any new stream. QUIC MUX is responsible to set it
just before its closure.

No functional change. This patch is purely a refactoring with a better
architecture design. Especially, H3 specific code from transport layer
is now completely removed.
2026-03-03 16:19:13 +01:00
Amaury Denoyelle
58830990d0 MINOR: quic: use signed char type for ALPN manipulation
In most of haproxy code, ALPN is used as a signed char pointer. In QUIC
code instead, it is manipulated as unsigned.

Unifies this by using signed type in QUIC code. This allows to remove a
bunch of unnecessary casts.
2026-03-03 16:11:58 +01:00
Amaury Denoyelle
f41e684e9a BUG/MINOR: hlua: fix return with push nil on proxy check
Some checks are pending
Contrib / build (push) Waiting to run
alpine/musl / gcc (push) Waiting to run
VTest / Generate Build Matrix (push) Waiting to run
VTest / (push) Blocked by required conditions
Windows / Windows, gcc, all features (push) Waiting to run
hlua_check_proxy() may now return NULL if the target proxy instance has
been flagged for deletion. Thus, proxies method have been adjusted and
may push nil to report such case.

This patch fixes these error paths. When nil is pushed, 1 must be
returned instead of 0. This represents the count of pushed values on the
stack which can be retrieved by the caller.

No need to backport.
2026-03-03 08:45:27 +01:00
Amaury Denoyelle
712055f2f8 MEDIUM: proxy: implement backend deletion
This patch finalizes "del backend" handler by implementing the proper
proxy deletion.

After ensuring backend deletion can be performed, several steps are
executed. First, any watcher elements are updated to point on the next
proxy instance. The backend is then removed from ID and name global
trees and is finally detached from proxies_list.

Once the backend instance is removed from proxies_list, the backend
cannot be found by new elements. Thread isolation is lifted and
proxy_drop() is called, which will purge the proxy if its refcount is
null. Thanks to recently introduced PROXIES_DEL_LOCK, proxy_drop() is
thread safe.
2026-03-02 14:14:05 +01:00
Amaury Denoyelle
6145f52d9c MINOR: proxy: use atomic ops for default proxy refcount
Default proxy refcount <def_ref> is used to comptabilize reference on a
default proxy instance by standard proxies. Currently, this is necessary
when a default proxy defines TCP/HTTP rules or a tcpcheck ruleset.

Transform every access on <def_ref> so that atomic operations are now
used. Currently, this is not strictly needed as default proxies
references are only manipulated at init or deinit in single thread mode.
However, when dynamic backends deletion will be implemented, <def_ref>
will be decremented at runtime also.
2026-03-02 14:14:05 +01:00
Amaury Denoyelle
f64aa036d8 MEDIUM: proxy: add lock for global accesses during default free
This patch is similar to the previous one, but this time it deals with
functions related to defaults proxies instances. Lock PROXIES_DEL_LOCK
is used to protect accesses on global collections.

This patch will be necessary to implement dynamic backend deletion, even
if defaults won't be use as direct target of a "del backend" CLI.
However, a backend may have a reference on a default instance. When the
backend is freed, this references is released, which can in turn cause
the freeing of the default proxy instance. All of this will occur at
runtime, outside of thread isolation.
2026-03-02 14:10:46 +01:00
Amaury Denoyelle
f58b2698ce MEDIUM: proxy: add lock for global accesses during proxy free
Define a new lock with label PROXIES_DEL_LOCK. Its purpose is to protect
operations performed on global lists or trees while a proxy is freed.

Currently, this lock is unneeded as proxies are only freed on
single-thread init or deinit. However, with the incoming dynamic backend
deletion, this operation will be also performed at runtime, outside of
thread isolation.
2026-03-02 14:09:25 +01:00
Amaury Denoyelle
a7d1c59a92 MINOR: proxy: add comment for defaults_px_ref/unref_all()
Write documentation for functions related to default proxies instances.
2026-03-02 14:08:30 +01:00
Amaury Denoyelle
98c8c5e16e MINOR: cli: implement wait on be-removable
Implement be-removable argument to CLI wait. This is implemented via
be_check_for_deletion() invokation, also used by "del backend" handler.

The objective is to test whether a backend instance can be removed. If
this is not the case, the command may returns immediately if the target
proxy is incompatible with dynamic removal or if a user action is
required. Else, the command will wait until the temporary restriction is
lifted.
2026-03-02 14:08:30 +01:00
Amaury Denoyelle
5ddfbd4b03 MINOR: server: mark backend removal as forbidden if QUIC was used
Currenly, quic_conn on the backend side may access their parent proxy
instance during their lifetime. In particular, this is the case for
counters update, with <prx_counters> field directly referencing a proxy
memory zone.

As such, this prevents safe backend removal. One solution would be to
check if the upper connection instance is still alive, as a proxy cannot
be removed if connection are still active. However, this would
completely prevent proxy counters update via
quic_conn_prx_cntrs_update(), as this is performed on quic_conn release.

Another solution would be to use refcount, or a dedicated counter on the
which account for QUIC connections on a backend instance. However,
refcount is currently only used by short-term references, and it could
also have a negative impact on performance.

Thus, the simplest solution for now is to disable a backend removal if a
QUIC server is/was used in it. This is considered acceptable for now as
QUIC on the backend side is experimental.
2026-03-02 14:08:30 +01:00
Amaury Denoyelle
053887cc98 MINOR: proxy: prevent backend deletion if server still exists in it
Ensure a backend instance cannot be removed if there is still server in
it. This is checked via be_check_for_deletion() to ensure "del backend"
cannot be executed. The only solution is to use "del server" to remove
on the servers instances.

This check only covers servers not yet targetted via "del server". For
deleted servers not yet purged (due to their refcount), the proxy
refcount is incremented but this does not block "del backend"
invokation.
2026-03-02 14:08:30 +01:00
Amaury Denoyelle
7f725f0754 MINOR: proxy: prevent deletion of backend referenced by config elements
Define a new proxy flag PR_FL_NON_PURGEABLE. This is used to mark every
proxy instance explicitely referenced in the config. Such instances
cannot be deleted at runtime.

Static use_backend/default_backend rules are handled in
proxy_finalize(). Also, sample expression proxy references are protected
via smp_resolve_args().

Note that this last case also incidentally protects any proxies
referenced via a CLI "set var" expression. This should not be the case
as in this case variable value is instantly resolved so the proxy
reference is not needed anymore. This also affects dynamic servers.
2026-03-02 14:08:30 +01:00
Amaury Denoyelle
7bf3020952 MINOR: proxy: prevent backend removal when unsupported
Prevent removal of a backend which relies on features not compatible
with dynamic backends. This is the case if either dispatch or
transparent option is used, or if a stick-table is declared.

These limitations are similar to the "add backend" ones.
2026-03-02 14:08:30 +01:00