]> git.ipfire.org Git - thirdparty/haproxy.git/log
thirdparty/haproxy.git
7 days agoMINOR: buffers: Swap buffers of same size only
Christopher Faulet [Wed, 28 Jan 2026 14:02:20 +0000 (15:02 +0100)] 
MINOR: buffers: Swap buffers of same size only

In b_xfer(), we now take care to swap buffers of the same size only. For
now, it is always the case. But that will change.

7 days agoMINOR: tree-wide: Use the buffer size instead of global setting when possible
Christopher Faulet [Wed, 28 Jan 2026 09:54:41 +0000 (10:54 +0100)] 
MINOR: tree-wide: Use the buffer size instead of global setting when possible

At many places, we rely on global.tune.bufsize value instead of using the buffer
size. For now, it is not a problem. But if we want to be able to deal with
buffers of different sizes, it is good to reduce as far as possible dependencies
on the global value. most of time, we can use b_size() or c_size()
functions. The main change is performed on the error snapshot where the buffer
size was added into the error_snapshot structure.

7 days agoBUG/MEDIUM: jwe: fix timing side-channel and dead code in JWE decryption
David Carlier [Sat, 14 Feb 2026 16:16:58 +0000 (16:16 +0000)] 
BUG/MEDIUM: jwe: fix timing side-channel and dead code in JWE decryption

Fix two issues in JWE token processing:

- Replace memcmp() with CRYPTO_memcmp() for authentication tag
  verification in build_and_check_tag() to prevent timing
  side-channel attacks. Also add a tag length validation check
  before the comparison to avoid potential buffer over-read when
  the decoded tag length doesn't match the expected HMAC half.

- Remove unreachable break statement after JWE_ALG_A256GCMKW case
  in decrypt_cek_aesgcmkw().

7 days agoREORG: stconn: Move functions related to channel buffers to sc_strm.h
Christopher Faulet [Wed, 28 Jan 2026 09:53:22 +0000 (10:53 +0100)] 
REORG: stconn: Move functions related to channel buffers to sc_strm.h

sc_have_buff(), sc_need_buff(), sc_have_room() and sc_need_room() are
related to the buffer's channel. So we can move them in sc_strm.h header
file. In addition, this will be mandatory for the next commit.

7 days agoMINOR: stconn: Add missing SC_FL_NO_FASTFWD flag in sc_show_flags
Christopher Faulet [Tue, 3 Feb 2026 17:32:19 +0000 (18:32 +0100)] 
MINOR: stconn: Add missing SC_FL_NO_FASTFWD flag in sc_show_flags

SC_FL_NO_FASTFWD flag was not listed in sc_show_flags() function. Let's do
so.

This patch could be backported as far as 3.0.

7 days agoBUG/MINOR: http-ana: Stop to wait for body on client error/abort
Christopher Faulet [Thu, 12 Feb 2026 10:24:27 +0000 (11:24 +0100)] 
BUG/MINOR: http-ana: Stop to wait for body on client error/abort

During the message analysis, we must take care to stop wait for the message
body if an error was reported on client side or an abort was detected with
abort-on-close configured (by default now).

The bug was introduced when the "wait-for-body" action was added. Only the
producer state was tested. So, when we were waiting for the request payload,
there was no issue. But when we were waiting for the response payload, error
or abort on client side was not considered.

This patch should be backported to all stable versions.

7 days agoBUG/MEDIUM: shctx: Use the next block when data exactly filled a block
Christopher Faulet [Tue, 3 Feb 2026 06:46:22 +0000 (07:46 +0100)] 
BUG/MEDIUM: shctx: Use the next block when data exactly filled a block

When the hot list was removed in 3.0, a regression was introduced.
Theorically, it is possible to override data in a block when new data are
appended. It happens when data are copied. If the data size is a multiple of
the block size, all data are copied and the last used block is full. But
instead of saving a reference on the next block as the restart point for the
next copies, we keep a reference on the last full one. On the next read, we
reuse this block and old data are crushed. To hit the bug, no new blocks
should be reserved between the two data copy attempts.

Concretely, for now, it seems not possible to hit the bug. But with a block
size set to 1024, if more than 1024 bytes are reseved, with a first copy of
1024 bytes and a second one with remaining data, data in the first block
will be crushed.

So to fix the bug, the reference of the last block used to write data (which
is in fact the next one to use to perform the next copy) is only updated
when a block is full. In that case the next block is used.

This patch should be backported as far as 3.0 after a period of observation.

7 days agoCLEANUP: compression: Remove unused static buffers
Christopher Faulet [Mon, 2 Feb 2026 08:31:37 +0000 (09:31 +0100)] 
CLEANUP: compression: Remove unused static buffers

Since the legacy HTTP code was removed, the global and thread-local buffers,
tmpbuf and zbuf, are no longer used. So let's removed them.

This could be backported, theorically to all supported versions. But at
least it could be good to do so as far as 3.2 as it saves 2 buffers
per-thread.

7 days agoMINOR: flt-trace: Add an option to limit the amount of data forwarded
Christopher Faulet [Mon, 16 Feb 2026 10:42:36 +0000 (11:42 +0100)] 
MINOR: flt-trace: Add an option to limit the amount of data forwarded

"max-fwd <max>" option can now be used to limit the maximum amount of data
forwarded at a time by the filter. It could be handy to make tests.

7 days agoBUG/MINOR: flt-trace: Properly compute length of the first DATA block
Christopher Faulet [Wed, 11 Feb 2026 09:20:12 +0000 (10:20 +0100)] 
BUG/MINOR: flt-trace: Properly compute length of the first DATA block

This bug is quite old. When the length of the first DATA block is computed,
the offset is used instead of the block length minus the offset. It is only
used with random forwarding and there is a test just after to prevent any
issue, so there is no effect.

It could be backported to all stable versions.

7 days agoDEV: term-events: Fix hanshake events decoding
Christopher Faulet [Tue, 17 Feb 2026 06:39:31 +0000 (07:39 +0100)] 
DEV: term-events: Fix hanshake events decoding

Handshakes events were not properly decoded. Only send errors were decoded
as expected, other events were reported with a '-'. It is now fixes.

This patch could be backported as far as 3.2.

7 days agoBUG/MEDIUM: applet: Fix test on shut flags for legacy applets (v2)
Christopher Faulet [Mon, 16 Feb 2026 18:14:57 +0000 (19:14 +0100)] 
BUG/MEDIUM: applet: Fix test on shut flags for legacy applets (v2)

The previous fix was wrong. When shut flags are tested for legacy applets,
to know if the I/O handler can be called or not, we must be sure shut for
reads and for writes are both set to skip the applet I/O handler.

This bug introduced regression, at least for the peer applet and for the DNS
applet.

