]> git.kaiwu.me - haproxy.git/log
haproxy.git
3 months agoMINOR: hlua: Use flags of HTX blocks to detect EOM from an HTTP applet 20260615-htx-flags
Christopher Faulet [Tue, 21 Jul 2026 09:58:22 +0000 (11:58 +0200)]
MINOR: hlua: Use flags of HTX blocks to detect EOM from an HTTP applet

When we try to get request's data from an HTTP applet, instead of testing
HTX_FL_HAS_EOM flag on the message, we now rely on the flags of HTX blocks.
The logic remains the same, when all DATA blocks were consumed, we consider
the request as fully received. It may be when the blocks with the EOM flag
was removed or because a trailer was seen.

3 months agoMINOR: stats-html: Detect a complete request by testing flags on the tail bloc
Christopher Faulet [Thu, 9 Jul 2026 14:17:46 +0000 (16:17 +0200)]
MINOR: stats-html: Detect a complete request by testing flags on the tail bloc

In the HTTP stats applet, when a POST is received, instead of testing the
HTX_FL_HAS_EOM flag on the message itself, we are now relying on the tail
bloc to know if the end of the request was received or not, by testing its
flags.

3 months agoMINOR: mux-fcgi: Use flags of HTX blocks to detect end of message during sending
Christopher Faulet [Thu, 9 Jul 2026 13:06:41 +0000 (15:06 +0200)]
MINOR: mux-fcgi: Use flags of HTX blocks to detect end of message during sending

When a message is sent, the end of the message is now detected by testing
flags of each HTX blocs. Otherwise, the logic remains mostly unchanged. The
way the end of the message is handled in fcgi_strm_send_stdin() was modified
a bit but the result is the same. Now, we rely on a variable to decide, at
the end, if an empty STDIN record should be sent or not. This avoid an extra
test on the HTX message to be sure it is empty.

3 months agoMINOR: mux-h1: Use flags of HTX blocks to detect end of message during sending
Christopher Faulet [Thu, 9 Jul 2026 12:52:58 +0000 (14:52 +0200)]
MINOR: mux-h1: Use flags of HTX blocks to detect end of message during sending

When a message is sent, the end of the message is now detected by testing
flags of each HTX blocs. Otherwise, the logic remains mostly unchanged. A
test in h1_make_eoh() was slightly changed but it should be harmless.
Especially because HTX_BLK_FL_EOM cannot be set on the EOH block if it is
followed by something else than tunneled data, which is unexpected and
invalid in that case. All conditions to establish a tunnel at this stage
were already evaluated. And if any, the error will be detected in
h1_make_trailers() function.

3 months agoMINOR: mux-h2: Use flags of HTX blocks to detect end of message during sending
Christopher Faulet [Thu, 9 Jul 2026 09:40:39 +0000 (11:40 +0200)]
MINOR: mux-h2: Use flags of HTX blocks to detect end of message during sending

When a message is sent, the end of the message is now detected by testing
flags of each HTX blocs. Otherwise, most of the logic remains unchanged. The
only difference is the detection of the end of the message when headers are
sent (back or front). Now, it is be possible to detect the EOM when the
stream is already closed and H2_SF_MORE_HTX_DATA may be removed while it was
untouched before. But it is not a big deal because this flag is only tested
when a shutdown is performed on the stream. So removing it for an already
closed stream is a no-op.

3 months agoMINOR: fcgi-app: Stop on last HTX block when getting the payload size
Christopher Faulet [Wed, 8 Jul 2026 15:12:27 +0000 (17:12 +0200)]
MINOR: fcgi-app: Stop on last HTX block when getting the payload size

In the loop counting all DATA block to be able to add a "Content-length:"
header in the FCGI response, we now check flags on the HTX block to know if
it is the last one of the message or not. If HTX_BLK_FL_EOM flag is set, it
means we can stop.

3 months agoMINOR: compression: Rely on HTX block flags to detect the end of message
Christopher Faulet [Wed, 8 Jul 2026 15:06:04 +0000 (17:06 +0200)]
MINOR: compression: Rely on HTX block flags to detect the end of message

Thanks to previous patches, instead of testing HTX_FL_HAS_EOM flag to detect
the end of the message, we now rely on the flags on the HTX block.

3 months agoMEDIUM: htx: Add HTX_BLK_FL_EOM flag and set it on last block of the message
Christopher Faulet [Wed, 8 Jul 2026 14:46:12 +0000 (16:46 +0200)]
MEDIUM: htx: Add HTX_BLK_FL_EOM flag and set it on last block of the message

HTX_BLK_FL_EOM flag was introduced to be set on the last block of an HTX
message. It must be set on the tail block when the HTX_FL_HAS_EOM is set.
Now, only the HTX API must set these flags by hand. From outside of the HTX
API, htx_set_eom() function must be used.

A BUG_ON() was added to unsure the flag is added on valid blocks. It is possible
to add it on EOH, EOT and DATA blocks only.

3 months agoMAJOR: htx: Rename HTX_FL_EOM into HTX_FL_HAS_EOM
Christopher Faulet [Thu, 23 Jul 2026 13:03:22 +0000 (15:03 +0200)]
MAJOR: htx: Rename HTX_FL_EOM into HTX_FL_HAS_EOM

It is just a flag renaming but it is an API breakage and this could generate
compilation errors for all external modules relying on the HTX API. This
change was performed to force to review all code using HTX to be sure this
flag is never set by hand from outside. Indeed, htx_set_eom() function must
always be used now.

3 months agoMAJOR: htx: Use htx_set_eom() instead of setting HTX_FL_EOM by hand
Christopher Faulet [Wed, 8 Jul 2026 14:13:24 +0000 (16:13 +0200)]
MAJOR: htx: Use htx_set_eom() instead of setting HTX_FL_EOM by hand

The function htx_set_eom() takes care to the HTX_FL_EOM on the HTX message,
by first adding a EOT block if the message is empty. So let's use it
wherever possible.

This commit is tagged as MAJOR because it is an API change.

3 months agoMINOR: htx: Add support for flags on HTX blocks
Christopher Faulet [Wed, 8 Jul 2026 13:23:11 +0000 (15:23 +0200)]
MINOR: htx: Add support for flags on HTX blocks