This patch must be backported with abc1947e1 ("BUG/MEDIUM: applet: Fix test
on shut flags for legacy applets"), so as far as 3.0.

7 days agoBUG/MEDIUM: mux-h1: Stop sending vi fast-forward for unexpected states
Christopher Faulet [Tue, 17 Feb 2026 14:56:19 +0000 (15:56 +0100)] 
BUG/MEDIUM: mux-h1: Stop sending vi fast-forward for unexpected states

If a producer tries to send data via the fast-forward mechanism while the
message is in an unexpected state from the consumer point of view, the
fast-forward is now disabled. Concretely, we now take care that the message
is in its data/tunnel stage to proceed in h1_nego_ff().

By disabling fast-forward in that case, we will automatically fall back on
the regular sending path and be able to handle the error in h1_snd_buf().

This patch should be backported as far as 3.0

7 days agoBUG/MEDIUM: mux-h2/quic: Stop sending via fast-forward if stream is closed
Christopher Faulet [Wed, 18 Feb 2026 08:26:02 +0000 (09:26 +0100)] 
BUG/MEDIUM: mux-h2/quic: Stop sending via fast-forward if stream is closed

If is illegal to send data if the stream is already closed. The case is
properly handled when data are sent via snd_buf(), by draining the data. But
it was still possible to process these data via nego_ff().

So, in this patch, both for the H2 and QUIC multiplexers, the fast-forward
is disabled if the stream is closed and nothing is performed. Doing so, we
will automatically fall back on the regular sending path and be able to
drain data in snd_buf().

Thanks to Mike Walker for his investigation on the subject.

This patch should be backported as far as 3.0.

8 days agoREGTESTS: fix quoting in feature cmd which prevents test execution
Amaury Denoyelle [Tue, 17 Feb 2026 17:27:14 +0000 (18:27 +0100)] 
REGTESTS: fix quoting in feature cmd which prevents test execution

Remove extra quote in feature cmd used to test SSL compatibility with
set_ssl_cafile QUIC regtest. Due to this syntax error, the test was
never executed.

No need to backport.

8 days agoMINOR: mux-quic: add BUG_ON_STRESS() when draining data on closed stream
Amaury Denoyelle [Tue, 17 Feb 2026 17:13:54 +0000 (18:13 +0100)] 
MINOR: mux-quic: add BUG_ON_STRESS() when draining data on closed stream

Add a BUG_ON_STRESS() to be able to detect if data draining is performed
due to early stream closure.

8 days agoBUG/MEDIUM: h3: reject frontend CONNECT as currently not implemented
Amaury Denoyelle [Mon, 16 Feb 2026 15:33:41 +0000 (16:33 +0100)] 
BUG/MEDIUM: h3: reject frontend CONNECT as currently not implemented

HTTP/3 CONNECT transcoding is not properly implemented on the frontend
side. Neither tunnel mode of application nor extended connect are
currently functional.

Clarify this situation by rejecting any CONNETC attempts on the frontend
side. The stream is thus now closed via a RESET_STREAM with error code
REQUEST_REJECTED.

This should be backported to every stable versions.

8 days agoBUG/MAJOR: Revert "MEDIUM: mux-quic: add BUG_ON if sending on locally closed QCS"
Amaury Denoyelle [Mon, 16 Feb 2026 15:41:50 +0000 (16:41 +0100)] 
BUG/MAJOR: Revert "MEDIUM: mux-quic: add BUG_ON if sending on locally closed QCS"

This reverts commit 235e8f1afd7e9753a26051b30c47ecc398ccfd12.

Prior to the above commit, snd_buf callback for QUIC MUX was able to
deal with data even after stream closure. The excess was simply
discarded, as no STREAM frame can be emitted after FIN/RESET_STREAM.
This code was later removed and replaced by a BUG_ON() to ensure snd_buf
is never called after stream closure.

However, this approach is too strict. Indeed, there is nothing in the
haproxy stream architecture which forbids this scheduling, in part
because QUIC MUX is the sole responsible of the stream closure. As such,
it is preferable to revert to the old code to prevent any triggering of
a BUG_ON() failure.

Note that nego_ff does not implement data draining if called after
stream closure. This will be done in a future patch.

Thanks to Mike Walker for his investigation on the subject.

This must be backported up to 2.8.

8 days agoMEDIUM: backend: make "balance random" consider tg local req rate when loads are...
Aurelien DARRAGON [Mon, 16 Feb 2026 15:12:15 +0000 (16:12 +0100)] 
MEDIUM: backend: make "balance random" consider tg local req rate when loads are equal

This is a follow up to b6bdb2553 ("MEDIUM: backend: make "balance random"
consider req rate when loads are equal")

In the above patch, we used the global sess_per_sec metric to choose which
server we should be using. But the original intent was to use the per
thread group statistic.

No backport needed, the previous patch already improved the situation in
3.3, so let's not take the risk of breaking that.

9 days agoBUG/MINOR: ssl: error with ssl-f-use when no "crt"
William Lallemand [Mon, 16 Feb 2026 17:41:40 +0000 (18:41 +0100)] 
BUG/MINOR: ssl: error with ssl-f-use when no "crt"

ssl-f-use lines tries to load a crt file, but the "crt" keyword is not
mandatory. That could lead to crtlist_load_crt() being called with a
NULL path, and trying to do a stat.

In this particular case we don't need to try anything and it's better to
leave with an actual error.

Must be backported as far as 3.2.

9 days agoBUG/MINOR: ssl: clarify ssl-f-use errors in post-section parsing
William Lallemand [Mon, 16 Feb 2026 17:22:53 +0000 (18:22 +0100)] 
BUG/MINOR: ssl: clarify ssl-f-use errors in post-section parsing

crtlist_load_crt() in post_section_frontend_crt_init() won't give
details about the line being parsed, this should be done by the caller.

Modify post_section_frontend_crt_init() to ouput the right error format.

Must be backported to 3.2.

9 days agoBUG/MINOR: ssl: fix leak in ssl-f-use parser upon error
William Lallemand [Mon, 16 Feb 2026 14:56:21 +0000 (15:56 +0100)] 
BUG/MINOR: ssl: fix leak in ssl-f-use parser upon error

cfg_crt_node->filename is leaked on the error path in the ssl-f-use
configuration parser.

Could be backported as far as 3.2

9 days agoBUG/MINOR: ssl: double-free on error path w/ ssl-f-use parser
William Lallemand [Mon, 16 Feb 2026 14:22:47 +0000 (15:22 +0100)] 
BUG/MINOR: ssl: double-free on error path w/ ssl-f-use parser

In post_section_frontend_crt_init(), the crt_entry is populated by the
ssl_conf fromt the cfg_crt_node. On error path, the crt_list is
completely freed, including the ssl_conf structure. But the ssl_conf
structure was already freed when freeing the cfg_crt_node.

Fix the issue by doing a crtlist_dup_ssl_conf(n->ssl_conf) in the
crtlist_entry instead of an assignation.

Fix issue #3268.

Need to be backported as far as 3.2. The previous patch which adds the
crtlist_dup_ssl_conf() declaration is needed.

9 days agoBUG/MINOR: ssl: lack crtlist_dup_ssl_conf() declaration
William Lallemand [Mon, 16 Feb 2026 14:10:35 +0000 (15:10 +0100)] 
BUG/MINOR: ssl: lack crtlist_dup_ssl_conf() declaration

Add lacking crtlist_dup_ssl_conf() declaration in ssl_crt-list.h.

Could be backported if needed.

9 days agoDEV: gdb: use unsigned longs to display pools memory usage
Willy Tarreau [Mon, 16 Feb 2026 10:07:23 +0000 (11:07 +0100)] 
DEV: gdb: use unsigned longs to display pools memory usage

The pools memory usage calculation was done using ints by default, making
it harder to identify large ones. Let's switch to unsigned long for the
size calculations.

11 days agoCLEANUP: deviceatlas: add unlikely hints and minor code tidying
David Carlier [Sat, 14 Feb 2026 13:24:07 +0000 (13:24 +0000)] 
CLEANUP: deviceatlas: add unlikely hints and minor code tidying

Add unlikely() hints on error paths in init, conv and fetch functions.
Remove unnecessary zero-initialization of local buffers that are
always written before use. Fix indentation in da_haproxy_checkinst()
and remove unused loop variable initialization.

11 days agoMINOR: deviceatlas: precompute maxhdrlen to skip oversized headers early
David Carlier [Sat, 14 Feb 2026 13:24:06 +0000 (13:24 +0000)] 
MINOR: deviceatlas: precompute maxhdrlen to skip oversized headers early

Precompute the maximum header name length from the atlas evidence
headers at init and hot-reload time. Use it in da_haproxy_fetch() to
skip headers early that cannot match any known DeviceAtlas evidence
header, avoiding unnecessary string copies and comparisons.

11 days agoMINOR: deviceatlas: define header_evidence_entry in dummy library header
David Carlier [Sat, 14 Feb 2026 14:08:04 +0000 (14:08 +0000)] 
MINOR: deviceatlas: define header_evidence_entry in dummy library header

Add the struct header_evidence_entry definition to the dummy dac.h
to accommodate the ongoing deviceatlas module update which now
iterates over atlas header_priorities to precompute maxhdrlen.
The struct was already referenced by struct da_atlas but lacked
a definition in the dummy header.

11 days agoMINOR: deviceatlas: increase DA_MAX_HEADERS and header buffer sizes
David Carlier [Sat, 14 Feb 2026 13:24:05 +0000 (13:24 +0000)] 
MINOR: deviceatlas: increase DA_MAX_HEADERS and header buffer sizes

Increase DA_MAX_HEADERS from 24 to 32 and hbuf from 24 to 64 to
accommodate current DeviceAtlas data files which may use more headers
and longer header names.

11 days agoMINOR: deviceatlas: check getproptype return and remove pprop indirection
David Carlier [Sat, 14 Feb 2026 13:24:04 +0000 (13:24 +0000)] 
MINOR: deviceatlas: check getproptype return and remove pprop indirection

Check the return value of da_atlas_getproptype() and skip the property
on failure instead of using an uninitialized proptype. Also remove the
unnecessary pprop pointer indirection, using prop directly.

11 days agoBUG/MINOR: deviceatlas: set cache_size on hot-reloaded atlas instance
David Carlier [Sat, 14 Feb 2026 13:24:03 +0000 (13:24 +0000)] 
BUG/MINOR: deviceatlas: set cache_size on hot-reloaded atlas instance

When hot-reloading the atlas in da_haproxy_checkinst(), the configured
cache_size was not applied to the new instance, causing it to use the
default value.

This should be backported to lower branches.

11 days agoBUG/MINOR: deviceatlas: fix deinit to only finalize when initialized
David Carlier [Sat, 14 Feb 2026 13:24:02 +0000 (13:24 +0000)] 
BUG/MINOR: deviceatlas: fix deinit to only finalize when initialized

da_fini() was called unconditionally in deinit_deviceatlas() even when
da_init() was never called. Move it inside the daset check. Also remove
the erroneous shm_unlink() call which could affect the dadwsch shared
memory used by the scheduling process.

This should be backported to lower branches.

11 days agoBUG/MINOR: deviceatlas: fix resource leak on hot-reload compile failure
David Carlier [Sat, 14 Feb 2026 13:24:01 +0000 (13:24 +0000)] 
BUG/MINOR: deviceatlas: fix resource leak on hot-reload compile failure

In da_haproxy_checkinst(), when da_atlas_compile() failed, the cnew
buffer was leaked. Add a free(cnew) in the else branch.

This should be backported to lower branches.

11 days agoBUG/MINOR: deviceatlas: fix double-checked locking race in checkinst
David Carlier [Sat, 14 Feb 2026 13:24:00 +0000 (13:24 +0000)] 
BUG/MINOR: deviceatlas: fix double-checked locking race in checkinst

In da_haproxy_checkinst(), base[0] was checked before acquiring the
lock but not re-checked after. Another thread could have already
processed the reload between the initial check and the lock
acquisition, leading to a race condition.

This should be backported to lower branches.

11 days agoBUG/MINOR: deviceatlas: fix cookie vlen using wrong length after extraction
David Carlier [Sat, 14 Feb 2026 13:23:59 +0000 (13:23 +0000)] 
BUG/MINOR: deviceatlas: fix cookie vlen using wrong length after extraction

In da_haproxy_fetch(), vlen was set from v.len (the raw header value
length) instead of the truncated copy length. Also the cookie-specific
vlen calculation used an incorrect subtraction instead of the actual
extracted cookie value length (pl) returned by
http_extract_cookie_value().

This should be backported to lower branches.

11 days agoBUG/MINOR: deviceatlas: fix off-by-one in da_haproxy_conv()
David Carlier [Sat, 14 Feb 2026 13:23:58 +0000 (13:23 +0000)] 
BUG/MINOR: deviceatlas: fix off-by-one in da_haproxy_conv()

The user-agent string copy had an off-by-one error: the buffer size
limit did not account for the null terminator, and the memcpy length
used i-1 which truncated the last character of the user-agent string.

This should be backported to lower branches.

11 days agoBUG/MEDIUM: deviceatlas: fix resource leaks on init error paths
David Carlier [Sat, 14 Feb 2026 13:23:57 +0000 (13:23 +0000)] 
BUG/MEDIUM: deviceatlas: fix resource leaks on init error paths

When da_atlas_compile() or da_atlas_open() failed in init_deviceatlas(),
atlasimgptr was leaked and da_fini() was never called. Also add a NULL
check on strdup() for the default cookie name with proper cleanup of
the atlas and image pointer on failure.

This should be backported to lower branches.

11 days agoBUG/MINOR: deviceatlas: add NULL checks on strdup() results in config parsers
David Carlier [Sat, 14 Feb 2026 13:23:56 +0000 (13:23 +0000)] 
BUG/MINOR: deviceatlas: add NULL checks on strdup() results in config parsers

Add missing NULL checks after strdup() for the json file path in
da_json_file() and the cookie name in da_properties_cookie().

This should be backported to lower branches.

11 days agoBUG/MINOR: deviceatlas: add missing return on error in config parsers
David Carlier [Sat, 14 Feb 2026 13:23:55 +0000 (13:23 +0000)] 
BUG/MINOR: deviceatlas: add missing return on error in config parsers

da_log_level() and da_cache_size() were missing a return -1 on error,
causing fall-through to the normal return 0 path when invalid values
were provided.

This should be backported to lower branches.

11 days agoDEV: gdb: add a utility to find the post-mortem address from a core
Willy Tarreau [Sat, 14 Feb 2026 09:41:44 +0000 (10:41 +0100)] 
DEV: gdb: add a utility to find the post-mortem address from a core

More and more often, core dumps retrieved on systems that build with
-fPIE by default are becoming unexploitable. Even functions and global
symbols get relocated and gdb cannot figure their final position.
Ironically the post_mortem struct lying in its own section that was
meant to ease its finding is not exempt from this problem.

The only remaining way is to inspect the core to search for the
post-mortem magic, figure its offset from the file and look up the
corresponding virtual address with objdump. This is quite a hassle.

This patch implements a simple utility that opens a 64-bit core dump,
scans the program headers looking for a data segment which contains
the post-mortem magic, and prints it on stdout. It also places the
"pm_init" command alone on its own line to ease copy-pasting into the
gdb console. With this, at least the other commands in this directory
work again and allow to inspect the program's state. E.g:

  $ ./getpm core.57612
  Found post-mortem magic in segment 5:
    Core File Offset: 0xfc600 (0xd5000 + 0x27600)
    Runtime VAddr:    0x5613e52b6600 (0x5613e528f000 + 0x27600)
    Segment Size:     0x28000

  In gdb, copy-paste this line:

     pm_init 0x5613e52b6600

It's worth noting that the program has so few dependencies that it even
builds with nolibc, allowing to upload a static executable into containers
being debugged and lacking development tools and compilers. The build
procedure is indicated inthe source code.

12 days agoMEDIUM: filters: use per-channel filter list when relevant
Aurelien DARRAGON [Thu, 5 Feb 2026 12:55:36 +0000 (13:55 +0100)] 
MEDIUM: filters: use per-channel filter list when relevant

In the historical implementation, all filter related information where
stored at the stream level (using struct strm_flt * context), and filters
iteration was performed at the stream level also.

We identified that this was not ideal and would make the implementation of
future filters more complex since filters ordering should be handled in
a different order during request and response handling for decompression
for instance.

To make such thing possible, in this commit we migrate some channel
specific filter contexts in the channel directly (request or response),
and we implement 2 additional filter lists, one on the request channel
and another on the response channel. The historical stream filter list
is kept as-is because in some contexts only the stream is available and
we have to iterate on all filters. But for functions where we only are
interested in request side or response side filters, we now use dedicated
channel filters list instead.

The only overhead is that the "struct filter" was expanded by two "struct
list".

For now, no change of behavior is expected.

12 days agoMINOR: filters: rework filter iteration for channel related callback functions
Aurelien DARRAGON [Thu, 5 Feb 2026 20:02:03 +0000 (21:02 +0100)] 
MINOR: filters: rework filter iteration for channel related callback functions

Multiple channel related functions have the same construction: they use
list_for_each_entry() to work on a given filter from the stream+channel
combination. In future commits we will try to use filter list from
dedicated channel list instead of the stream one, thus in this patch we
need as a prerequisite to implement and use the flt_list_{start,next} API
to iterate over filter list, giving the API the responsibility to iterate
over the correct list depending on the context, while the calling function
remains free to use the iteration construction it needs. This way we will
be able to easily change the way we iterate over filter list without
duplicating the code for requests and responses.

12 days agoMINOR: filters: rework RESUME_FILTER_* macros as inline functions
Aurelien DARRAGON [Thu, 5 Feb 2026 19:36:23 +0000 (20:36 +0100)] 
MINOR: filters: rework RESUME_FILTER_* macros as inline functions

There is no need to have those helpers defined as macro, and since it
is not mandatory, code maintenance is much easier using functions,
thus let's switch to function definitions.

Also, we change the way we iterate over the list so that the calling
function now has a pseudo API to get and iterate over filter pointers
while keeping control on how they implement the iterating logic.

One benefit of this is that we will also be able to switch between lists
depending on the channel type, which is a prerequisite for upcoming
rework that split the filter list over request and response channels
(commit will follow)

No change of behavior is expected.

13 days agoSCRIPTS: build-vtest: allow to set a TMPDIR and a DESTDIR 20260212-build-vtest flx04/20260212-build-vtest
William Lallemand [Thu, 12 Feb 2026 17:48:09 +0000 (18:48 +0100)] 
SCRIPTS: build-vtest: allow to set a TMPDIR and a DESTDIR

Implement a way to set a destination directory using DESTDIR, and a tmp
directory using TMPDIR.

By default:

- DESTDIR is ../vtest like it was done previously
- TMPDIR  is mktemp -d

Only the vtest binary is copied in DESTDIR.

Example:

TMPDIR=/dev/shm/ DESTDIR=/home/user/.local/bin/ ./scripts/build-vtest.sh

13 days agoMINOR: startup: show the list of detected features at runtime with haproxy -vv
William Lallemand [Thu, 12 Feb 2026 16:49:11 +0000 (17:49 +0100)] 
MINOR: startup: show the list of detected features at runtime with haproxy -vv

Features prefixed by "HAVE_WORKING_" in the haproxy -vv feature list,
are features that are detected during runtime.

This patch splits these features on another line in haproxy -vv. This
line is named "Detected feature list".

13 days agoMINOR: startup: sort the feature list in haproxy -vv
William Lallemand [Thu, 12 Feb 2026 16:41:31 +0000 (17:41 +0100)] 
MINOR: startup: sort the feature list in haproxy -vv

The feature list in haproxy -vv is partly generated from the Makefile
using the USE_* keywords, but it's also possible to add keywords in the
feature list using hap_register_feature(), which adds the keyword at the
end of list. When doing so, the list is not correctly sorted anymore.

This patch fixes the problem by splitting the string using an array of
ist and applying a qsort() on it.

13 days agoMINOR: startup: Add HAVE_WORKING_TCP_MD5SIG in haproxy -vv
William Lallemand [Wed, 11 Feb 2026 14:34:43 +0000 (15:34 +0100)] 
MINOR: startup: Add HAVE_WORKING_TCP_MD5SIG in haproxy -vv

the TCP_MD5SIG ifdef is not enough to check if the feature is usable.
The code might compile but the OS could prevent to use it.

This patch tries to use the TCP_MD5SIG setsockopt before adding
HAVE_WORKING_TCP_MD5SIG in the feature list.  so it would prevent to
start reg-tests if the OS can't run it.

13 days agoREGTESTS: jwt: Add new "jwt_decrypt_jwk" tests
Remi Tricot-Le Breton [Tue, 10 Feb 2026 14:30:01 +0000 (15:30 +0100)] 
REGTESTS: jwt: Add new "jwt_decrypt_jwk" tests

Test the new "jwt_decrypt_jwk" converter that takes a JWK as argument,
either as a string or in a variable.
Only "RSA" and "oct" types are managed for now.

13 days agoMINOR: jwt: Add new jwt_decrypt_jwk converter
Remi Tricot-Le Breton [Tue, 10 Feb 2026 14:30:00 +0000 (15:30 +0100)] 
MINOR: jwt: Add new jwt_decrypt_jwk converter

This converter takes a private key in the JWK format (RFC7517) that can
be provided as a string of via a variable.
The only keys managed for now are of type 'RSA' or 'oct'.

13 days agoMINOR: jwt: Convert an RSA JWK into an EVP_PKEY
Remi Tricot-Le Breton [Tue, 10 Feb 2026 14:29:59 +0000 (15:29 +0100)] 
MINOR: jwt: Convert an RSA JWK into an EVP_PKEY

Add helper functions that take a JWK (JSON representation of an RSA
private key) into an EVP_PKEY (containing the private key).
Those functions are not used yet, they will be used in the upcoming
'jwt_decrypt_jwk' converter.

13 days agoMINOR: ssl: Missing '\n' in error message
Remi Tricot-Le Breton [Wed, 11 Feb 2026 10:11:49 +0000 (11:11 +0100)] 
MINOR: ssl: Missing '\n' in error message

Fix missing '\n' in error message raised when trying to load a password
protected private key.

13 days agoBUG/MAJOR: quic: fix parsing frame type
Amaury Denoyelle [Mon, 9 Feb 2026 08:09:33 +0000 (09:09 +0100)] 
BUG/MAJOR: quic: fix parsing frame type

QUIC frame type is encoded as a varint. Initially, haproxy parsed it as
a single byte, which was enough to cover frames defined in RFC9000.

The code has been extended recently to support multi-bytes encoded
value, in anticipation of QUIC frames extension support. However, there
was no check on the varint format. This is interpreted erroneously as a
PADDING frame as this serves as the initial value. Thus the rest of the
packet is incorrectly handled, with various resulting effects, including
infinite loops and/or crashes.

This patch fixes this by checking the return value of quic_dec_int(). If
varint cannot be parsed, the connection is immediately closed.

This issue is assigned to CVE-2026-26080 report.

This must be backported up to 3.2.

Reported-by: Asim Viladi Oglu Manizada <manizada@pm.me>
13 days agoBUG/MAJOR: quic: reject invalid token
Amaury Denoyelle [Mon, 9 Feb 2026 08:04:13 +0000 (09:04 +0100)] 
BUG/MAJOR: quic: reject invalid token

Token parsing code on INITIAL packet for the NEW_TOKEN format is not
robust enough and may even crash on some rare malformed packets.

This patch fixes this by adding a check on the expected length of the
received token. The packet is now rejected if the token does not match
QUIC_TOKEN_LEN. This check is legitimate as haproxy should only parse
tokens emitted by itself.

This issue has been introduced with the implementation of NEW_TOKEN
tokens parsing required for 0-RTT support.

This issue is assigned to CVE-2026-26081 report.

This must be backported up to 3.0.

Reported-by: Asim Viladi Oglu Manizada <manizada@pm.me>
13 days agoBUG/MINOR: quic: ensure handshake speed up is only run once per conn
Amaury Denoyelle [Wed, 11 Feb 2026 10:34:15 +0000 (11:34 +0100)] 
BUG/MINOR: quic: ensure handshake speed up is only run once per conn

When a duplicated CRYPTO frame is received during handshake, a server
may consider that there was a packet loss and immediately retransmit its
pending CRYPTO data without having to wait for PTO expiration. However,
RFC 9002 indicates that this should only be performed at most once per
connection to avoid excessive packet transmission.

QUIC connection is flagged with QUIC_FL_CONN_HANDSHAKE_SPEED_UP to mark
that a fast retransmit has been performed. However, during the
refactoring on CRYPTO handling with the storage conversion from ncbuf to
ncbmbuf, the check on the flag was accidentely removed. The faulty patch
is the following one :

  commit f50425c021eceb324add6873b58cc5f366554d31
  MINOR: quic: remove received CRYPTO temporary tree storage

This patch adds again the check on QUIC_FL_CONN_HANDSHAKE_SPEED_UP
before initiating fast retransmit. This ensures this is only performed
once per connection.

This must be backported up to 3.3.

13 days agoMINOR: servers: Call process_srv_queue() without lock when possible
Olivier Houchard [Tue, 3 Feb 2026 01:54:56 +0000 (02:54 +0100)] 
MINOR: servers: Call process_srv_queue() without lock when possible

In server_warmup(), call process_srv_queue() only once we released the
server lock, as we don't need it.

13 days agoMINOR: queues: Check minconn first in srv_dynamic_maxconn()
Olivier Houchard [Wed, 11 Feb 2026 06:53:21 +0000 (07:53 +0100)] 
MINOR: queues: Check minconn first in srv_dynamic_maxconn()

In srv_dynamic_maxconn(), we'll decide that the max number of connection
is the server's maxconn if 1) the proxy's number of connection is over
fullconn, or if minconn was not set.
Check if minconn is not set first, as it will be true most of the time,
and as the proxy's "beconn" variable is in a busy cache line, it can be
costly to access it, while minconn/maxconn is in a cache line that
should very rarely change.

2 weeks agoDOC: proxy-proto: underline the packed attribute for struct pp2_tlv_ssl
Willy Tarreau [Wed, 11 Feb 2026 13:46:55 +0000 (14:46 +0100)] 
DOC: proxy-proto: underline the packed attribute for struct pp2_tlv_ssl

Oto Valek rightfully reported in issue #3262 that the proxy-protocol
doc makes no mention of the packed attribute on struct pp2_tlv_ssl,
which is mandatory since fields are not type-aligned in it. Let's
add it in the definition and make an explicit mention about it to
save implementers from wasting their time trying to debug this.

It can be backported.

2 weeks agoCLEANUP: initcall: adjust comments to INITCALL{0,1} macros
Egor Shestakov [Mon, 9 Feb 2026 18:44:37 +0000 (18:44 +0000)] 
CLEANUP: initcall: adjust comments to INITCALL{0,1} macros

It is likely that copy-pasted text was not initially adjusted in the
comments, that is misleading regarding number of arguments.

No backport needed.

2 weeks agoBUG/MINOR: ssl: SSL_CERT_DIR environment variable doesn't affect haproxy 20260210-default-ca flx04/20260210-default-ca
William Lallemand [Tue, 10 Feb 2026 20:31:07 +0000 (21:31 +0100)] 
BUG/MINOR: ssl: SSL_CERT_DIR environment variable doesn't affect haproxy

The documentation of @system-ca specifies that one can overwrite the
value provided by the SSL Library using SSL_CERT_DIR.

However it seems like X509_get_default_cert_dir() is not affected by
this environment variable, and X509_get_default_cert_dir_env() need to
be used in order to get the variable name, and get the value manually.

This could be backported in every stable branches. Note that older
branches don't have the memprintf in ssl_sock.c.

2 weeks agoMINOR: startup: Add the SSL lib verify directory in haproxy -vv
William Lallemand [Tue, 10 Feb 2026 19:36:14 +0000 (20:36 +0100)] 
MINOR: startup: Add the SSL lib verify directory in haproxy -vv

SSL libraries built manually might lack the right
X509_get_default_cert_dir() value.

The common way to fix the problem is to build openssl with
./configure --openssldir=/etc/ssl/

In order to verify this setting, output it with haproxy -vv.

2 weeks agoMINOR: activity: allow to switch per-task lock/memory profiling at runtime
Willy Tarreau [Tue, 10 Feb 2026 15:57:55 +0000 (16:57 +0100)] 
MINOR: activity: allow to switch per-task lock/memory profiling at runtime

Given that we already have "set profiling task", it's easy to permit to
enable/disable the lock and/or memory profiling at run time. However, the
change will only be applied next time the task profiling will be switched
from off/auto to on.

The patch is very minor and is best viewed with git show -b because it
indents a whole block that moves in a "if" clause.

This can be backported to 3.3 along with the two previous patches.

2 weeks agoMEDIUM: activity: apply and use new finegrained task profiling settings
Willy Tarreau [Tue, 10 Feb 2026 13:17:36 +0000 (14:17 +0100)] 
MEDIUM: activity: apply and use new finegrained task profiling settings

In continuity of previous patch, this one makes use of the new profiling
flags. For this, based on the global "profiling" setting, when switching
profiling on, we set or clear two flags on the thread context,
TH_FL_TASK_PROFILING_L and TH_FL_TASK_PROFILING_M to indicate whether
lock profiling and/or malloc profiling are desired when profiling is
enabled. These flags are checked along with TH_FL_TASK_PROFILING to
decide when to collect time around a lock or a malloc. And by default
we're back to the behavior of 3.2 in that neither lock nor malloc times
are collected anymore.

This is sufficient to see the CPU usage spent in the VDSO to significantly
drop from 22% to 2.2% on a highly loaded system.

This should be backported to 3.3 along with the previous patch.

2 weeks agoMINOR: activity: support setting/clearing lock/memory watching for task profiling
Willy Tarreau [Tue, 10 Feb 2026 07:30:05 +0000 (08:30 +0100)] 
MINOR: activity: support setting/clearing lock/memory watching for task profiling

Damien Claisse reported in issue #3257 a performance regression between
3.2 and 3.3 when task profiling is enabled, more precisely in relation
with the following patches were merged:

  98cc815e3e ("MINOR: activity: collect time spent with a lock held for each task")
  503084643f ("MINOR: activity: collect time spent waiting on a lock for each task")
  9d8c2a888b ("MINOR: activity: collect CPU time spent on memory allocations for each task")

The issue mostly comes from the first patches. What happens is that the
local time is taken when entering and leaving each lock, which costs a
lot on a contended system. The problem here is the lack of finegrained
settings for lock and malloc profiling.

This patch introduces a better approach. The task profiler goes back to
its default behavior in on/auto modes, but the configuration now accepts
new extra options "lock", "no-lock", "memory", "no-memory" to precisely
indicate other timers to watch for each task when profiling turns on.

This is achieved by setting two new flags HA_PROF_TASKS_LOCK and
HA_PROF_TASKS_MEM in the global "profiling" variable.

This patch only parses the new values and assigns them to the global
variable from the config file for now. The doc was updated.

2 weeks agoCLEANUP: haproxy: fix bad line wrapping in run_poll_loop()
Willy Tarreau [Tue, 10 Feb 2026 13:09:54 +0000 (14:09 +0100)] 
CLEANUP: haproxy: fix bad line wrapping in run_poll_loop()

Commit 3674afe8a0 ("BUG/MEDIUM: threads: Atomically set TH_FL_SLEEPING
and clr FL_NOTIFIED") accidentally left a strange-looking line wrapping
making one think of an editing mistake, let's fix it and keep it on a
single line given that even indented wrapping is almost as large.

This can be backported with the fix above till 2.8 to keep the patch
context consistent between versions.

2 weeks agoBUG/MEDIUM: lb-chash: always properly initialize lb_nodes with dynamic servers
Willy Tarreau [Tue, 10 Feb 2026 06:10:09 +0000 (07:10 +0100)] 
BUG/MEDIUM: lb-chash: always properly initialize lb_nodes with dynamic servers

An issue was introduced in 3.0 with commit faa8c3e024 ("MEDIUM: lb-chash:
Deterministic node hashes based on server address"): the new server_key
field and lb_nodes entries initialization were not updated for servers
added at run time with "add server": server_key remains zero and the key
used in lb_node remains the one depending only on the server's ID.

This will cause trouble when adding new servers with consistent hashing,
because the hash-key will be ignored until the server's weight changes
and the key difference is detected, leading to its recalculation.

This is essentially caused by the poorly placed lb_nodes initialization
that is specific to lb-chash and had to be replicated in the code dealing
with server addition.

This commit solves the problem by adding a new ->server_init() function
in the lbprm proxy struct, that is called by the server addition code.
This also allows to abandon the complex check for LB algos that was
placed there for that purpose. For now only lb-chash provides such a
function, and calls it as well during initial setup. This way newly
added servers always use the correct key now.

While it should also theoretically have had an impact on servers added
with the "random" algorithm, it's unlikely that the difference between
proper server keys and those based on their ID could have had any visible
effect.

This patch should be backported as far as 3.0. The backport may be eased
by a preliminary backport of previous commit "CLEANUP: lb-chash: free
lb_nodes from chash's deinit(), not global", though this is not strictly
necessary if context is manually adjusted.

2 weeks agoCLEANUP: lb-chash: free lb_nodes from chash's deinit(), not global
Willy Tarreau [Tue, 10 Feb 2026 05:49:24 +0000 (06:49 +0100)] 
CLEANUP: lb-chash: free lb_nodes from chash's deinit(), not global

There's an ambuity on the ownership of lb_nodes in chash, it's allocated
by chash but freed by the server code in srv_free_params() from srv_drop()
upon deinit. Let's move this free() call to a chash-specific function
which will own the responsibility for doing this instead. Note that
the .server_deinit() callback is properly called both on proxy being
taken down and on server deletion.

2 weeks agoBUG/MINOR: proxy: fix default ALPN bind settings
Amaury Denoyelle [Mon, 9 Feb 2026 12:36:59 +0000 (13:36 +0100)] 
BUG/MINOR: proxy: fix default ALPN bind settings

For "add backend" implementation, postparsing code in
check_config_validity() from cfgparse.c has been extracted in a new
dedicated function named proxy_finalize() into proxy.c.

This has caused unexpected compilation issue as in the latter file
TLSEXT_TYPE_application_layer_protocol_negotiation macro may be
undefined, in particular when building without QUIC support. Thus, code
related to default ALPN on binds is discarded after the preprocessing
stage.

Fix this by including openssl-compat header file into proxy source file.
This should be sufficient to ensure SSL related defines are properly
included.

This should fix recent issues on SSL regtests.

No need to backport.

2 weeks agoMINOR: net_helper: extend the ip.fp output with an option presence mask
Willy Tarreau [Mon, 9 Feb 2026 08:06:38 +0000 (09:06 +0100)] 
MINOR: net_helper: extend the ip.fp output with an option presence mask

Emeric suggested that it's sometimes convenient to instantly know if a
client has advertised support for window scaling or timestamps for
example. While the info is present in the TCP options output, it's hard
to extract since it respects the options order.

So here we're extending the 56-bit fingerprint with 8 extra bits that
indicate the presence of options 2..8, and any option above 9 for the
last bit. In practice this is sufficient since higher options are not
commonly used. Also TCP option 5 is normally not sent on the SYN (SACK,
only SACK_perm is sent), and echo options 6 & 7 are no longer used
(replaced with timestamps). These fields might be repurposed in the
future if some more meaningful options are to be mapped (e.g. MPTCP,
TFO cookie, auth).

2 weeks agoBUG/MINOR: proxy: fix null dereference in "add backend" handler
Amaury Denoyelle [Fri, 6 Feb 2026 20:28:42 +0000 (21:28 +0100)] 
BUG/MINOR: proxy: fix null dereference in "add backend" handler

When a backend is created at runtime, the new proxy instance is inserted
at the end of proxies_list. This operation is buggy if this list is
empty : the code causes a null dereference which will lead to a crash.
This causes the following compilation error :

  CC      src/proxy.o
src/proxy.c: In function 'cli_parse_add_backend':
src/proxy.c:4933:36: warning: null pointer dereference [-Wnull-dereference]
 4933 |                 proxies_list->next = px;
      |                 ~~~~~~~~~~~~~~~~~~~^~~~

This patch fixes this issue. Note that in reality it cannot occur at
this moment as proxies_list cannot be empty (haproxy requires at least
one frontend to start, and the list also always contains internal
proxies).

No need to backport.

2 weeks agoBUG/MINOR: proxy: fix clang build error on "add backend" handler
Amaury Denoyelle [Fri, 6 Feb 2026 20:11:37 +0000 (21:11 +0100)] 
BUG/MINOR: proxy: fix clang build error on "add backend" handler

This patch fixes the following compilation error :
  src/proxy.c:4954:12: error: format string is not a string literal
        (potentially insecure) [-Werror,-Wformat-security]
   4954 |         ha_notice(msg);
        |                   ^~~

No need to backport.

2 weeks agoREGTESTS: add dynamic backend creation test
Amaury Denoyelle [Mon, 2 Feb 2026 09:52:07 +0000 (10:52 +0100)] 
REGTESTS: add dynamic backend creation test

Add a new regtests to validate backend creation at runtime. A server is
then added and requests made to validate the newly created instance
before (with force-be-switch) and after publishing.

2 weeks agoMINOR: proxy: assign dynamic proxy ID
Amaury Denoyelle [Tue, 23 Dec 2025 15:15:47 +0000 (16:15 +0100)] 
MINOR: proxy: assign dynamic proxy ID

Implement proxy ID generation for dynamic backends. This is performed
through the already function existing proxy_get_next_id().

As an optimization, lookup will performed starting from a global
variable <dynpx_next_id>. It is initialized to the greatest ID assigned
after parsing, and updated each time a backend instance is created. When
backend deletion will be implemented, it could be lowered to the newly
available slot.

2 weeks agoMEDIUM: proxy: implement dynamic backend creation
Amaury Denoyelle [Thu, 18 Dec 2025 08:51:27 +0000 (09:51 +0100)] 
MEDIUM: proxy: implement dynamic backend creation

Implement the required operations for "add backend" handler. This
requires a new proxy allocation, settings copy from the specified
default instance and proxy config finalization. All handlers registered
via REGISTER_POST_PROXY_CHECK() are also called on the newly created
instance.

If no error were encountered, the newly created proxy is finally
attached in the proxies list.

2 weeks agoMINOR: proxy: check default proxy compatibility on "add backend"
Amaury Denoyelle [Fri, 6 Feb 2026 12:51:02 +0000 (13:51 +0100)] 
MINOR: proxy: check default proxy compatibility on "add backend"

This commits completes "add backend" handler with some checks performed
on the specified default proxy instance. These are additional checks
outside of the already existing inheritance rules, specific to dynamic
backends.

For now, a default proxy is considered not compatible if it is not in
mode TCP/HTTP. Also, a default proxy is rejected if it references HTTP
errors. This limitation may be lifted in the future, when HTTP errors
are partiallay reworked.

2 weeks agoMINOR: proxy: parse guid on dynamic backend creation
Amaury Denoyelle [Tue, 13 Jan 2026 15:13:27 +0000 (16:13 +0100)] 
MINOR: proxy: parse guid on dynamic backend creation

Defines an extra optional GUID argument for "add backend" command. This
can be useful as it is not possible to define it via a default proxy
instance.

2 weeks agoMINOR: proxy: parse mode on dynamic backend creation
Amaury Denoyelle [Mon, 12 Jan 2026 14:25:52 +0000 (15:25 +0100)] 
MINOR: proxy: parse mode on dynamic backend creation

Add an optional "mode" argument to "add backend" CLI command. This
argument allows to specify if the backend is in TCP or HTTP mode.

By default, it is mandatory, unless the inherited default proxy already
explicitely specifies the mode. To differentiate if TCP mode is implicit
or explicit, a new proxy flag PR_FL_DEF_EXPLICIT_MODE is defined. It is
set for every defaults instances which explicitely defined their mode.

2 weeks agoMINOR: proxy: define "add backend" handler
Amaury Denoyelle [Wed, 17 Dec 2025 09:57:40 +0000 (10:57 +0100)] 
MINOR: proxy: define "add backend" handler

Define a basic CLI handler for "add backend".

For now, this handler only performs a parsing of the name argument and
return an error if a duplicate already exists. It runs under thread
isolation, to guarantee thread safety during the proxy creation.

This feature is considered in development. CLI command requires to set
experimental-mode.

2 weeks agoMINOR: backend: add function to check support for dynamic servers
Amaury Denoyelle [Fri, 6 Feb 2026 06:40:59 +0000 (07:40 +0100)] 
MINOR: backend: add function to check support for dynamic servers

Move backend compatibility checks performed during 'add server' in a
dedicated function be_supports_dynamic_srv(). This should simplify
addition of future restriction.

This function will be reused when implementing backend creation at
runtime.

2 weeks agoMINOR: proxy: refactor mode parsing
Amaury Denoyelle [Mon, 12 Jan 2026 13:47:51 +0000 (14:47 +0100)] 
MINOR: proxy: refactor mode parsing

Define a new utility function str_to_proxy_mode() which is able to
convert a string into the corresponding proxy mode if possible. This new
function is used for the parsing of "mode" configuration proxy keyword.

This patch will be reused for dynamic backend implementation, in order
to parse a similar "mode" argument via a CLI handler.

2 weeks agoMINOR: proxy: refactor proxy inheritance of a defaults section
Amaury Denoyelle [Mon, 22 Dec 2025 10:59:33 +0000 (11:59 +0100)] 
MINOR: proxy: refactor proxy inheritance of a defaults section

If a proxy is referencing a defaults instance, some checks must be
performed to ensure that inheritance will be compatible. Refcount of the
defaults instance may also be incremented if some settings cannot be
copied. This operation is performed when parsing a new proxy of defaults
section which references a defaults, either implicitely or explicitely.

This patch extracts this code into a dedicated function named
proxy_ref_defaults(). This in turn may call defaults_px_ref()
(previously called proxy_ref_defaults()) to increment its refcount.

The objective of this patch is to be able to reuse defaults inheritance
validation for dynamic backends created at runtime, outside of the
parsing code.

2 weeks agoMINOR: cfgparse: move proxy post-init in a dedicated function
Amaury Denoyelle [Fri, 30 Jan 2026 15:31:04 +0000 (16:31 +0100)] 
MINOR: cfgparse: move proxy post-init in a dedicated function

A lot of proxies initialization code is delayed on post-parsing stage,
as it depends on the configuration fully parsed. This is performed via a
loop on proxies_list.

Extract this code in a dedicated function proxy_finalize(). This patch
will be useful for dynamic backends creation.

Note that for the moment the code has been extracted as-is. With each
new features, some init code was added there. This has become a giant
loop with no real ordering. A future patch may provide some cleanup in
order to reorganize this.

2 weeks agoMINOR: cfgparse: validate defaults proxies separately
Amaury Denoyelle [Tue, 3 Feb 2026 10:09:42 +0000 (11:09 +0100)] 
MINOR: cfgparse: validate defaults proxies separately

Default proxies validation occurs during post-parsing. The objective is
to report any tcp/http-rules which could not behave as expected.

Previously, this was performed while looping over standard proxies list,
when such proxy is referencing a default instance. This was enough as
only named referenced proxies were kept after parsing. However, this is
not the case anymore in the context of dynamic backends creation at
runtime.

As such, this patch now performs validation on every named defaults
outside of the standard proxies list loop. This should not cause any
behavior difference, as defaults are validated without using the proxy
which relies on it.

Along with this change, PR_FL_READY proxy flag is now removed. Its usage
was only really needed for defaults, to avoid validating a same instance
multiple times. With the validation of defaults in their own loop, it is
now redundant.

2 weeks agoBUG/MINOR: startup: handle a possible strdup() failure
Egor Shestakov [Thu, 5 Feb 2026 08:55:58 +0000 (08:55 +0000)] 
BUG/MINOR: startup: handle a possible strdup() failure

Fix unhandled strdup() failure when initializing global.log_tag.

Bug was introduced with the fix UAF for global progname pointer from
351ae5dbe. So it must be backported as far as 3.1.

2 weeks agoBUG/MINOR: startup: fix allocation error message of progname string
Egor Shestakov [Thu, 5 Feb 2026 08:55:57 +0000 (08:55 +0000)] 
BUG/MINOR: startup: fix allocation error message of progname string

Initially when init_early was introduced the progname string was a local
used for temporary storage of log_tag. Now it's global and detached from
log_tag enough. Thus, in the past we could inform that log_tag
allocation has been failed but not now.

Must be backported since the progname string became global, that is
v3.1-dev9-96-g49772c55e

2 weeks agoBUG/MEDIUM: threads: Differ checking the max threads per group number
Olivier Houchard [Fri, 6 Feb 2026 01:59:14 +0000 (02:59 +0100)] 
BUG/MEDIUM: threads: Differ checking the max threads per group number

Differ checking the max threads per group number until we're done
parsing the configuration file, as it may be set after a "thread-group-
directive. Otherwise the default value of 64 will be used, even if there
is a max-threads-per-group directive.

This should be backported to 3.3.

2 weeks agoBUG/MINOR: threads: Initialize maxthrpertgroup earlier.
Olivier Houchard [Fri, 6 Feb 2026 01:49:26 +0000 (02:49 +0100)] 
BUG/MINOR: threads: Initialize maxthrpertgroup earlier.

Give global.maxthrpertgroup its default value at global creation,
instead of later when we're trying to detect the thread count.
It is used when verifying the configuration file validity, and if it was
not set in the config file, in a few corner cases, the value of 0 would
be used, which would then reject perfectly fine configuration files.

This should be backported to 3.3.

3 weeks agoDOC: internals: addd mworker V3 internals
William Lallemand [Wed, 4 Feb 2026 15:30:40 +0000 (16:30 +0100)] 
DOC: internals: addd mworker V3 internals

Document the mworker V3 implementation introduced in HAProxy 3.1.
Explains the rationale behind moving configuration parsing out of the
master process to improve robustness.

Could be backported to 3.1.

3 weeks ago[RELEASE] Released version 3.4-dev4 v3.4-dev4
Willy Tarreau [Wed, 4 Feb 2026 13:59:47 +0000 (14:59 +0100)] 
[RELEASE] Released version 3.4-dev4

Released version 3.4-dev4 with the following main changes :
    - BUG/MEDIUM: hlua: fix invalid lua_pcall() usage in hlua_traceback()
    - BUG/MINOR: hlua: consume error object if ignored after a failing lua_pcall()
    - BUG/MINOR: promex: Detach promex from the server on error dump its metrics dump
    - BUG/MEDIUM: mux-h1: Skip UNUSED htx block when formating the start line
    - BUG/MINOR: proto_tcp: Properly report support for HAVE_TCP_MD5SIG feature
    - BUG/MINOR: config: check capture pool creations for failures
    - BUG/MINOR: stick-tables: abort startup on stk_ctr pool creation failure
    - MEDIUM: pools: better check for size rounding overflow on registration
    - DOC: reg-tests: update VTest upstream link in the starting guide
    - BUG/MINOR: ssl: Properly manage alloc failures in SSL passphrase callback
    - BUG/MINOR: ssl: Encrypted keys could not be loaded when given alongside certificate
    - MINOR: ssl: display libssl errors on private key loading
    - BUG/MAJOR: applet: Don't call I/O handler if the applet was shut
    - MINOR: ssl: allow to disable certificate compression
    - BUG/MINOR: ssl: fix error message of tune.ssl.certificate-compression
    - DOC: config: mention some possible TLS versions restrictions for kTLS
    - OPTIM: server: move queueslength in server struct
    - OPTIM: proxy: separate queues fields from served
    - OPTIM: server: get rid of the last use of _ha_barrier_full()
    - DOC: config: mention that idle connection sharing is per thread-group
    - MEDIUM: h1: strictly verify quoting in chunk extensions
    - BUG/MINOR: config/ssl: fix spelling of "expose-experimental-directives"
    - BUG/MEDIUM: ssl: fix msg callbacks on QUIC connections
    - MEDIUM: ssl: remove connection from msg callback args
    - MEDIUM: ssl: porting to X509_STORE_get1_objects() for OpenSSL 4.0
    - REGTESTS: ssl: make reg-tests compatible with OpenSSL 4.0
    - DOC: internals: cleanup few typos in master-worker documentation
    - BUG/MEDIUM: applet: Fix test on shut flags for legacy applets
    - MINOR: quic: Fix build with USE_QUIC_OPENSSL_COMPAT
    - MEDIUM: tcpcheck: add post-80 option for mysql-check to support MySQL 8.x
    - BUG/MEDIUM: threads: Atomically set TH_FL_SLEEPING and clr FL_NOTIFIED
    - BUG/MINOR: cpu-topo: count cores not cpus to distinguish core types
    - DOC: config: mention the limitation on server id range for consistent hash
    - MEDIUM: backend: make "balance random" consider req rate when loads are equal
    - BUG/MINOR: config: Fix setting of alt_proto

3 weeks agoBUG/MINOR: config: Fix setting of alt_proto
Aperence [Sat, 31 Jan 2026 22:08:44 +0000 (23:08 +0100)] 
BUG/MINOR: config: Fix setting of alt_proto

This patch fixes the bug presented in issue #3254
(https://github.com/haproxy/haproxy/issues/3254), which
occured on FreeBSD when using a stream socket for in
nameserver section. This bug occured due to an incorrect
reset of the alt_proto for a stream socket when the default
socket is created as a datagram socket. This patch fixes
this bug by doing a late assignment to alt_proto when
a datagram socket is requested, leaving only the modification
of alt_proto done by mptcp. Additional documentation
for the use of alt_proto has also been added to
clarify the use of the alt_proto variable.

3 weeks agoMEDIUM: backend: make "balance random" consider req rate when loads are equal
Willy Tarreau [Fri, 30 Jan 2026 12:41:08 +0000 (13:41 +0100)] 
MEDIUM: backend: make "balance random" consider req rate when loads are equal

As reported by Damien Claisse and Cédric Paillet, the "random" LB
algorithm can become particularly unfair with large numbers of servers
having few connections. It's indeed fairly common to see many servers
with zero connection in a thousand-server large farm, and in this case
the P2C algo consisting in checking the servers' loads doesn't help at
all and is basically similar to random(1). In this case, we only rely
on the distribution of server IDs in the random space to pick the best
server, but it's possible to observe huge discrepancies.

An attempt to model the problem clearly shows that with 1600 servers
with weight 10, for 1 million requests, the lowest loaded ones will
take 300 req while the most loaded ones will get 780, with most of
the values between 520 and 700.

In addition, only the first 28 lower bits of server IDs are used for
the key calculation, which means that node keys are more determinist.
Setting random keys in the lowest 28 bits only better packs values
with min around 530 and max around 710, with values mostly between
550 and 680.

This can only be compensated by increasing weights and draws without
being a perfect fix either. At 4 draws, the min is around 560 and the
max around 670, with most values bteween 590 and 650.

This patch takes another approach to this problem: when servers are on
tie regarding their loads, instead of arbitrarily taking the second one,
we now compare their current request rates, which is updated all the
time and smoothed over one second, and we pick the server with the
lowest request rate. Now with 2 draws, the curve is mostly flat, with
the min at 580 and the max at 628, and almost all values between 611
and 625. And 4 draws exclusively gives values from 614 to 624.

Other points will need to be addressed separately (bits of server ID,
maybe refine the hash algorithm), but these ones would affect how
caches are selected, and cannot be changed without an extra option.
For random however we can perform a change without impacting anyone.

This should be backported, probably only to 3.3 since it's where the
"random" algo became the default.

3 weeks agoDOC: config: mention the limitation on server id range for consistent hash
Willy Tarreau [Wed, 4 Feb 2026 09:44:30 +0000 (10:44 +0100)] 
DOC: config: mention the limitation on server id range for consistent hash

When using "hash-type consistent", we default to using the server's ID
as the insertion key. However, that key is scaled to avoid collisions
when inserting multiple slots for a server (16 per weight unit), and
that scaling loses the 4 topmost bits of the ID, so the only effective
range of IDs is 1..268435456, and anything above will provide the same
hashing keys again.

Let's mention this in the documentation, and also remind that it can
affect "balance random". This can be backported to all versions.

3 weeks agoBUG/MINOR: cpu-topo: count cores not cpus to distinguish core types
Willy Tarreau [Mon, 2 Feb 2026 16:55:57 +0000 (17:55 +0100)] 
BUG/MINOR: cpu-topo: count cores not cpus to distinguish core types

The per-cpu capacity of a cluster was taken into account since 3.2 with
commit 6c88e27cf4 ("MEDIUM: cpu-topo: change "performance" to consider
per-core capacity").

In cpu_policy_performance() and cpu_policy_efficiency(), we're trying
to figure which cores have more capacity than others by comparing their
cluster's average capacity. However, contrary to what the comment says,
we're not averaging per core but per cpu, which makes a difference for
CPUs mixing SMT with non-SMT cores on the same SoC, such as intel's 14th
gen CPUs. Indeed, on a machine where cpufreq is not enabled, all CPUs
can be reported with a capacity of 1024, resulting in a big cluster of
16*1024, and 4 small clusters of 4*1024 each, giving an average of 1024
per CPU, making it impossible to distinguish one from the other. In this
situation, both "cpu-policy performance" and "cpu-policy efficiency"
enable all cores.

But this is wrong, what needs to be taken into account in the divide is
the number of *cores*, not *cpus*, that allows to distinguish big from
little clusters. This was not noticeable on the ARM machines the commit
above aimed at fixing because there, the number of CPUs equals the number
of cores. And on an x86 machine with cpu_freq enabled, the frequencies
continue to help spotting which ones are big/little.

By using nb_cores instead of nb_cpus in the comparison and in the avg_capa
compare function, it properly works again on x86 without affecting other
machines with 1 CPU per core.

This can be backported to 3.2.

3 weeks agoBUG/MEDIUM: threads: Atomically set TH_FL_SLEEPING and clr FL_NOTIFIED
Olivier Houchard [Wed, 4 Feb 2026 01:46:36 +0000 (01:46 +0000)] 
BUG/MEDIUM: threads: Atomically set TH_FL_SLEEPING and clr FL_NOTIFIED

When we're about to enter polling, atomically set TH_FL_SLEEPING and
remove TH_FL_NOTIFIED, instead of doing it in sequence. Otherwise,
another thread may sett that both the TH_FL_SLEEPING and the
TH_FL_NOTIFIED bits are set, and don't wake up the thread then it should
be doing that.
This prevents a bug where a thread is sleeping while it should be
handling a new connection, which can happen if there are very few
incoming connection. This is easy to reproduce when using only two
threads, and injecting with only one connection, the connection may then
never be handled.

This should be backported up to 2.8.

3 weeks agoMEDIUM: tcpcheck: add post-80 option for mysql-check to support MySQL 8.x
Hyeonggeun Oh [Mon, 2 Feb 2026 13:31:33 +0000 (22:31 +0900)] 
MEDIUM: tcpcheck: add post-80 option for mysql-check to support MySQL 8.x

This patch adds a new 'post-80' option that sets the
CLIENT_PLUGIN_AUTH (0x00080000) capability flag
and explicitly specifies mysql_native_password as
the authentication plugin in the handshake response.

This patch also addes documentation content for post-80 option
support in MySQL 8.x version. Which handles new default auth
plugin caching_sha2_password.

MySQL 8.0 changed the default authentication plugin from
mysql_native_password to caching_sha2_password.
The current mysql-check implementation only supports pre-41
and post-41 client auth protocols, which lack the CLIENT_PLUGIN_AUTH
capability flag. When HAProxy sends a post-41 authentication
packet to a MySQL 8.x server, the server responds with error 1251:
"Client does not support authentication protocol requested by server".

The new client capabilities for post-80 are:
- CLIENT_PROTOCOL_41 (0x00000200)
- CLIENT_SECURE_CONNECTION (0x00008000)
- CLIENT_PLUGIN_AUTH (0x00080000)

Usage example:
backend mysql_servers
option mysql-check user haproxy post-80
server db1 192.168.1.10:3306 check

The health check user must be created with mysql_native_password:
CREATE USER 'haproxy'@'%' IDENTIFIED WITH mysql_native_password BY '';

This addresses https://github.com/haproxy/haproxy/issues/2934.

3 weeks agoMINOR: quic: Fix build with USE_QUIC_OPENSSL_COMPAT
Olivier Houchard [Tue, 3 Feb 2026 03:02:46 +0000 (04:02 +0100)] 
MINOR: quic: Fix build with USE_QUIC_OPENSSL_COMPAT

Commit fa094d0b619343f61fab877ef65f43b404262dd9 changed the msg callback
args, but forgot to fix quic_tls_msg_callback() accordingly, so do that,
and remove the unused struct connection paramter.

3 weeks agoBUG/MEDIUM: applet: Fix test on shut flags for legacy applets
Christopher Faulet [Fri, 30 Jan 2026 08:51:00 +0000 (09:51 +0100)] 
BUG/MEDIUM: applet: Fix test on shut flags for legacy applets

A regression was introduced in the commit 0ea601127 ("BUG/MAJOR: applet: Don't
call I/O handler if the applet was shut"). The test on shut flags for legacy
applets is inverted.

It should be harmeless on 3.4 and 3.3 because all applets were converted. But
this fix is mandatory for 3.2 and older.

The patch must be backported as far as 3.0 with the commit above.

3 weeks agoDOC: internals: cleanup few typos in master-worker documentation
Egor Shestakov [Thu, 29 Jan 2026 17:15:33 +0000 (17:15 +0000)] 
DOC: internals: cleanup few typos in master-worker documentation

s/mecanism/mechanism
s/got ride/got rid
s/traditionnal/traditional

One typo is confusion between master and worker that results to a
semantic mistake in the sentence:

"...the master will emit an "exit-on-failure" error and will kill every
workers with a SIGTERM and exits with the same error code than the
failed [-master-]{+worker+}..."

Should be backported as far as 3.1.

3 weeks agoREGTESTS: ssl: make reg-tests compatible with OpenSSL 4.0
William Lallemand [Thu, 29 Jan 2026 14:18:08 +0000 (15:18 +0100)] 
REGTESTS: ssl: make reg-tests compatible with OpenSSL 4.0

OpenSSL 4.0 changed the way it stores objects in X509_STORE structures
and are not allowing anymore to iterate on objects in insertion order.

Meaning that the order of the object are not the same before and after
OpenSSL 4.0, and the reg-tests need to handle both cases.

3 weeks agoMEDIUM: ssl: porting to X509_STORE_get1_objects() for OpenSSL 4.0
William Lallemand [Mon, 24 Nov 2025 20:44:46 +0000 (21:44 +0100)] 
MEDIUM: ssl: porting to X509_STORE_get1_objects() for OpenSSL 4.0

OpenSSL 4.0 is deprecating X509_STORE_get0_objects().

Every occurence of X509_STORE_get0_objects() was first replaced by
X509_STORE_get1_objects().
This changes the ref count of the STACK_OF(X509_OBJECT) everywhere, and
need it to be sk_X509_OBJECT_pop_free(objs, X509_OBJECT_free) each time.

X509_STORE_get1_objects() is not available in AWS-LC, OpenSSL < 3.2,
LibreSSL and WolfSSL, so we need to still be compatible with get0.
To achieve this, 2 macros were added X509_STORE_getX_objects() and
sk_X509_OBJECT_popX_free(), these macros will use either the get0 or the
get1 macro depending on their availability. In the case of get0,
sk_X509_OBJECT_popX_free() will just do nothing instead of trying to
free.

Don't backport that unless really needed if we want to be compatible
with OpenSSL 4.0. It changes all the refcounts.

3 weeks agoMEDIUM: ssl: remove connection from msg callback args
Amaury Denoyelle [Wed, 28 Jan 2026 09:37:38 +0000 (10:37 +0100)] 
MEDIUM: ssl: remove connection from msg callback args

SSL msg callbacks are used for notification about sent/received SSL
messages. Such callbacks are registered via
ssl_sock_register_msg_callback().

Prior to this patch, connection was passed as first argument of these
callbacks. However, most of them do not use it. Worst, this may lead to
confusion as connection can be NULL in QUIC context.

This patch cleans this by removing connection argument. As an
alternative, connection can be retrieved in callbacks if needed using
ssl_sock_get_conn() but the code must be ready to deal with potential
NULL instances. As an example, heartbeat parsing callback has been
adjusted in this manner.