In the commit 32b51cdf3 ("BUG/MINOR: config: reject configs using HTTP with
bufsize >= 256 MB"), the maximum possible size for buffers is limited to 256
MB. So, on HTX side, it means a bloc cannot have a relative address higher
than this value. So on the 32-bits integer used to store the relative block
address, only 28 bits can be used, and 4 bits remains unused.

So these 4 bits were reused to store flags on block themselves. In this
patch, the support for these flags is introduced and the HTX API was adapted
to deal with it.

3 months agoMEDIUM: htx: Insert headers and trailers before corresponding end-of block
Christopher Faulet [Wed, 8 Jul 2026 13:15:53 +0000 (15:15 +0200)]
MEDIUM: htx: Insert headers and trailers before corresponding end-of block

htx_add_header() and htx_add_trailer() were updated to automatically insert
the block at the right place, just before the corresponding end-of block.
Indeed, it is invalid, unexepected and probably unsupported to insert a
header after the EOH block without moving it. So it is easier to handle it
in HTX function directly.

It means that http_add_header() was simplified.

3 months agoMEDIUM: htx/tree-wide: Remove tests on HTX_BLK_UNUSED when possible
Christopher Faulet [Thu, 23 Jul 2026 09:05:53 +0000 (11:05 +0200)]
MEDIUM: htx/tree-wide: Remove tests on HTX_BLK_UNUSED when possible

Thanks to previous changes, it is possible to remove all tests on
HTX_BLK_UNUSED outside of the HTX API. Indeed, because htx_get_*_blk() and
htx_remove_blk() functions are now skipping automatically unused blocks, we
are sure to never get such blocks from outside.

3 months agoMEDIUM: htx: Skip UNUSED blocs when getting previous,next and first blocks
Christopher Faulet [Wed, 8 Jul 2026 08:38:12 +0000 (10:38 +0200)]
MEDIUM: htx: Skip UNUSED blocs when getting previous,next and first blocks

htx_get_prev_blk(), htx_get_next_blk() and htx_get_first_blk() functions
were modified to automatically skip UNUSED blocks. So now, a valid block or
NULL is returned.  In addition, htx_remove_blk() was adapted accordingly to
also skip UNUSED blocks.

Thanks to this change, the loops on HTX messages could be simplified by
removing test on UNUSED blocks, while it remains harmless.

3 months agoMINOR: mux-h1: loop on HTX blocks using _blk() functions to look for WS key
Christopher Faulet [Thu, 23 Jul 2026 08:58:58 +0000 (10:58 +0200)]
MINOR: mux-h1: loop on HTX blocks using _blk() functions to look for WS key

In h1_search_websocket_key() function, instead of looping on the block
position, we now use functions returning a blocks. This commit is mandatory
for next changes.

3 months agoREORG: htx: Move functions to deal with first block after ones about next block
Christopher Faulet [Thu, 23 Jul 2026 08:35:06 +0000 (10:35 +0200)]
REORG: htx: Move functions to deal with first block after ones about next block

functions htx_get_first_* were moved after htx_get_next_*() ones. There is no
change here but it is mandatory for the next commit. htx_get_first_blk() will
rely on htx_get_next().

3 months agoDOC: htx: Fix comment of htx_expect_more() function
Christopher Faulet [Wed, 8 Jul 2026 08:30:04 +0000 (10:30 +0200)]
DOC: htx: Fix comment of htx_expect_more() function

The comment of htx_expect_more() was inverted from what the function really
does. So let's fix it.

3 months agoCLEANUP: htx: Remove ref to EOM block on HTX_FL_EOM flag comment
Christopher Faulet [Wed, 8 Jul 2026 08:27:27 +0000 (10:27 +0200)]
CLEANUP: htx: Remove ref to EOM block on HTX_FL_EOM flag comment

EOM block was removed since a while, so let's adapt the HTX_FL_EOM flag
comment.

3 months agoMINOR: htx: Remove htx_xfer_blks function
Christopher Faulet [Wed, 8 Jul 2026 08:23:11 +0000 (10:23 +0200)]
MINOR: htx: Remove htx_xfer_blks function

This function was deprecated during the 3.4 dev cycle and is no longer
used. So let's remove it.

3 months agoMINOR: httpclient: Don't manually set HTX_FL_EOM flag after calling htx_xfer()
Christopher Faulet [Wed, 8 Jul 2026 14:22:58 +0000 (16:22 +0200)]
MINOR: httpclient: Don't manually set HTX_FL_EOM flag after calling htx_xfer()

The htx_xfer() function already takes care to copy HTX_FL_EOM flag when it
is required. So there is no reason to still do it in the HTTP client I/O
handler function.

3 months agoBUG/MEDIUM: htx: Don't reset flags when source must be preserved during transfer
Christopher Faulet [Wed, 22 Jul 2026 08:59:57 +0000 (10:59 +0200)]
BUG/MEDIUM: htx: Don't reset flags when source must be preserved during transfer

When htx_xfer() is called with HTX_XFER_KEEP_SRC_BLKS flag, to preserve
blocks from the source HTX message, the source flags must not be reset at
the end of the transfer.

This bug can be triggered with L7-retries are configured with small
buffers. In that case, the HTX_FL_EOM flag is removed from the request
fowarded to the backend multiplexer.

This patch must be backported to 3.4.

3 months agoBUG/MINOR: hlua: Always return nil if there is no data to dup for HTTP messages
Christopher Faulet [Tue, 21 Jul 2026 12:06:26 +0000 (14:06 +0200)]
BUG/MINOR: hlua: Always return nil if there is no data to dup for HTTP messages

In _hlua_http_msg_dup(), we must always return nil if no data was
duplicated. The fact the end of the message was reached or not should not
interfere. So let's remove the extra condition on HTX_FL_EOM flag and always
return nil if no data was duplicated.

This patch could be backported to all supported versions.

3 months agoMINOR: mux-h1: Use htx version to send default low-level errors
Christopher Faulet [Fri, 24 Jul 2026 09:47:36 +0000 (11:47 +0200)]
MINOR: mux-h1: Use htx version to send default low-level errors

When an error was returned by the H1 multiplexer, the raw version was used
for default low-level errors. It is not really an issue, but it is more
consitent to use the HTX version. This way, by default, header names for
such errors are now sent in lower case. And the case of header names can
still be adjusted if necessary, thanks to the previous fix.

It is not really a bug, there is no reason to backport it, except if someone
ask for it.

3 months agoMINOR: mux-h1: Lower the case for Sec-Websocket-* headers when manually added
Christopher Faulet [Fri, 24 Jul 2026 09:39:48 +0000 (11:39 +0200)]
MINOR: mux-h1: Lower the case for Sec-Websocket-* headers when manually added

During the message formatting, if websocket handshake key must be added by
the mux itself, the corresponding headers were not inserted in lowercase as
expected. It is not really an issue but it is not consistant with processing
on other headers. So let's fix it.

3 months agoBUG/MEDIUM: mux-h1: Always adjust case for all outgoing headers as expected
Christopher Faulet [Fri, 24 Jul 2026 09:08:15 +0000 (11:08 +0200)]
BUG/MEDIUM: mux-h1: Always adjust case for all outgoing headers as expected

In HTX, all header names are converted to lowercase. However, some legacy H1
applications are still sensitive to the header names case.  For this
purpose, it is possible to provide a map to automatically adjust the case of
header names. While it is performed for most responses, it is not true for
the low-level errors triggered during requests parsing. It the same ways,
the case of "Sec-Websocket-Key" a "Sec-Websocket-Accept" headers were
adjusted as expected.

To fix this issue the h1-htx API was slightly changed. Now the map used to
adjust the case of header names, if any, is passed to the function
responsible to format the headers. In the H1 multiplexer, the map is first
retrieved then passed as argument to h1_format_htx_hdr() and
h1_format_htx_msg() functions. A NULL pointer is passed if no rewrite must
be performed.

In the H1 multiplexer, h1_adjust_case_outgoing_hdr() was replaced by
h1_get_hdrs_map().

All other calls to h1_format_htx_hdr() were adapted to use a NULL pointer
(httpclient, http-fetch).

This patch relies on "REORG: h1-htx: Move h1 headers map in h1-htx". Both
commits should be backported to all supported versions.

This should fix the issue #3448.

3 months agoREORG: h1-htx: Move h1 headers map in h1-htx
Christopher Faulet [Fri, 24 Jul 2026 09:02:38 +0000 (11:02 +0200)]
REORG: h1-htx: Move h1 headers map in h1-htx

The map used to adjust the H1 headers case was moved in h1-htx part. For
this purpose h1_htx-t.h file was added and h1_hdrs_map and h1_hdr_entry
structures were moved into this file.

This commit is mandatory for the next fix.

3 months agoMINOR: halog: Add support filtering on header capture values using -hdr-match
Tim Duesterhus [Wed, 15 Jul 2026 15:14:00 +0000 (17:14 +0200)]
MINOR: halog: Add support filtering on header capture values using -hdr-match

This patch extends the existing support for printing captured header fields
(`-hdr`) by a new filter (`-hdr-match`) that only processes lines where the
given capture has a specific value. It works together with all existing filters
and output formats.

The full syntax is `-hdr-match <block>:<field>=<value>`, where <block> and <field>
work just like `-hdr` and `<value>` is an exact string match:

Example:

    capture request  header a len 50
    capture request  header b len 50
    capture request  header c len 50
    capture response header d len 50
    capture response header e len 50
    capture response header f len 50

- `-hdr-match 1:1=foo` will filter for requests where `a` is equal to "foo".
- `-hdr-match "2:3=foo bar"` will filter for requests where `f` is equal to
  "foo bar".

The chosen syntax leaves future scope for allowing `<block>:<field>*<value>`
for substring matches and `<block>:<field>^<value>` for prefix matches without
introducing a breaking change.

3 months agoCLEANUP: halog: Clean up naming for variables related to `-hdr` processing
Tim Duesterhus [Wed, 15 Jul 2026 15:10:36 +0000 (17:10 +0200)]
CLEANUP: halog: Clean up naming for variables related to `-hdr` processing

This is in preparation of allowing to filter based on the values of a header
capture by having a common "capture" prefix for variables related to extracting
header captures.

3 months agoMINOR: halog: Add reusable function to extract the value of header captures
Tim Duesterhus [Wed, 15 Jul 2026 15:09:21 +0000 (17:09 +0200)]
MINOR: halog: Add reusable function to extract the value of header captures

This is in preparation of allowing to filter based on the values of a header
capture. No functional change is expected.

3 months agoDEBUG: fd: catch access attempts to closed FDs
Willy Tarreau [Fri, 24 Jul 2026 09:31:12 +0000 (11:31 +0200)]
DEBUG: fd: catch access attempts to closed FDs

Certain rare bugs may cause an fd_want_recv() or any of the other
operations being done on a closed FD. This triggers a BUG_ON() on the
next call trying to insert the FD but it's too late to figure when
this happened. Let's just add some BUG_ON_HOT() to detect an attempt
to modify the state of a closed FD so that the culprit is detected.

It will only be enabled with DEBUG_STRICT=2, since by design this may
never happen so it's not needed to enable it in default builds. It was
verified not to trigger on various tests.

3 months agoOPTIM: tools: keep a cache of recent localtime() and gmtime()
Willy Tarreau [Thu, 23 Jul 2026 13:53:56 +0000 (15:53 +0200)]
OPTIM: tools: keep a cache of recent localtime() and gmtime()

The log subsystem already keeps a cache of the latest generated time
header to avoid paying the price of snprintf() notably. However, as
reported in GH issue #3444 by @zino7825, localtime() and gmtime() are
affected (at least in glibc) by a tzset_lock held during the call to
__tz_convert(), which ruins performance when logging time such as the
accept date. Even just "option httplog" sees its performance divided
by two on a 64-core machine, from 1.8M to 910k req/s.

The following config even goes down to 388k req/s:

  defaults
    mode http

  frontend fe
    bind :8001
    log 127.0.0.1:5514 len 8192 local0
    log-format '{"t":"%t","tr":"%tr","ci":"%ci"}'
    http-request set-var(txn.now) date(),ltime("%Y-%m-%dT%H:%M:%S")
    option httplog
    default_backend be

  backend be
    server s1 198.18.0.31:8000

With native_queued_spin_lock_slowpath() taking 80% of the CPU, showing
that it's also involved in futexes.

This patch, suggested by @zino7825, implements a very simple thread-
local cache for the 4 previously seen values for both localtime() and
gmtime(). The cache is visited in reverse order so that most recently
updated values are visited first (the most likely ones to be used). A
test with the config above and 12.8M requests showed 38.4M lookups with
only 12k total misses. A more naive scan from 0 to N caused 59M misses.
With this patch, all variants of the tests above remain at native speed
without native_queued_spin_lock_slowpath() being noticeable at all. If
for any reason a log format was so complex that it needed more stored
local times, it would be easy to change the cache size by redefining
TIME_CACHE_BITS.

The functions are no longer inlined, they were moved to tools.c since
we'd rather avoid loops and complex constructs in inlined functions.

Co-authored-by: Jinho Kong <zino7825@users.noreply.github.com>
3 months agoOPTIM/MEDIUM: proxy/server: avoid server list reordering on startup
Amaury Denoyelle [Wed, 22 Jul 2026 13:51:29 +0000 (15:51 +0200)]
OPTIM/MEDIUM: proxy/server: avoid server list reordering on startup

Prior to this patch, each server parsed from the configuration was added
at the front of the proxy list. The list was then reversed once parsing
is finished to reflect the configuration order.

Now that proxy servers list has been converted to a doubly linked list,
there is no more a reason for this. Thus, this patch changes the server
insertion order on configuration parsing : this is now performed
directly at the end of the proxy list. Reversal is unnecessary and has
been removed, so post-config performance may be slightly improved.

Peers parsing is the only module which relies on the order insertion.
Thus it has been adapted to now use the last server in its proxy.

3 months agoMAJOR: proxy: convert server list to a doubly linked struct list
Amaury Denoyelle [Wed, 22 Jul 2026 13:01:59 +0000 (15:01 +0200)]
MAJOR: proxy: convert server list to a doubly linked struct list

Servers are stored in a list in their parent proxy. Prior to this patch,
this list was singly linked.

This patch converts the proxy server list to a doubly linked struct
list. Server <next> pointer is replaced by a struct list <el_px> attach
point.

The main benefit from this patch is that it removes the bottleneck
performance for add and delete server operations at runtime. As with
main proxies list conversion, this is labelled as major as it is an API
change.

Most of the changes are straightforward : for/while statements are
replaced by list_for_each_entry() macros. LIST_ISEMPTY() is now used to
detect if a proxy does not contain any server.

Server insertion at the front position during config parsing is kept at
the moment, with reordering on post parsing. With the current patch,
this is not strictly necessary so this will be removed in a next change.

3 months agoMINOR: proxy: define server list iteration functions
Amaury Denoyelle [Thu, 23 Jul 2026 14:34:49 +0000 (16:34 +0200)]
MINOR: proxy: define server list iteration functions

Define wrappers function to iterate over a proxy servers list. These
functions are used when a standard for loop over the whole list is not
desirable.

This patch will ease the conversion of the proxy servers list into a
doubly linked struct list type, as the final conversion patch changes
will be smaller.

3 months agoMINOR: server: do not return next server on srv_drop()
Amaury Denoyelle [Wed, 22 Jul 2026 08:14:35 +0000 (10:14 +0200)]
MINOR: server: do not return next server on srv_drop()

Previously, srv_drop() returned the next server entry in the parent
proxy. This was used as convenience during server iteration. However,
the code has evolved several times to better deal with the server
deletion risk. Currently, srv_drop() return value is only used in a
single place.

Thus, this patch simplifies srv_drop() by removing its return value. As
a side effect, this will also reduce the modification required to
convert the proxy server list to a doubly linked struct list.

3 months agoMINOR: server: rename global servers_list to all_servers
Amaury Denoyelle [Thu, 23 Jul 2026 14:15:24 +0000 (16:15 +0200)]
MINOR: server: rename global servers_list to all_servers

Rename global <servers_list> to <all_servers>. This name better reflects
that it contains all the servers and servers a similar purpose to
<all_proxies> list.

3 months agoBUILD: ssl: Do not use SSL3_MT_KEY_UPDATE, hardcode 24 instead
Olivier Houchard [Thu, 23 Jul 2026 23:12:33 +0000 (01:12 +0200)]
BUILD: ssl: Do not use SSL3_MT_KEY_UPDATE, hardcode 24 instead

Not every SSL lib provides SSL3_MT_KEY_UPDATE, so just hardcode 24
instead.
This should be backported up to 2.8, when
91004114fe8816f848025fe71def4ea23e72a5f6 will be backported.

3 months agoBUG/MEDIUM: ssl: Put CO_ER_SSL_KEYUPDATE at the right place
Olivier Houchard [Thu, 23 Jul 2026 22:59:15 +0000 (00:59 +0200)]
BUG/MEDIUM: ssl: Put CO_ER_SSL_KEYUPDATE at the right place

FOr some reason, CO_ER_SSL_KEYUPDATE has been put in the middle of the
enum containing all the different possible connection errors, but
reg-tests depend on their numeric value, so it broke them. Put it at the
end of the enum instead.

This should be backported up to 2.8 with commit
91004114fe8816f848025fe71def4ea23e72a5f6.

3 months agoDOC: ssl: Document tune.ssl.keyupdate-rate-limit
Olivier Houchard [Thu, 23 Jul 2026 22:30:18 +0000 (00:30 +0200)]
DOC: ssl: Document tune.ssl.keyupdate-rate-limit

Add documentation for tune.ssl.keyupdate-rate-limit

This should be backported up to 2.8, when commit
91004114fe8816f848025fe71def4ea23e72a5f6 will be backported.

3 months agoMEDIUM: ssl: Add a way to rate-limit TLSv1.3 KeyUpdate
Olivier Houchard [Thu, 23 Jul 2026 13:31:18 +0000 (15:31 +0200)]
MEDIUM: ssl: Add a way to rate-limit TLSv1.3 KeyUpdate

Processing TLSv1.3 KeyUpdate is expensive in term of CPU, and in normal
usage there is very few reason to get a lot of them. So add a new
keyword, tune.ssl.keyupdate-rate-limit, that gives the maximum number of
KeyUpdate we're okay with receiving per second. The default is 100,
which should be enough. 0 means no rate-limiting at all.

This should mitigate the problem reported in Github issue #3450.

This should be backported as far back as 2.8.

3 months agoBUG/MEDIUM: ssl: Handle non-application data record while splicing
Olivier Houchard [Wed, 22 Jul 2026 16:43:24 +0000 (18:43 +0200)]
BUG/MEDIUM: ssl: Handle non-application data record while splicing

When using splicing with kTLS, if we receive a record that is not an
application data record, such as a KeyUpdate, then splicing will fail.
If that happens, temporarily disable splicing and go the regular way so that
recvmsg() is used, we get the record, and we can resume splicing.
Please not that KeyUpdate is still not handled with AWS-LC. Only recent
Linux kernels support it, and the code hasn't been written for that yet.

This should be backported up to 3.3.

This should help with github issue #3450.

3 months agoBUG/MEDIUM: ssl: Spell HAVE_VANILLA_OPENSSL correctly
Olivier Houchard [Wed, 22 Jul 2026 16:33:28 +0000 (18:33 +0200)]
BUG/MEDIUM: ssl: Spell HAVE_VANILLA_OPENSSL correctly

Use HAVE_VANILLA_OPENSSL, which is what we actually define when we're
linked against OpenSSL, and not USE_VANILLA_OPENSSL.
Not using the right macro means we may start splicing with kTLS while
there are still data available in OpenSSL's internal buffers, leading to
data not being properly read.

This should be backported up to 3.3.

3 months agoMINOR: proxy: rename proxies list to all_proxies
Amaury Denoyelle [Mon, 20 Jul 2026 13:14:52 +0000 (15:14 +0200)]
MINOR: proxy: rename proxies list to all_proxies

Rename global list <proxies> to <all_proxies>. This better highlights
the difference with the other list <main_proxies>. The first one contain
every proxy instances, whereas the second list is only a subset of user
visible proxies.

In the future, it should be sufficient to only keep <all_proxies> list.
However, this requires careful code analysis, in particular to ensure
proxies iteration are always executed with the proper capabilities
filter.

3 months agoCLEANUP: proxy/config: clean up after proxies list conversion
Amaury Denoyelle [Thu, 16 Jul 2026 13:07:02 +0000 (15:07 +0200)]
CLEANUP: proxy/config: clean up after proxies list conversion

All proxies list (main proxies, log forward and sink) have been
converted to the doubly linked standard list type. Proxy <next> member
is now unneeded, it is thus removed from the structure.

This patch also removes obsolete _get_next_proxy() wrapper used during
check_config_validity().

3 months agoOPTIM/MEDIUM: proxy: avoid main proxies list reordering on startup
Amaury Denoyelle [Wed, 22 Jul 2026 14:13:42 +0000 (16:13 +0200)]
OPTIM/MEDIUM: proxy: avoid main proxies list reordering on startup

Prior to this patch, proxies were added in front ot the visible proxies
list, resulting in the reverse order of their parsing. The list was then
reversed once parsing was completed to reflect the configuration order.
This was performed for performance reason, as visible proxies list was
simply linked.

This list has recently been converted to a doubly linked struct list.
Thus, it is now possible to append a newly parsed proxy at the end of
the list in constant time.

Thus, with this patch, a newly parsed instance is now directly inserted
at the end of main proxies list. This is implemented by updating
main_proxies_register() wrapper. Post-config performance are slightly
improved as reversal is now unneeded.

3 months agoMAJOR: proxy: convert proxies_list to a doubly linked struct list
Amaury Denoyelle [Fri, 16 Jan 2026 08:26:56 +0000 (09:26 +0100)]
MAJOR: proxy: convert proxies_list to a doubly linked struct list

Frontend, backend and listen proxies are all stored in <proxies_list>
which contain all user visible entries. This list is read in several
places, for example during stats dump.

Dynamic backend have just been introduced in the previous 3.4 release,
with creation and removal of new instances at runtime. The main
bottleneck of these operation is the manipulation of <proxies_list> due
to its singly linked nature.

This patch converts <proxies_list> into a doubly linked standard list
type. Proxy member <el> is reused as attach point. It is already used
for internal proxies in other list, not intersecting with this usage.
The main benefit of this change is to improve performance for add and
delete backend operations. It is labelled as major as it may break
external components which manipulate this list.

Also, old naming <proxies_list> has been replaced by <main_proxies>.
This helps to differentiate with the already existing superset <proxies>
list which contain all proxies instances, even internal ones. In the
future, it should be sufficient to only keep the latter list. However,
this requires careful code analysis, in particular to ensure proxies
iteration are always executed with the proper capabilities filter.

Proxies reversal on post parsing has been updated to use the new list
format. This will be removed in a latter patch as it is now possible to
insert proxies in the order of their parsing in constant time. Most of
the other changes are straightforward : for/while statements are
replaced by list_for_each_entry(). For incomplete iteration, recently
introduced iteration wrappers are updated to use LIST macros.

3 months agoMINOR: proxy: define proxies_list iteration functions
Amaury Denoyelle [Wed, 15 Jul 2026 14:30:45 +0000 (16:30 +0200)]
MINOR: proxy: define proxies_list iteration functions

Define wrappers function for <proxies_list> iteration. These functions
are used when a standard for loop over the whole list is not desirable.

The objective of this patch is to ease the conversion of <proxies_list>
from a singly linked list to a standard doubly linked list type. This
will help to keep the final conversion patch smaller.

Also, iteration over struct list is sligthly more complicated as it
requires more operation, for example for list end detection. Thus, the
wrappers will become handy to avoid tedious code repetion.

3 months agoMINOR: proxy: centralize proxies_list insert during config parsing
Amaury Denoyelle [Wed, 22 Jul 2026 14:06:55 +0000 (16:06 +0200)]
MINOR: proxy: centralize proxies_list insert during config parsing

Define a new function wrapper mainpx_register() which is used to insert
a proxy instance in <proxies_list> which contain all user visible
entries. Insertion is performed at the front of the list. Thus it must
only be used during configuration parsing, before proxies list reversal.

The main objective of this patch is to simplify the list conversion to a
doubly linked one by centralizing the required changes in a single
function. A nice benefit is that it is now easier to determine the exact
proxies list composition.

3 months agoMINOR: sink: convert list to standard doubly linked one
Amaury Denoyelle [Thu, 16 Jul 2026 10:01:02 +0000 (12:01 +0200)]
MINOR: sink: convert list to standard doubly linked one

This patch is similar to the previous one, dealing this time with sink
proxies stored in <sink_proxies_list>.

This list is converted to a doubly linked standard list type, in
preparation to the conversion of the visible proxies list. The objective
is similar : code simplification for check_config_validity() when
looping over several proxies list.

3 months agoMINOR: log: convert list to standard doubly linked one
Amaury Denoyelle [Thu, 16 Jul 2026 10:00:46 +0000 (12:00 +0200)]
MINOR: log: convert list to standard doubly linked one

Log-forward proxies are not stored in <proxies_list> alongside other
visible user proxies. Instead, they are stored in a dedicated list
<cfg_log_forward>.

As with the visible proxies list, log forwarders list was defined as a
simple singly linked one. This patch converts it to the doubly linked
standard list type, frequently used in haproxy source code. Proxy <el>
member is reused as list attach point. It was only used by defaults
instances prior to this patch.

This patch does not bring noticeable change. However it will simplify
visible proxies list similar conversion as both lists are looped over
together during check_config_validity().

3 months agoMINOR: config: define wrapper for proxies loop during check config
Amaury Denoyelle [Thu, 16 Jul 2026 09:27:41 +0000 (11:27 +0200)]
MINOR: config: define wrapper for proxies loop during check config

On check_config_validity(), proxy post init code is reexcuted over
several proxies list : the main proxies list, log sections and sinks.

This patch defines an internal wrapper to help performing this
iteration. It will become necessary once each list is converted from a
singly linked format to a doubly linked struct list. Once all lists are
converted, the wrapper should be removed as it will be once again
unnecessary.

3 months agoMINOR: log: use curproxy during config parsing
Amaury Denoyelle [Wed, 15 Jul 2026 08:39:36 +0000 (10:39 +0200)]
MINOR: log: use curproxy during config parsing

Adjusts configuration parsing for log-forward sections : replace
<cfg_log_forward> head pointer list usage in individual keywords parser
by <curproxy> global variable. This parsing patterm is already
implemetned in cfgparse-listen module.

This is only a refactoring change without any visible effect. It is a
preparatoy step before converting <cfg_log_forward> to a full doubly
linked struct list.

3 months agoMINOR: haload: add rate limiting support using -R option
Frederic Lecaille [Thu, 23 Jul 2026 08:41:33 +0000 (10:41 +0200)]
MINOR: haload: add rate limiting support using -R option

Implement request/connection rate limiting per second using the new
-R command line option <arg_rate>.

Instead of reinventing the wheel, this implementation aligns with the
h1load approach by relying on existing frequency counters. Dedicated
tasks <hld_rate_task> are spawned on each thread solely to manage and
throttle connection initializations based on <arg_rate>.

The counter <running_usrs> is renamed to <running_tasks> to track both
users and connection rate-limiting tasks.

Modify the doc/haload.txt file.

3 months agoBUG/MINOR: haload: fix display glitches by flushing stdout in summary
Frederic Lecaille [Thu, 23 Jul 2026 08:31:46 +0000 (10:31 +0200)]
BUG/MINOR: haload: fix display glitches by flushing stdout in summary

Fix a bug in hld_summary() where the output stream was not explicitly
flushed after printing the periodic statistics line. This caused text
buffering issues and visual overlapping in the terminal output.

3 months agoBUG/MINOR: haload: set default thread count to 1
Frederic Lecaille [Wed, 22 Jul 2026 09:00:49 +0000 (11:00 +0200)]
BUG/MINOR: haload: set default thread count to 1

By default <arg_thrd> was unset (-1) and fell back to global.nbthread,
causing inconsistencies since <arg_usr> defaults to 1. This patch sets
the default thread count to 1, enforces that <arg_thrd> does not exceed
<arg_usr>, updates usage help, and writes nbthread unconditionally.

Modify the doc/haload.txt file.

3 months agoBUG/MINOR: haload: fix use-after-free upon updating task expiration
Frederic Lecaille [Tue, 21 Jul 2026 13:09:20 +0000 (15:09 +0200)]
BUG/MINOR: haload: fix use-after-free upon updating task expiration

Fix a bug in hld_strm_task() where hs was accessed after it had already been
freed via hldstream_free(&hs). The task expiration update and queueing
now safely rely on <usr> rather than <hs->usr>.

3 months agoMINOR: proxy: stress "show errors" handler
Amaury Denoyelle [Tue, 21 Jul 2026 14:04:18 +0000 (16:04 +0200)]
MINOR: proxy: stress "show errors" handler

Implement stress function for "show errors" output. This forces the
command to yield on every newly dumped instance, which is useful for
debugging.

3 months agoBUG/MEDIUM: proxy: protect "show errors" against backend deletion
Amaury Denoyelle [Thu, 23 Jul 2026 09:28:07 +0000 (11:28 +0200)]
BUG/MEDIUM: proxy: protect "show errors" against backend deletion

Command "show errors" is not safe as it loops over the list of proxies.
A crash may occur if the task yields on a proxy which is deleted just
before the dump is restarted.

As with previous fixes dealing with similar cases, this is fixed via the
watcher mechanism. A new <px_watcher> member is defined in
<show_errors_ctx> and used to loop over the proxies list.

This must be backported up to 3.4.

3 months agoCLEANUP: mux_quic: remove unused prototype
Amaury Denoyelle [Thu, 23 Jul 2026 09:21:28 +0000 (11:21 +0200)]
CLEANUP: mux_quic: remove unused prototype

Remove qcc_update_shut_id() declaration. This function was never defined
in the code.

3 months ago[RELEASE] Released version 3.5-dev3 v3.5-dev3
Willy Tarreau [Wed, 22 Jul 2026 15:36:25 +0000 (17:36 +0200)]
[RELEASE] Released version 3.5-dev3

Released version 3.5-dev3 with the following main changes :
    - BUILD: haload: Increase a buffer size so that gcc will stop complaining
    - BUILD: task: Fix build when no 8B CAS is available at all
    - BUG/MINOR: hlua: Apply socket timeout on server side only
    - BUG/MEDIUM: applet: Reenable reads in applet context if requesting a connection
    - MINOR: stats: factor the proxy vs scope check into its own function
    - BUG/MEDIUM: stats: subject "stats admin" accesses to "stats scope" filtering
    - BUG/MINOR: shctx: fix shctx_row_data_get() when offset exceeds a block
    - MINOR: shctx: clamp shctx_row_data_get() reads against the offset
    - DOC: stats: document the per-proxy byte count fields in the CSV list
    - BUG/MEDIUM: cache: reattach the row when a secondary entry is incomplete
    - MINOR: http: add two header parsing functions
    - MINOR: cache: minor changes ahead of support for sending early hints
    - MINOR: cache: add config options for early hints support
    - MINOR: cache: add helper functions for early hints support
    - MINOR: shctx: allow consumers to customize eviction strategy
    - MINOR: cache: track full and hints entries in per-pool LRU lists
    - MEDIUM: cache: early hints-aware eviction code
    - MINOR: cache: indicate whether entries are stripped or not
    - MINOR: http: factor 103 emission into start/end helpers
    - MEDIUM: cache: emit early hints if configured to do so
    - MINOR: cache: add a counter for cache hits serving early hints
    - MINOR: cache: allow opting out of early hints at the rule level
    - MINOR: cache: allow customizing ratio for early hints
    - REGTESTS: cache: validate the emission of 103s
    - MINOR: cache: factor cache_extract_link_hints out of cache_extract_hints
    - MEDIUM: cache: add support for hints-only HTTP caches
    - MEDIUM: ssl: introduce src/fips.c with TLS version check
    - MEDIUM: ssl: add FIPS TLS 1.2 cipher check for AWS-LC
    - MEDIUM: ssl: set FIPS-approved cipher defaults for AWS-LC FIPS builds
    - MEDIUM: ssl: add FIPS TLS 1.3 ciphersuite check for AWS-LC
    - MEDIUM: ssl: set FIPS-approved curve defaults for AWS-LC FIPS builds
    - MEDIUM: ssl: add FIPS elliptic curve check for AWS-LC
    - MEDIUM: ssl: set FIPS-approved sigalgs defaults for AWS-LC FIPS builds
    - MEDIUM: ssl: add FIPS signature algorithm check for AWS-LC
    - CLEANUP: cache: align the cache_hint_hits increment with its siblings
    - BUG/MEDIUM: stats: Ensure that Origin is valid on POSTs
    - DOC: stats: Document that stats admin is vulnerable to a CSRF attack
    - BUG/MEDIUM: ssl-gencert: Don't forget to free memory when done
    - BUG/MEDIUM: protobuf: adjust sample size capacity after pointer shift
    - BUG/MEDIUM: protobuf: fix nested path bypass in field lookup
    - BUG/MINOR: ssl: fix proxy lookup for show ssl sni
    - REGTESTS: protobuf: add regression test for nested vs flat paths
    - DEBUG: add BUG_ON_STATIC(): a compile-time BUG_ON()
    - CLEANUP: event_hdl: Use BUG_ON_STATIC()
    - DOC: internals: update core-principles with initializations
    - BUG/MINOR: mux-h1: Don't delay send if message with c-l was fully sent
    - BUG/MEDIUM: net-helper: Adjust sample size capacity after pointer shift
    - BUG/MEDIUM: sample: Adjust sample size capacity after pointer shift for bytes()
    - BUG/MEDIUM: sample: Adjust sample size capacity after pointer shift for ltrim()
    - BUG/MINOR: sample: Fix bytes() when length it greater than remaining data
    - BUILD: Makefile: error when trying to build with aws-lc with the wrong flags
    - DOC: fix typo in "del ssl ech" command
    - DOC: remove outdated experimental mention on dynamic backends
    - BUG/MEDIUM: proxy: protect "show servers ..." against server deletion
    - BUG/MEDIUM: proxy: protect "show servers ..." against backend deletion
    - BUG/MEDIUM: proxy: protect show backend against be deletion
    - MINOR: proxy: stress CLI commands with backends/servers loop
    - BUG/MEDIUM: server: Properly check for streams before deletion
    - BUG/MINOR: resolvers: do not index resolvers names in the proxies

3 months agoBUG/MINOR: resolvers: do not index resolvers names in the proxies
Willy Tarreau [Wed, 22 Jul 2026 13:17:38 +0000 (15:17 +0200)]
BUG/MINOR: resolvers: do not index resolvers names in the proxies

Resolvers are self-sustaining sections that have their own list, but for
the purpose of supporting TCP connections, a backend proxy is created
with them, and it holds the same name as the section. Since we started
to create a "default" resolvers section, a similarly named backend in
TCP mode automatically appeared, resulting in issues such as the one
described in GH #3445:

   defaults
       mode http

   frontend public
       bind :8001
       default_backend default

It yells: "... tries to use incompatible tcp proxy 'default' (<internal>:0)
in a 'use_backend' rule (see 'mode')" because it in fact finds the hidden
resolvers proxy. Depending on versions, adding such a default backend makes
the issue go away or not.

Worse, the following config:

   frontend public
       bind :8001
       default_backend default

actually routes the traffic to the local resolvers :-(

Resolvers do not need to appear in proxies index tree, as they're looked
up by find_resolvers_by_id() which iterates over all resolvers sections
(i.e. tree not used), so we can safely avoid indexing them.

Some other proxies are now protected against this via the use of PR_CAP_INT
which also prevents indexing, but that flag changed multiple times along
versions and is extremely sensitive in older ones, to the point of not
being suitable for a backport.

Instead, commit 116983ad94 ("MEDIUM: cfgparse: do not store unnamed
defaults in name tree") added the following test to refrain from
indexing an unnamed proxy in setup_new_proxy():

  @@ -1718,7 +1718,8 @@ int setup_new_proxy(struct proxy *px, const char *name, unsigned int cap, char *
          px->cap = cap;
          px->last_change = ns_to_sec(now_ns);

  -       if (name && !(cap & PR_CAP_INT))
  +       /* Internal proxies or with empty name are not stored in the named tree. */
  +       if (name && name[0] != '\0' && !(cap & PR_CAP_INT))
                  proxy_store_name(px);

          if (!(cap & PR_CAP_DEF))

This part is totally suitable for backporting and permits to simply
change the resolvers' proxy creation to pass NULL or an empty string
instead of the resolvers section's name so that we don't index that
proxy. That's what this patch does. For versions before 3.4, the
commented patch above must be explicitly backported. This patch must
be backported to 3.0. Thanks to Lukasz Nowak for reporting this bug.

It's worth noting that this area is really falling apart and urgently
needs attention. The internal API is currently too limited to permit
reliable lookups, which is the reason why so many proxies are hidden
that way. In an ideal world, all names would be indexed and caps and
modes properly set to unambiguous values, so that lookup functions
only look up specific caps and modes, and support being passed a mask
to avoid matching undesired caps. At the very least a mask should be
given in lookups, and a few extra caps should permit to distinguish
regular proxies (those declared with the "frontend" and "backend"
keyword, supporting use_backend) from other ones (rings, resolvers,
log-forward etc).

3 months agoBUG/MEDIUM: server: Properly check for streams before deletion
Olivier Houchard [Mon, 20 Jul 2026 14:05:51 +0000 (16:05 +0200)]
BUG/MEDIUM: server: Properly check for streams before deletion

When a server delete command happens, before we actually delete the
server, we check if there are any streams still attached to the server,
and will refuse the deletion if it is so. Unfortunately, the check was
not exhaustive, we would check if there's any stream in the queue, if
there are any connection to the server established, and if served is
non-zero.
But there are at least two cases where a stream will have a reference to
the server, but none of those will be true : the first one is the case
where we tried a connection to the server, and it failed. At this point
we decremented served, but we will still hold a reference to the server
in target until a new server has been assigned. The second one happens
with cookie persistence, in which case target will be set to the server
address way before any connection is attempted, and so way before served
is incremented.
To fix that, introduce a new per-thread-group counter in the server
structure, nb_strm, that counts the streams whose target points to that
server. It is incremented when a stream's target is set to a server, and
decremented when the target changes to another server, to a non-server,
or the stream ends. To make this reliable, all assignments to a stream's
target now go through the new stream_set_target() helper, which keeps
nb_strm up to date and also clears sv_tgcounters when the target is no
longer a server, so we don't keep a dangling reference to the server's
counters (its failure counters have already been accounted for by that
point). To check if there are still any streams attached to the server,
the code just looks at all the per-thread-group counters, and if one of
them is non-zero, there are still streams on that server. This will
always be accurate because the server deletion command runs with thread
isolation.

This should be backported up to 3.0.

3 months agoMINOR: proxy: stress CLI commands with backends/servers loop
Amaury Denoyelle [Tue, 21 Jul 2026 09:38:12 +0000 (11:38 +0200)]
MINOR: proxy: stress CLI commands with backends/servers loop

Update handlers for "show backend" and "show servers state/conn" so that
stress mode can be used to force the task yielding each time a new
instance is dumped.

This is useful for debugging commands safety with backend/server
deletion in parallel.

3 months agoBUG/MEDIUM: proxy: protect show backend against be deletion
Amaury Denoyelle [Tue, 21 Jul 2026 09:35:25 +0000 (11:35 +0200)]
BUG/MEDIUM: proxy: protect show backend against be deletion

Command "show backend" loops over the list of visible proxies to display
information about all the backend instances. This command may yield in
case of a long output, but this is not safe with introduction of dynamic
backend deletion at runtime.

Fixes this by using the watcher mechanism, similarly to what is
implemented for stats dump. To support this, a new context dedicated to
"show backend" has been defined.

This must be backported up to 3.4.

3 months agoBUG/MEDIUM: proxy: protect "show servers ..." against backend deletion
Amaury Denoyelle [Tue, 21 Jul 2026 14:27:46 +0000 (16:27 +0200)]
BUG/MEDIUM: proxy: protect "show servers ..." against backend deletion

This patch is a direct follow up of the previous one which fixes
commands "show servers conn/state". The current patch ensures that these
commands are safe even with task yielding and backend deletion in
parallel. This is also based on the watcher mechanism.

This must be backported up to 3.4.

3 months agoBUG/MEDIUM: proxy: protect "show servers ..." against server deletion
Amaury Denoyelle [Tue, 21 Jul 2026 07:26:22 +0000 (09:26 +0200)]
BUG/MEDIUM: proxy: protect "show servers ..." against server deletion

Command show servers conn/state loops over a server list to display
various information. This command may yield in case of a large output.
This can cause a crash if the server on which the command was paused is
deleted prior to restarting the command.

Fixes this by using the watcher mechanism, similar to what is already
implementing with stats dump.

This must be backported at least up to 3.0. For older releases, watcher
mechanism is not available, server refcount + SRV_F_DELETED flag must be
used instead.

3 months agoDOC: remove outdated experimental mention on dynamic backends
Amaury Denoyelle [Tue, 21 Jul 2026 07:32:55 +0000 (09:32 +0200)]
DOC: remove outdated experimental mention on dynamic backends

Dynamic backends commands were first implemented with experimental
status guard. However, this status was removed before the final release
as it is considered stable enough.

This patch cleans up outdated references to experimental status for
add/del backend commands in management documentation.

This must be backported up to 3.4.

3 months agoDOC: fix typo in "del ssl ech" command
Amaury Denoyelle [Tue, 21 Jul 2026 07:42:09 +0000 (09:42 +0200)]
DOC: fix typo in "del ssl ech" command

Correct "det" to "del" keyword.

This must be backported up to 3.3.

3 months agoBUILD: Makefile: error when trying to build with aws-lc with the wrong flags
William Lallemand [Tue, 21 Jul 2026 13:06:20 +0000 (15:06 +0200)]
BUILD: Makefile: error when trying to build with aws-lc with the wrong flags

USE_OPENSSL_AWSLC=1 is required when trying to build with aws-lc. This
was already required before, but kind of worked without it since
f76e8e50f460 ("BUILD: ssl: replace USE_OPENSSL_AWSLC by
OPENSSL_IS_AWSLC").

However since 9ac590b5 ("MEDIUM: ssl: introduce src/fips.c with TLS
version check"), this can't work by accident anymore.

This patch emits an error when we find OPENSSL_IS_AWSLC, but we didn't
found USE_OPENSSL_AWSLC=1.

3 months agoBUG/MINOR: sample: Fix bytes() when length it greater than remaining data
Christopher Faulet [Mon, 20 Jul 2026 16:05:14 +0000 (18:05 +0200)]
BUG/MINOR: sample: Fix bytes() when length it greater than remaining data

For bytes() converter, when the length parameter is greater than the
remaining data, no truncation on length must be performed. However, in that
case, nothing was performed at all. The changes because of the offset
parameter was just ignored.

Now, when the length value is too large, the sample data are moved
accordingly to the offset value as expected.

The coresponding reg-test was updated to test this case with a non-zero
offset. In addition the documentation was fixed to properly match what the
converter do. It was wrongly updated when the support of variables was
introduced in 2.9.

This patch must be backported as far as 3.0.

3 months agoBUG/MEDIUM: sample: Adjust sample size capacity after pointer shift for ltrim()
Christopher Faulet [Mon, 20 Jul 2026 15:50:20 +0000 (17:50 +0200)]
BUG/MEDIUM: sample: Adjust sample size capacity after pointer shift for ltrim()

For the ltrim() converter, on success, the area pointer of the sample buffer
is moved forward without updating the buffer size accordingly. If this
converter is followed by another one relying on the buffer size to do some
operations on the buffer area, this could lead to a buffer overflow.

Thanks to Charles Vosburgh <theminershive@gmail.com> for reporting this and
providing the fix.

This patch must be backported to all supported versions.

3 months agoBUG/MEDIUM: sample: Adjust sample size capacity after pointer shift for bytes()
Christopher Faulet [Mon, 20 Jul 2026 15:48:47 +0000 (17:48 +0200)]
BUG/MEDIUM: sample: Adjust sample size capacity after pointer shift for bytes()

For the bytes() converter, on success, the area pointer of the sample buffer
is moved forward without updating the buffer size accordingly. If this
converter is followed by another one relying on the buffer size to do some
operations on the buffer area, this could lead to a buffer overflow.

Thanks to Charles Vosburgh <theminershive@gmail.com> for reporting this and
providing the fix.

This patch must be backported to 3.0.

3 months agoBUG/MEDIUM: net-helper: Adjust sample size capacity after pointer shift
Christopher Faulet [Mon, 20 Jul 2026 15:07:39 +0000 (17:07 +0200)]
BUG/MEDIUM: net-helper: Adjust sample size capacity after pointer shift

eth.data, eth.src and ip.data converters are concerned. On success, the area
pointer of the sample buffer is moved forward without updating the buffer
size accordingly. If these converters are followed by another one relying on
the buffer size to do some operations on the buffer area, this could lead to
a buffer overflow.

Thanks to Charles Vosburgh <theminershive@gmail.com> for reporting this and
providing the fix.

This patch must be backported to 3.4.

3 months agoBUG/MINOR: mux-h1: Don't delay send if message with c-l was fully sent
Christopher Faulet [Mon, 20 Jul 2026 12:21:27 +0000 (14:21 +0200)]
BUG/MINOR: mux-h1: Don't delay send if message with c-l was fully sent

In the H1 multiplexer, if a message was fully sent considering the specified
content-length, the MSG_MORE flag must be unset, regardless the upper layer
said. This should avoid a extra latency of 200ms when this happens while the
HTX EOM flag is not set on the message. This may happen for H2/H3 messages
with trailers or if the END_OF_STREAM was not reported yet on H2/H3 side. In
both cases, on H1 side, no more data will be sent (trailers will be
dropped). So we must never delay the send.

This patch should fix the issue #3447. It must be backported to all
supported versions.

3 months agoDOC: internals: update core-principles with initializations
Willy Tarreau [Sun, 19 Jul 2026 15:18:44 +0000 (17:18 +0200)]
DOC: internals: update core-principles with initializations

Code reviews tend to remain confused about initialized values depending
on struct types. Let's clarify when pool_alloc() and calloc() are used.

3 months agoCLEANUP: event_hdl: Use BUG_ON_STATIC()
Olivier Houchard [Thu, 16 Jul 2026 17:00:44 +0000 (19:00 +0200)]
CLEANUP: event_hdl: Use BUG_ON_STATIC()

Now that we have a BUG_ON_STATIC() macro, use it instead of rolling our
own.

3 months agoDEBUG: add BUG_ON_STATIC(): a compile-time BUG_ON()
Maxime Henrion [Thu, 16 Jul 2026 16:18:17 +0000 (12:18 -0400)]
DEBUG: add BUG_ON_STATIC(): a compile-time BUG_ON()

Fails the build when <cond>, a constant expression, is true. Maps to
_Static_assert() on C11+; older dialects declare a negatively-sized
extern array instead, which emits no storage nor symbol. Usable at
file and block scope.

3 months agoREGTESTS: protobuf: add regression test for nested vs flat paths
Frederic Lecaille [Thu, 16 Jul 2026 15:41:18 +0000 (17:41 +0200)]
REGTESTS: protobuf: add regression test for nested vs flat paths

This patch adds a new VTC regression test to validate the protobuf()
sample converter and prevent future regressions.

It tests four distinct scenarios to ensure correct behavior:
  - validating legitimate nested path extraction (e.g., path "1.2") on a
    nested payload.
  - ensuring flat path extraction (path "2") is blocked when the field is
    actually inside a nested payload.
  - validating legitimate flat sibling extraction (path "2") on a flat
    payload.
  - ensuring nested path extraction (path "1.2") is blocked when run on
    a flat sibling payload which was fixed by this commit

    BUG/MEDIUM: protobuf: fix nested path bypass in field lookup

3 months agoBUG/MINOR: ssl: fix proxy lookup for show ssl sni
Amaury Denoyelle [Wed, 15 Jul 2026 15:11:22 +0000 (17:11 +0200)]
BUG/MINOR: ssl: fix proxy lookup for show ssl sni

Command "show ssl sni" accepts an extra option -f to restrict output to
a single frontend. If the specified proxy is not found, an error message
should be displayed. However, this does not behave as expected as no
error is reported and the first proxy in the list is used as a sort of
fallback.

This patch fixes the command parsing function when -f is used. The loop
is now interrupted as soon as a matching entry is found. After the loop,
if local variable <px> is still NULL, it indicates that no matching
entry was found. The error message is displayed as intended and the
command is not executed.

This must be backported up to 3.2.

3 months agoBUG/MEDIUM: protobuf: fix nested path bypass in field lookup
Frederic Lecaille [Thu, 16 Jul 2026 13:19:52 +0000 (15:19 +0200)]
BUG/MEDIUM: protobuf: fix nested path bypass in field lookup

The previous implementation of protobuf_field_lookup() was susceptible
to a security bypass where flat sibling fields could be incorrectly matched
as nested children. This occurred because the parser did not strictly
enforce hierarchical boundaries and depth matching during sequential
iteration, allowing flat structures to satisfy nested path requirements (e.g.
treating a root-level sibling field as if it were nested under a parent).

This patch refactors the lookup logic into a strict, iterative stream
parser that progresses through the defined configuration path (depth).
The new logic guarantees that:

 - intermediate matching parent fields must be of type LENGTH_DELIMITED.
   If an intermediate match is found but is a primitive type, the parsing
   aborts immediately.
 - when descending into an intermediate parent, the scanning boundary
   (*len) is strictly narrowed down to the nested sub-message size (vlen)
   with an upfront validation against buffer overflow (vlen > *len).
 - sibling fields at the current level are skipped cleanly without polluting
   higher or lower hierarchy levels.

This implementation achieves absolute stack safety (O(1) memory complexity,
no recursion) and guarantees strict validation of nested Protobuf paths.

Many thanks to Red Hat and AISLE Research for reporting this.

This must be backported as far as 2.6

3 months agoBUG/MEDIUM: protobuf: adjust sample size capacity after pointer shift
Frederic Lecaille [Thu, 16 Jul 2026 07:05:48 +0000 (09:05 +0200)]
BUG/MEDIUM: protobuf: adjust sample size capacity after pointer shift

This bug impacts "protobuf" and "ungrpc" sample fetches.

When extracting fields from a  payload, the data pointer
"smp->data.u.str.area" is forwarded to point directly onto the decoded
sub-field data. However, the sample's maximum capacity size tracking property
"smp->data.u.str.size" was left untouched, remaining set to the total
original buffer size (e.g., tune.bufsize).

This creates an architectural size mismatch. Subsequent processing layers or
converters (such as stick-tables executing padding mechanisms via memset())
may assume that the original total capacity is still fully available starting
from the new forwarded offset. In specific configurations involving writable
cloned buffers (e.g., combining "lower" and "protobuf" converters before
tracking key storage), this logical flaw can easily lead to out-of-bounds
heap memory corruption or crashes.

Under rare conditions, depending on the specific combination of frontend
configurations (e.g., use of wait-for-body rules) and the alignment of
incoming HTTP requests containing specific chunked or large payload patterns,
this out-of-bounds write could lead to an immediate haproxy process crash
or data corruption.

Fix this by introducing "protobuf_adjust_smp_size()". This inline function
safely computes the consumed byte offset after each pointer shift and
decrements the sample's residual capacity size accordingly before updating
the payload reference. All "protobuf_smp_store_*" callbacks are updated.

Many thanks to Red Hat and AISLE Research for reporting this.

This must be backported as far as 2.6

3 months agoBUG/MEDIUM: ssl-gencert: Don't forget to free memory when done
Olivier Houchard [Wed, 15 Jul 2026 16:01:46 +0000 (18:01 +0200)]
BUG/MEDIUM: ssl-gencert: Don't forget to free memory when done

In ssl_sock_do_create_cert(), don't forget to free ctmp and tmp_ssl once
we're done creating the certificate, otherwise we will get a memory leak
each time we have to create a new certificate, which will happen each
time a new SNI is used.

This should be backported as far as 2.6 (though on older releases,
ssl_gencert.c doesn't exist, and that function is found in ssl_sock.c).

This patch was submitted by Red Hat and AISLE Research

3 months agoDOC: stats: Document that stats admin is vulnerable to a CSRF attack
Olivier Houchard [Wed, 15 Jul 2026 14:40:27 +0000 (16:40 +0200)]
DOC: stats: Document that stats admin is vulnerable to a CSRF attack

Document that stats admin is vulnerable to a CSRF attack that can't be
totally mitigated, so if that feature really has to be used, precautions
must be taken.

This should be backported up to 2.6.

Many thanks to Red Hat and AISLE Research for reporting this.

3 months agoBUG/MEDIUM: stats: Ensure that Origin is valid on POSTs
Olivier Houchard [Wed, 15 Jul 2026 14:02:37 +0000 (16:02 +0200)]
BUG/MEDIUM: stats: Ensure that Origin is valid on POSTs

When receiving a POST on the stats interface, make sure that Origin (or
Referer if no Origin is found) matches the Host, to attempt to mitigate
a CSRF attack.

This should be backported up to 2.6.

Many thanks to Red Hat and AISLE Research for reporting this.

3 months agoCLEANUP: cache: align the cache_hint_hits increment with its siblings
Maxime Henrion [Fri, 10 Jul 2026 21:55:28 +0000 (17:55 -0400)]
CLEANUP: cache: align the cache_hint_hits increment with its siblings

For the sake of consistency, increment cache_hint_hits the same way as the
surrounding cache counters instead of going through a temporary pointer.

No functional change, and nothing to backport.

4 months agoMEDIUM: ssl: add FIPS signature algorithm check for AWS-LC
William Lallemand [Tue, 30 Jun 2026 13:39:14 +0000 (13:39 +0000)]
MEDIUM: ssl: add FIPS signature algorithm check for AWS-LC

Add ssl_fips_check_sigalgs() which validates the configured signature
algorithm list against the FIPS-approved set: ECDSA on NIST P-curves
with SHA-256/384/512, RSA-PSS (rsae and pss variants) with SHA-256/
384/512, and RSA-PKCS1 with SHA-256/384/512.  SHA-1 based algorithms
and non-FIPS primitives (ed25519, ed448) are rejected.

The check uses the same strchr-based string parsing as
ssl_fips_check_ciphersuites().  A NULL list is silently accepted since
the global defaults were already overwritten with FIPS values at init
time.

The check is called right after SSL_CTX_set1_sigalgs_list() and
SSL_CTX_set1_client_sigalgs_list() in both the bind
(ssl_sock_prepare_ctx) and server (ssl_sock_prepare_srv_ssl_ctx)
configuration paths.

4 months agoMEDIUM: ssl: set FIPS-approved sigalgs defaults for AWS-LC FIPS builds
William Lallemand [Tue, 30 Jun 2026 13:37:27 +0000 (13:37 +0000)]
MEDIUM: ssl: set FIPS-approved sigalgs defaults for AWS-LC FIPS builds

When AWS-LC is built in FIPS mode, unconditionally override the
compile-time signature algorithm defaults with the FIPS-approved set
before config parsing. Explicit ssl-default-{bind,server}-sigalgs
keywords in the global section still take precedence over these
defaults.

The approved set is defined as macros in include/haproxy/defaults.h
alongside the existing CONNECT/LISTEN_DEFAULT_FIPS_CIPHERS family:
  CONNECT/LISTEN_DEFAULT_FIPS_SIGALGS        - ECDSA (P-256/384/521),
                                               RSA-PSS and RSA-PKCS1
                                               with SHA-256/384/512
  CONNECT/LISTEN_DEFAULT_FIPS_CLIENT_SIGALGS - same set for client
                                               certificate sigalgs

SHA-1 based algorithms and non-FIPS primitives (ed25519, ed448) are
excluded from the defaults.

4 months agoMEDIUM: ssl: add FIPS elliptic curve check for AWS-LC
William Lallemand [Tue, 30 Jun 2026 13:28:03 +0000 (13:28 +0000)]
MEDIUM: ssl: add FIPS elliptic curve check for AWS-LC

Add ssl_fips_check_curves() which validates the configured curve list
against the FIPS-approved NIST P-curves (P-256, P-384, P-521).  Each
colon-separated name is resolved to a NID via OBJ_txt2nid() so all
standard aliases (P-256, prime256v1, secp256r1) are handled uniformly.
A NULL list is silently accepted since the global defaults were already
overwritten with FIPS values at init time.

The check is called right after SSL_CTX_set1_curves_list() in both the
bind (ssl_sock_prepare_ctx) and server (ssl_sock_prepare_srv_ssl_ctx)
configuration paths.

4 months agoMEDIUM: ssl: set FIPS-approved curve defaults for AWS-LC FIPS builds
William Lallemand [Tue, 30 Jun 2026 13:26:19 +0000 (13:26 +0000)]
MEDIUM: ssl: set FIPS-approved curve defaults for AWS-LC FIPS builds

When AWS-LC is built in FIPS mode, unconditionally override the
compile-time curve defaults with the FIPS-approved NIST P-curves
before config parsing. Explicit ssl-default-{bind,server}-curves
keywords in the global section still take precedence over these
defaults.

The approved set is defined as macros in include/haproxy/defaults.h
alongside the existing CONNECT/LISTEN_DEFAULT_FIPS_CIPHERS family:
  CONNECT/LISTEN_DEFAULT_FIPS_CURVES - P-256, P-384, P-521

This ensures that internal servers (httpclient, Lua SSL sockets) that
inherit global defaults also operate with FIPS-compliant curve lists
without requiring explicit configuration.

4 months agoMEDIUM: ssl: add FIPS TLS 1.3 ciphersuite check for AWS-LC
William Lallemand [Tue, 30 Jun 2026 13:14:53 +0000 (13:14 +0000)]
MEDIUM: ssl: add FIPS TLS 1.3 ciphersuite check for AWS-LC

AWS-LC does not expose TLS 1.3 ciphersuites set via SSL_CTX_set_ciphersuites()
through SSL_CTX_get_ciphers(), so the existing NID-based cipher check in
ssl_fips_check_ciphers() cannot catch non-FIPS TLS 1.3 suites.  This is
further compounded by a defect in the AWS-LC-FIPS 3.x branch where TLS 1.3
ciphers are missing from SSL_get_ciphers() entirely (fixed in
https://github.com/aws/aws-lc/pull/2092), making any SSL_CTX-based
inspection unreliable across versions.

Add ssl_fips_check_ciphersuites() which validates the ciphersuite string
directly against a FIPS-approved allowlist (TLS_AES_128_GCM_SHA256 and
TLS_AES_256_GCM_SHA384).  A NULL string is silently accepted since the
global defaults were already overwritten with FIPS values at init time.

The new check is called right after SSL_CTX_set_ciphersuites() in both
the bind (ssl_sock_prepare_ctx) and server (ssl_sock_prepare_srv_ssl_ctx)
configuration paths.

4 months agoMEDIUM: ssl: set FIPS-approved cipher defaults for AWS-LC FIPS builds
William Lallemand [Tue, 30 Jun 2026 12:44:45 +0000 (12:44 +0000)]
MEDIUM: ssl: set FIPS-approved cipher defaults for AWS-LC FIPS builds

When AWS-LC is built in FIPS mode, unconditionally override the
compile-time cipher defaults with FIPS-approved sets before config
parsing. Explicit ssl-default-{bind,server}-ciphers{suites} keywords
in the global section still take precedence over these defaults.

The approved sets are defined as macros in include/haproxy/defaults.h
alongside the existing CONNECT/LISTEN_DEFAULT_CIPHERS family:
  CONNECT/LISTEN_DEFAULT_FIPS_CIPHERS     - AES-128-GCM-SHA256 and
                                            AES-256-GCM-SHA384 (TLS 1.2)
  CONNECT/LISTEN_DEFAULT_FIPS_CIPHERSUITES - TLS_AES_128_GCM_SHA256 and
                                             TLS_AES_256_GCM_SHA384 (TLS 1.3)

This ensures internal servers (httpclient, Lua SSL sockets) that
inherit global defaults also operate with FIPS-compliant cipher lists
without requiring explicit configuration.

4 months agoMEDIUM: ssl: add FIPS TLS 1.2 cipher check for AWS-LC
William Lallemand [Tue, 30 Jun 2026 12:39:50 +0000 (12:39 +0000)]
MEDIUM: ssl: add FIPS TLS 1.2 cipher check for AWS-LC

Add ssl_fips_check_ciphers() to check the cipher list already loaded
into an SSL_CTX against the FIPS-approved bulk cipher NID allowlist
(AES-128-GCM, AES-256-GCM).  The check is run unconditionally after
SSL_CTX_set_cipher_list() for both bind and server contexts.

The function reuses the fips_obj_info() helper introduced with the
version check to emit precise 'type proxy/name [file:line]' error
messages and returns ERR_ALERT|ERR_ABORT|ERR_FATAL on violation.

4 months agoMEDIUM: ssl: introduce src/fips.c with TLS version check
William Lallemand [Tue, 30 Jun 2026 12:38:31 +0000 (12:38 +0000)]
MEDIUM: ssl: introduce src/fips.c with TLS version check

Add src/fips.c and include/haproxy/fips.h to centralise FIPS compliance
checks for AWS-LC builds.

ssl_fips_check_version() verifies that ssl-min-ver is not set below
TLS 1.2, which AWS-LC in FIPS mode would refuse to negotiate.

The check accepts an enum obj_type * so it can resolve the owning
bind/server and produce a precise error message including the proxy
and object name in the standard HAProxy 'type proxy/name' form.

4 months agoMEDIUM: cache: add support for hints-only HTTP caches
Maxime Henrion [Tue, 30 Jun 2026 15:33:37 +0000 (11:33 -0400)]
MEDIUM: cache: add support for hints-only HTTP caches

The "early-hints" option can now be set to "only", in which case the
cache will only store data relevant to the emission of 103 Early Hints
responses.

Hint records are extracted on the fly from the live response HTX
rather than going through a full-storage-then-strip cycle: the entry
is created as CACHE_EF_STRIPPED directly, with hint records written
past the cache_entry header at storage time. Response bodies are
never stored.

Because entries are stripped from the start, eviction in this mode
never has to strip a full entry; the full LRU stays empty and
cache_make_room() falls through to evicting the oldest stripped entry
when the cache fills up.

The max-object-size check (which gates caching based on the upstream-
announced Content-Length) is bypassed in this mode: the actual stored
entry is just the hint records (typically under 1 KB), so applying it
to the body size would needlessly discard hints for arbitrarily large
responses.

As a hints-only entry is never served as a response, the backend
response is forwarded unchanged in this mode: in particular its Age
header is kept rather than stripped as it is for a stored response.

4 months agoMINOR: cache: factor cache_extract_link_hints out of cache_extract_hints
Maxime Henrion [Tue, 30 Jun 2026 15:32:50 +0000 (11:32 -0400)]
MINOR: cache: factor cache_extract_link_hints out of cache_extract_hints

Move the per-Link-value processing into a new cache_extract_link_hints()
helper. cache_extract_hints() continues to walk the cached row's HDR
blocks and now invokes the helper once per Link header it finds.

No behaviour change. This prepares the helper for reuse by an upcoming
hints-only storage path that extracts Link headers directly from the
live response HTX rather than from a cached row.

4 months agoREGTESTS: cache: validate the emission of 103s
Maxime Henrion [Tue, 2 Jun 2026 13:08:23 +0000 (09:08 -0400)]
REGTESTS: cache: validate the emission of 103s

Add four regtests to validate the behavior of the HTTP cache when early
hints are enabled.

- early_hints.vtc: covers 103 emission on stripped entries and that the
  "no-early-hints" rule keyword suppresses it.
- early_hints_ratio.vtc: covers cap-driven eviction of hints entries when
  the ratio is reached.
- early_hints_parsing.vtc: pins down the (deliberately strict) Link
  header parsing behaviour of link_is_hint() so future relaxations
  cannot silently change hint detection.
- early_hints_multiblock.vtc: checks that hints are still extracted when
  the relevant Link headers span more than one cache block.

4 months agoMINOR: cache: allow customizing ratio for early hints
Maxime Henrion [Mon, 1 Jun 2026 21:12:21 +0000 (17:12 -0400)]
MINOR: cache: allow customizing ratio for early hints

It is now possible to give a "ratio" parameter to the "early-hints"
option to indicate what percentage of blocks to reserve for hints-only
entries. Defaults to 25%.

4 months agoMINOR: cache: allow opting out of early hints at the rule level
Maxime Henrion [Fri, 26 Jun 2026 20:45:23 +0000 (16:45 -0400)]
MINOR: cache: allow opting out of early hints at the rule level

A "cache-use" directive can now specify the "no-early-hints" keyword
to suppress 103 Early Hints emission for matching requests, when used
with a cache that has the "early-hints" setting enabled.

4 months agoMINOR: cache: add a counter for cache hits serving early hints
Maxime Henrion [Tue, 7 Jul 2026 13:10:59 +0000 (09:10 -0400)]
MINOR: cache: add a counter for cache hits serving early hints

Add a cache_hint_hits counter to the per-proxy HTTP stats, incremented
each time the cache emits a 103 Early Hints response. It is reported
in the CSV/typed outputs, on the stats page next to the cache hits,
and exported to prometheus as http_cache_hint_hits_total. Since the
new field changes the shm stats file mapping, its minor version is
bumped along with the object size assertion.

4 months agoMEDIUM: cache: emit early hints if configured to do so
Maxime Henrion [Fri, 26 Jun 2026 20:44:50 +0000 (16:44 -0400)]
MEDIUM: cache: emit early hints if configured to do so

The HTTP cache now supports sending 103 Early Hints responses if
enabled, without the need for explicit per-rule configuration.

Two paths feed the 103 response depending on the matched entry. A
stripped entry (CACHE_EF_STRIPPED) carries its Link records
pre-extracted alongside the cache entry header and is copied out of
the row as-is. A complete entry only carries the cached HTX; the
Link headers are walked on the fly at request time, deliberately
avoiding the extra storage cost of duplicating them alongside the
body.

The on-the-fly path has a cost: a workload where many hits land on
expired complete entries re-parses the cached response on each hit.
To bound this, the first such hit also strips the entry in place
when conditions allow (the hints pool is below its cap, and the row
is not currently being read by another request); subsequent hits for
the same URL then take the cheap pre-extracted path.

To let the cache-use lookup reach that logic, get_entry() now returns
expired entries to callers passing delete_expired=0; such callers are
responsible for checking entry->expire themselves.