haproxy-3.0.git
4 days agoBUG/MAJOR: lb-chash: fix key calculation when using default hash-key id
Willy Tarreau [Thu, 16 Oct 2025 08:30:57 +0000 (10:30 +0200)]
BUG/MAJOR: lb-chash: fix key calculation when using default hash-key id

A subtle regression was introduced in 3.0 by commit faa8c3e02 ("MEDIUM:
lb-chash: Deterministic node hashes based on server address"). When keys
are calculated from the server's ID (which is the default), due to the
reorganisation of the code, the key ended up being hashed twice instead
of being multiplied by the scaling range.

While most users will never notice it, it is blocking some large cache
users from upgrading from 2.8 to 3.0 or 3.2 because the keys are
redistributed.

After a check with users on the mailing list [1] it was estimated that
keep the current situation is the worst choice because those who have
not yet upgraded will face the problem while by fixing it, those who
already have and for whom it happened smoothly will handle it just
right again.

As such this fix must be backported to 3.0 without waiting (in order
to preserve those who upgrade from two redistributions). Please note
that only configurations featuring "hash-type consistent" and not
having "hash-key" present with a value other than "id" are affected,
others are not (e.g. "hash-key addr" is unaffected).

[1] https://www.mail-archive.com/haproxy@formilux.org/msg46115.html

(cherry picked from commit 03e9a5a1e74b88c7ab7a9522c0345f8d54ec373b)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit cb65f85d54ef5dbb0222e1d66ff49476d728c113)
[wt: dropped the non-existing vtc]
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 3e498531d114fe65ba4c907cd1045366ef1a7bae)
Signed-off-by: Willy Tarreau <w@1wt.eu>

4 days agoBUG/MINOR: ssl: Free key_base from global_ssl structure during deinit
Remi Tricot-Le Breton [Fri, 10 Oct 2025 15:05:22 +0000 (17:05 +0200)]
BUG/MINOR: ssl: Free key_base from global_ssl structure during deinit

The key_base field of the global_ssl structure is an strdup'ed field
(when set) which was never free'd during deinit.

This patch can be backported up to branch 3.0.

(cherry picked from commit b706f2d092b02e8e37662d407d3a2a4914872988)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 20ac503865d106003188710a55746876446dfb3a)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 23be68fe35e0e045109a9f5caf394ea4bef7949b)
Signed-off-by: Willy Tarreau <w@1wt.eu>

4 days agoBUG/MINOR: ssl: Free global_ssl structure contents during deinit
Remi Tricot-Le Breton [Fri, 10 Oct 2025 15:05:21 +0000 (17:05 +0200)]
BUG/MINOR: ssl: Free global_ssl structure contents during deinit

Some fields of the global_ssl structure are strings that are strdup'ed
but never freed. There is only one static global_ssl structure so not
much memory is used but we might as well free it during deinit.

This patch can be backported to all stable branches.

(cherry picked from commit 9bc6a0349d7dc8b17e407b7360ceddd568ed3d7e)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 03ac586b529198065f8bbe055b0fb50a28b2f3f9)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 22f87b5bc3080cb24a4b7b8e984e6c2c1bf6fc38)
Signed-off-by: Willy Tarreau <w@1wt.eu>

6 days agoBUG/MINOR: sink: retry attempt for sft server may never occur
Aurelien DARRAGON [Thu, 2 Oct 2025 19:40:57 +0000 (21:40 +0200)]
BUG/MINOR: sink: retry attempt for sft server may never occur

Since 9561b9fb6 ("BUG/MINOR: sink: add tempo between 2 connection
attempts for sft servers"), there is a possibility that the tempo we use
to schedule the task expiry may point to TICK_ETERNITY as we add ticks to
tempo with a simple addition that doesn't take care of potential wrapping.

When this happens (although relatively rare, since now_ms only wraps every
49.7 days, but a forced wrap occurs 20 seconds after haproxy is started
so it is more likely to happen there), the process_sink_forward() task
expiry being set to TICK_ETERNITY, it may never be called again, this
is especially true if the ring section only contains a single server.

To fix the issue, we must use tick_add() helper function to set the tempo
value and this way we ensure that the value will never be TICK_ETERNITY.

It must be backported everywhere 9561b9fb6 was backported (up to 2.6
it seems).

(cherry picked from commit c26ac3f5e44b78b7fc4caaaa6f8a8ea807178438)
Signed-off-by: Aurelien DARRAGON <adarragon@haproxy.com>
(cherry picked from commit 27e59792c158aef7219194f43bc9e2d9d060b758)
Signed-off-by: Aurelien DARRAGON <adarragon@haproxy.com>
(cherry picked from commit 0a1603052030876249140f2a92038f79611faa58)
Signed-off-by: Aurelien DARRAGON <adarragon@haproxy.com>

6 days agoMINOR: sink: Remove useless test on SE_FL_SHR/SHW flags
Aurelien DARRAGON [Tue, 23 Jul 2024 17:02:29 +0000 (19:02 +0200)]
MINOR: sink: Remove useless test on SE_FL_SHR/SHW flags

Re-apply dcd917d972 ("MINOR: applet: Remove uselelss test on SE_FL_SHR/SHW
flags") for sink_forward_oc_io_handler() function as it was probably
overlooked given that sink_forward_oc_io_handler() and
sink_forward_io_handler() follow the same logic.

(cherry picked from commit f2848e6146faa0794a9878610602d03608af07df)
[ada: required to fix applet not destroyed upon server disconnect,
 see GH #3153, the test turned out to be mandatory, not useless]
Signed-off-by: Aurelien DARRAGON <adarragon@haproxy.com>

9 days agoBUG/MEDIUM: apppet: Improve spinning loop detection with the new API
Christopher Faulet [Fri, 10 Oct 2025 12:32:04 +0000 (14:32 +0200)]
BUG/MEDIUM: apppet: Improve spinning loop detection with the new API

Conditions to detect the spinning loop for applets based on the new API are
not accurrate. We cannot continue to check the channel's buffers state to
know if an applet has made some progress. At least, we must also check the
applet's buffers.

After digging to find the right way to do, it was clear that the best is to
use something similar to what is performed for the streams, namely, checking
read and write events. And in fact, it is quite easy to do with the new
API. So let's do so.

This patch must be backported as far as 3.0.

(cherry picked from commit 54b7539d64d70f033955a0bfe7d0f19d7eef2328)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 20623769917780b8fb7a01a7aa1a2539cc60961b)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit ff753da75357e2595d69570b455f8c782297eb27)
Signed-off-by: Willy Tarreau <w@1wt.eu>

10 days agoBUILD: makefile: disable tail calls optimizations with memory profiling
Willy Tarreau [Fri, 10 Oct 2025 09:28:35 +0000 (11:28 +0200)]
BUILD: makefile: disable tail calls optimizations with memory profiling

The purpose of memory profiling precisely is to figure what function
allocates and what function frees for specific objects. It turns out
that a non-negligible number of release callbacks basically do nothing
but a free() or pool_free() call and return, which the compiler happily
turns into a jump, making the caller of that callback appear as the
real one. That's how we can see libcrypto release to pools such as
ssl-capture for example, which also makes the per-DSO calls appear
wrong:

      10000           0       10720000              0|         0x448c8d ssl_async_fd_free+0x3b9d p_alloc(1072) [pool=ssl-capture]
      50000           0        6800000              0|         0x4456b9 ssl_async_fd_free+0x5c9 p_alloc(136) [pool=ssl-keylogf]
      10072           0         644608              0|         0x447f14 ssl_async_fd_free+0x2e24 p_alloc(64) [pool=ssl-keylogf]
          0       10000              0        1360000|         0x445987 ssl_async_fd_free+0x897 p_free(-136) [pool=ssl-keylogf]
          0       10000              0        1360000|         0x4459b8 ssl_async_fd_free+0x8c8 p_free(-136) [pool=ssl-keylogf]
          0       10000              0        1360000|         0x4459e9 ssl_async_fd_free+0x8f9 p_free(-136) [pool=ssl-keylogf]
          0       10000              0        1360000|         0x445a1a ssl_async_fd_free+0x92a p_free(-136) [pool=ssl-keylogf]
          0       10000              0        1360000|         0x445a4b ssl_async_fd_free+0x95b p_free(-136) [pool=ssl-keylogf]
          0       20072              0       11364608|   0x7f5f1397db62 libcrypto:CRYPTO_free_ex_data+0xf2/0x261 p_free(-566) [pool=ssl-keylogf] [locked=72 (0.3 %)]

Worse, as can be seen on the last line above, there can be a single pool
per call place (since we don't release to arbitrary pools), and the stats
are misleading by reporting the first used pool only when a same function
can call multiple release callbacks. This is why the free call totals
10k ssl-capture and 10072 ssl-keylogfile.

Let's just disable tail call optimization when using memory profiling.
The gains are only very marginal and complicate so much the debugging
that it's not worth it. Now the output is correct, and no longer claims
that libcrypto is the caller:

      10000           0       10720000              0|         0x448c9f ssl_async_fd_free+0x3b9f p_alloc(1072) [pool=ssl-capture]
          0       10000              0       10720000|         0x445af0 ssl_async_fd_free+0x9f0 p_free(-1072) [pool=ssl-capture]
      50000           0        6800000              0|         0x4456c9 ssl_async_fd_free+0x5c9 p_alloc(136) [pool=ssl-keylogf]
      10177           0        1221240              0|         0x45543d ssl_async_fd_handler+0xb51d p_alloc(120) [pool=ssl_sock_ct] [locked=165 (1.6 %)]
      10061           0         643904              0|         0x447f1c ssl_async_fd_free+0x2e1c p_alloc(64) [pool=ssl-keylogf]
          0       10000              0        1360000|         0x445987 ssl_async_fd_free+0x887 p_free(-136) [pool=ssl-keylogf]
          0       10000              0        1360000|         0x4459b8 ssl_async_fd_free+0x8b8 p_free(-136) [pool=ssl-keylogf]
          0       10000              0        1360000|         0x4459e9 ssl_async_fd_free+0x8e9 p_free(-136) [pool=ssl-keylogf]
          0       10000              0        1360000|         0x445a1a ssl_async_fd_free+0x91a p_free(-136) [pool=ssl-keylogf]
          0       10000              0        1360000|         0x445a4b ssl_async_fd_free+0x94b p_free(-136) [pool=ssl-keylogf]
          0       10188              0        1222560|         0x44f518 ssl_async_fd_handler+0x55f8 p_free(-120) [pool=ssl_sock_ct] [locked=176 (1.7 %)]
          0       10072              0         644608|         0x445aa6 ssl_async_fd_free+0x9a6 p_free(-64) [pool=ssl-keylogf] [locked=72 (0.7 %)]

An attempt was made to only instrument pool_free() to place a compiler
barrier, but that resulted in much larger code and wouldn't cover
functions ending with a simple "free()" call. "ha_free()" however is
already immune against tail call optimization since it has to write
the NULL when returning from free().

This should be backported to recent stable releases that are still
regularly being debugged.

(cherry picked from commit dfe7fa9349b73858fa40e3ddcc2cce913c5f8af8)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 1e8bd2b0e46c873c7e329bf75a4e603f628b6afc)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit f5d0aaf639263c3fdc65055aca99319c270d1c32)
Signed-off-by: Willy Tarreau <w@1wt.eu>

10 days agoBUG/MINOR: ssl: always clear the remains of the first hello for the second one
Willy Tarreau [Thu, 9 Oct 2025 16:47:54 +0000 (18:47 +0200)]
BUG/MINOR: ssl: always clear the remains of the first hello for the second one

William rightfully pointed that despite the ssl capture being a
structure, some of its entries are only set for certain contents,
so we need to always zero it before using it so as to clear any
remains of a previous use, otherwise we could possibly report some
entries that were only present in the first hello and not the second
one. No need to clear the data though, since any remains will not be
referenced by the fields.

This must be backported wherever commit 336170007c ("BUG/MEDIUM: ssl:
take care of second client hello") is backported.

(cherry picked from commit 54f0ab08b8f1a3cb1970586e4b7ac48cf7bdf520)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit f86ff7f51271b4b7bccd1f3b8cef0d911e1b5b9e)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 63bb7b723be0926511741fab5169bcfd8dd221e8)
Signed-off-by: Willy Tarreau <w@1wt.eu>

10 days agoBUG/MEDIUM: ssl: take care of second client hello
Willy Tarreau [Thu, 9 Oct 2025 14:13:18 +0000 (16:13 +0200)]
BUG/MEDIUM: ssl: take care of second client hello

For a long time we've been observing some sporadic leaks of ssl-capture
pool entries on haproxy.org without figuring exactly the root cause. All
that was seen was that less calls to the free callback were made than
calls to the hello parsing callback, and these were never reproduced
locally.

It recently turned out to be triggered by the presence of "curves" or
"ecdhe" on the "bind" line. Captures have shown the presence of a second
client hello, called "Change Cipher Client Hello" in wireshark traces,
that calls the client hello callback again. That one wasn't prepared for
being called twice per connection, so it allocates an ssl-capture entry
and assigns it to the ex_data entry, possibly overwriting the previous
one.

In this case, the fix is super simple, just reuse the current ex_data
if it exists, otherwise allocate a new one. This completely solves the
problem.

Other callbacks have been audited for the same issue and are not
affected: ssl_ini_keylog() already performs this check and ignores
subsequent calls, and other ones do not allocate data.

This must be backported to all supported versions.

(cherry picked from commit 336170007c280ac7e8c8edc413f10cbb78af0ec5)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit c3974c9da408fe1d387ad333a32fdf062ceb41eb)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 1a9cddac05fe90d7299d2a84c00bae290dc14d42)
Signed-off-by: Willy Tarreau <w@1wt.eu>

10 days agoBUG/MINOr: hlua: Fix receive from HTTP applet by properly accounting data
Christopher Faulet [Tue, 7 Oct 2025 13:31:27 +0000 (15:31 +0200)]
BUG/MINOr: hlua: Fix receive from HTTP applet by properly accounting data

A regression was introduced when the commit 5b5ecf848 ("BUG/MINOR: hlua:
Skip headers when a receive is performed on an HTTP applet"). To work
properly, the way consumed data are accounted must be adapted. On the dev
version, the changes were hidden in the HTTP applet refactoring and were not
backported. Because of this issue, it is possible to freeze a lua HTTP
applet.

To fix the issue, the requested length of data to retrieved is only
evaluated when a DATA HTX blocked is processed. Otherwise, the blocked is
just skipped.

The bug was introduced to the 3.2. Thus, there is no upstream commit ID.

This patch should fix issue #3150. It shoukd be backported everywhere the
patch above was backported. So at least as far as 2.8 for now.

(cherry picked from commit 7259dffe8ea5bc820bc7b6d3c2ee0775a09063da)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 59c9496b56059eb5b7144d4d507210a43f326195)
Signed-off-by: Willy Tarreau <w@1wt.eu>

13 days agoMINOR: ssl: diagnostic warning when both 'default-crt' and 'strict-sni' are used
William Lallemand [Wed, 27 Aug 2025 13:44:24 +0000 (15:44 +0200)]
MINOR: ssl: diagnostic warning when both 'default-crt' and 'strict-sni' are used

It possible to use both 'strict-sni' and 'default-crt' on the same bind
line, which does not make much sense.

This patch implements a check which will look for default certificates
in the sni_w tree when strict-sni is used. (Referenced by their empty
sni ""). default-crt sets the CKCH_INST_EXPL_DEFAULT flag in
ckch_inst->is_default, so its possible to differenciate explicits
default from implicit default.

Could be backported as far as 3.0.

This was discussed in ticket #3082.

(cherry picked from commit 18ebd81962e1f53b8f59bfee5b9795bff69ac16b)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit a9010888c016718d1b5200e88b0410ad315f8f64)
[wla: BC_SSL_O_STRICT_SNI doesn't exist and must be replaced by
strict_sni]
Signed-off-by: William Lallemand <wlallemand@haproxy.com>
(cherry picked from commit 39f930548d188c92aacf3107dcb8e03bca069a4b)
Signed-off-by: William Lallemand <wlallemand@haproxy.com>

2 weeks ago[RELEASE] Released version 3.0.12 v3.0.12
Christopher Faulet [Fri, 3 Oct 2025 10:59:17 +0000 (12:59 +0200)]
[RELEASE] Released version 3.0.12

Released version 3.0.12 with the following main changes :
    - BUG/MEDIUM: peers: also limit the number of incoming updates
    - BUG/MINOR: mux-quic: do not decode if conn in error
    - MINOR: quic: rename min/max fields for congestion window algo
    - BUG/MINOR: quic: ensure cwnd limits are always enforced
    - BUILD: tools: properly define ha_dump_backtrace() to avoid a build warning
    - DOC: config: Fix a typo in 2.7 (Name format for maps and ACLs)
    - BUG/MEDIUM: check: Requeue healthchecks on I/O events to handle check timeout
    - BUG/MINOR: quic: Missing SSL session object freeing
    - BUG/MEDIUM: fd: Use the provided tgid in fd_insert() to get tgroup_info
    - BUG/MINIR: h1: Fix doc of 'accept-unsafe-...-request' about URI parsing
    - BUG/MINOR: config/server: reject QUIC addresses
    - BUG/MEDIUM: cli: Don't consume data if outbuf is full or not available
    - MINOR: cli: handle EOS/ERROR first
    - BUG/MEDIUM: check: Set SOCKERR by default when a connection error is reported
    - BUG/MEDIUM: ssl/clienthello: ECDSA with ssl-max-ver TLSv1.2 and no ECDSA ciphers
    - BUG/MINOR: hlua_fcn: restore server pairs iterator pointer consistency
    - BUG/MEDIUM: hlua_fcn: ensure systematic watcher cleanup for server list iterator
    - MINOR: compiler: add __nonstring macro
    - MINOR: http: add a function to validate characters of :authority
    - BUG/MEDIUM: h2/h3: reject some forbidden chars in :authority before reassembly
    - BUG/MEDIUM: h1/h2/h3: reject forbidden chars in the Host header field
    - DOC: config: prefer-last-server: add notes for non-deterministic algorithms
    - BUG/MINOR: mux-quic/h3: properly handle too low peer fctl initial stream
    - BUG/MINOR: stream: Avoid recursive evaluation for unique-id based on itself
    - BUG/MINOR: log: Be able to use %ID alias at anytime of the stream's evaluation
    - DOC: configuration: add details on prefer-client-ciphers
    - BUG/MINOR: quic: wrong QUIC_FT_CONNECTION_CLOSE(0x1c) frame encoding
    - MINOR: quic: Useless TX buffer size reduction in closing state
    - SCRIPTS: drop the HTML generation from announce-release
    - BUG/MEDIUM: hlua: Forbid any L6/L7 sample fetche functions from lua services
    - BUG/MEDIUM: mux-h2: Properly handle connection error during preface sending
    - BUG/MINOR: jwt: Copy input and parameters in dedicated buffers in jwt_verify converter
    - DOC: Fix 'jwt_verify' converter doc
    - BUG/MINOR: httpclient: wrongly named httpproxy flag
    - BUILD/MEDIUM: deviceatlas: fix when installed in custom locations.
    - DOC: deviceatlas build clarifications
    - BUG/MINOR: hlua: Skip headers when a receive is performed on an HTTP applet
    - BUG/MEDIUM: hlua: Report to SC when data were consumed on a lua socket
    - BUG/MEDIUM: hlua: Report to SC when output data are blocked on a lua socket
    - BUG/MEDIUM: dns: Reset reconnect tempo when connection is finally established
    - BUG/MEDIUM: logs: fix sess_build_logline_orig() recursion with options
    - BUG/MINOR: hlua: take default-path into account with lua-load-per-thread
    - DOC: management: clarify usage of -V with -c
    - MEDIUM: ssl/cli: relax crt insertion in crt-list of type directory
    - BUG/MINOR: listener: really assign distinct IDs to shards
    - BUG/MEDIUM: http-client: Don't wake http-client applet if nothing was xferred
    - BUG/MEDIUM: http-client: Properly inc input data when HTX blocks are xferred
    - BUG/MEDIUM: http-client: Ask for more room when request data cannot be xferred
    - BUG/MINOR: http-client: Ignore 1XX interim responses in non-HTX mode
    - BUG/MINOR: http-client: Reject any 101-switching-protocols response
    - BUG/MEDIUM: http-client: Drain the request if an early response is received
    - BUG/MEDIUM: http-client: Notify applet has more data to deliver until the EOM
    - BUG/MINOR: quic: Wrong source address use on FreeBSD
    - BUG/MINOR: applet: Don't trigger BUG_ON if the tid is not on appctx init
    - BUG/MINOR: halog: exit with error when some output filters are set simultaneosly
    - BUG/MEDIUM: threads: Disable the workaround to load libgcc_s on macOS
    - DOC: list missing global QUIC settings
    - BUILD: compat: provide relaxed versions of the MIN/MAX macros
    - BUILD: compat: always set _POSIX_VERSION to ease comparisons
    - BUG/MINOR: stick-table: cap sticky counter idx with tune.nb_stk_ctr instead of MAX_SESS_STKCTR
    - BUG/MEDIUM: ssl: Fix 0rtt to the server
    - BUG/MEDIUM: ssl: fix build with AWS-LC
    - BUG/MINOR: init: Initialize random seed earlier in the init process
    - DOC: management: fix typo in commit f4f93c56
    - DOC: config: recommend single quoting passwords
    - BUG/MEDIUM: http-client: Test HTX_FL_EOM flag before commiting the HTX buffer
    - BUG/MINOR: mux-h1: fix wrong lock label
    - BUG/MINOR: quic: do not emit probe data if CONNECTION_CLOSE requested
    - BUG/MAJOR: quic: fix INITIAL padding with probing packet only
    - MINOR: quic: centralize padding for HP sampling on packet building
    - BUG/MEDIUM: stconn: Fix conditions to know an applet can get data from stream
    - BUG/MEDIUM: Remove sync sends from streams to applets
    - BUG/MINOR: quic: reorder fragmented RX CRYPTO frames by their offsets
    - MINOR: quic: remove ->offset qf_crypto struct field
    - BUG/MINOR: mux-quic: trace with non initialized qcc
    - BUG/MINOR: acl: set arg_list->kw to aclkw->kw string literal if aclkw is found
    - BUG/MINOR: connection: rearrange union list members
    - BUG/MINOR: connection: remove extra session_unown_conn() on reverse
    - BUG/MINOR: server: decrement session idle_conns on del server
    - DOC: unreliable sockpair@ on macOS
    - DOC: configuration: confuse "strict-mode" with "zero-warning"
    - MINOR: doc: add missing statistics column
    - MINOR: doc: add missing statistics column
    - CLEANUP: quic: remove a useless CRYPTO frame variable assignment
    - BUG/MEDIUM: quic: CRYPTO frame freeing without eb_delete()
    - BUG/MAJOR: mux-quic: fix crash on reload during emission
    - REG-TESTS: map_redirect: Don't use hdr_dom in ACLs with "-m end" matching method
    - BUG/MEDIUM: server: Duplicate healthcheck's alpn inherited from default server
    - BUG/MINOR: halog: Add OOM checks for calloc() in filter_count_srv_status() and filter_count_url()
    - BUG/MINOR: log: Add OOM checks for calloc() and malloc() in logformat parser and dup_logger()
    - BUG/MINOR: acl: Add OOM check for calloc() in smp_fetch_acl_parse()
    - BUG/MINOR: cfgparse: Add OOM check for calloc() in cfg_parse_listen()
    - BUG/MINOR: compression: Add OOM check for calloc() in parse_compression_options()
    - BUG/MINOR: tools: Add OOM check for malloc() in indent_msg()
    - BUG/MINOR: quic: ignore AGAIN ncbuf err when parsing CRYPTO frames
    - BUG/MINOR: quic: fix room check if padding requested
    - BUG/MINOR: quic: fix padding issue on INITIAL retransmit
    - BUG/MINOR: haproxy: be sure not to quit too early on soft stop
    - BUILD: acl: silence a possible null deref warning in parse_acl_expr()
    - MINOR: quic: Add more information about RX packets
    - REGTESTS: explicitly use "balance roundrobin" where RR is needed
    - BUG/MEDIUM: conn: fix UAF on connection after reversal on edge
    - BUG/MINOR: connection: streamline conn detach from lists
    - BUG/MINOR: log: fix potential memory leak upon error in add_to_logformat_list()
    - BUILD: trace: silence a bogus build warning at -Og
    - BUG/MINOR: cpu_topo: work around a small bug in musl's CPU_ISSET()
    - CLEANUP: quic: fix typo in quic_tx trace
    - OPTIM: check: do not delay MUX for ALPN if SSL not active
    - BUG/MEDIUM: checks: fix ALPN inheritance from server
    - BUG/MEDIUM: h1: Allow reception if we have early data
    - BUG/MEDIUM: ssl: create the mux immediately on early data
    - BUG/MINOR: activity: fix reporting of task latency
    - BUG/MAJOR: stream: Remove READ/WRITE events on channels after analysers eval
    - BUG/MAJOR: stream: Force channel analysis on successful synchronous send
    - BUG/MINOR: ocsp: Crash when updating CA during ocsp updates
    - BUG/MINOR: resolvers: always normalize FQDN from response
    - BUG/MEDIUM: ring: invert the length check to avoid an int overflow
    - MINOR: server: Parse sni and pool-conn-name expressions in a dedicated function
    - BUG/MEDIUM: server: Use sni as pool connection name for SSL server only
    - BUG/MINOR: server: Update healthcheck when server settings are changed via CLI
    - OPTIM: sink: reduce contention on sink_announce_dropped()
    - BUG/MEDIUM: stick-tables: Don't let table_process_entry() handle refcnt
    - BUILD: halog: misleading indentation in halog.c
    - MINOR: ssl: add the ssl_bc_sni sample fetch function to retrieve backend SNI
    - BUG/MINOR: pattern: Properly flag virtual maps as using samples
    - BUG/MINOR: pattern: Fix pattern lookup for map with opt@ prefix
    - BUG/MEDIUM: ssl: ca-file directory mode must read every certificates of a file
    - DOC: config: clarify some known limitations of the json_query() converter
    - BUG/CRITICAL: mjson: fix possible DoS when parsing numbers
    - BUG/MINOR: h2: forbid 'Z' as well in header field names checks
    - BUG/MINOR: h3: forbid 'Z' as well in header field names checks
    - Revert "MINOR: quic: Useless TX buffer size reduction in closing state"

2 weeks agoRevert "MINOR: quic: Useless TX buffer size reduction in closing state"
Christopher Faulet [Fri, 3 Oct 2025 07:40:14 +0000 (09:40 +0200)]
Revert "MINOR: quic: Useless TX buffer size reduction in closing state"

By chasing a QUIC regression on 3.0, we found this commit. We don't if it
introduced a regression or not but the context is quite different. So let's
revert it for now, especially because it is not a bug fix, to review it
later.

This reverts commit 6edc24a81f9347d49f674c9fdd6641e922b85132.

2 weeks agoBUG/MINOR: h3: forbid 'Z' as well in header field names checks
zhanhb [Sat, 27 Sep 2025 15:01:32 +0000 (23:01 +0800)]
BUG/MINOR: h3: forbid 'Z' as well in header field names checks

The current tests in _h3_handle_hdr() and h3_trailers_to_htx() check
for an interval between 'A' and 'Z' for letters in header field names
that should be forbidden, but mistakenly leave the 'Z' out of the
forbidden range, resulting in it being implicitly valid.

This has no real consequences but should be fixed for the sake of
protocol validity checking.

This must be backported to all relevant versions.

(cherry picked from commit ad75431b9c7eb739fa05f748098a9a505cf9c868)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 2c3eec71e195fa9b60b93e9b7532f55b827a22b3)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 65b8ac6c8681549e19643062897db3655b279ce4)
Signed-off-by: Willy Tarreau <w@1wt.eu>

2 weeks agoBUG/MINOR: h2: forbid 'Z' as well in header field names checks
zhanhb [Sat, 27 Sep 2025 15:01:32 +0000 (23:01 +0800)]
BUG/MINOR: h2: forbid 'Z' as well in header field names checks

The current tests in h2_make_htx_request(), h2_make_htx_response()
and h2_make_htx_trailers() check for an interval between 'A' and 'Z'
for letters in header field names that should be forbidden, but
mistakenly leave the 'Z' out of the forbidden range, resulting in it
being implicitly valid.

This has no real consequences but should be fixed for the sake of
protocol validity checking.

This must be backported to all relevant versions.

(cherry picked from commit 7163d9180cb319db087221a683c0f2d02ffbf0be)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 82b546ff936285f855a02378c38aed8168fd646f)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 970a437c4b612ebb2acac75528dc9e32d1e1b412)
Signed-off-by: Willy Tarreau <w@1wt.eu>

2 weeks agoBUG/CRITICAL: mjson: fix possible DoS when parsing numbers
Willy Tarreau [Mon, 29 Sep 2025 16:34:11 +0000 (18:34 +0200)]
BUG/CRITICAL: mjson: fix possible DoS when parsing numbers

Mjson comes with its own strtod() implementation for portability
reasons and probably also because many generic strtod() versions as
provided by operating systems do not focus on resource preservation
and may call malloc(), which is not welcome in a parser.

The strtod() implementation used here apparently originally comes from
https://gist.github.com/mattn/1890186 and seems to have purposely
omitted a few parts that were considered as not needed in this context
(e.g. skipping white spaces, or setting errno). But when subject to the
relevant test cases of the designated file above, the current function
provides the same results.

The aforementioned implementation uses pow() to calculate exponents,
but mjson authors visibly preferred not to introduce a libm dependency
and replaced it with an iterative loop in O(exp) time. The problem is
that the exponent is not bounded and that this loop can take a huge
amount of time. There's even an issue already opened on mjson about
this: https://github.com/cesanta/mjson/issues/59. In the case of
haproxy, fortunately, the watchdog will quickly stop a runaway process
but this remains a possible denial of service.

A first approach would consist in reintroducing pow() like in the
original implementation, but if haproxy is built without Lua nor
51Degrees, -lm is not used so this will not work everywhere.

Anyway here we're dealing with integer exponents, so an easy alternate
approach consists in simply using shifts and squares, to compute the
exponent in O(log(exp)) time. Not only it doesn't introduce any new
dependency, but it turns out to be even faster than the generic pow()
(85k req/s per core vs 83.5k on the same machine).

This must be backported as far as 2.4, where mjson was introduced.

Many thanks to Oula Kivalo for reporting this issue.

CVE-2025-11230 was assigned to this issue.

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

2 weeks agoDOC: config: clarify some known limitations of the json_query() converter
Willy Tarreau [Thu, 2 Oct 2025 02:52:33 +0000 (04:52 +0200)]
DOC: config: clarify some known limitations of the json_query() converter

Oula Kivalo reported that different JSON libraries may process duplicate
keys differently and that most JSON libraries usually decode the stream
before extracting keys, while the current mjson implementation decodes the
contents during extraction instead. Let's document this point so that
users are aware of the limitations and do not rely on the current behavior
and do not use it for what it's not made for (e.g. content sanitization).

This is also the case for jwt_header_query(), jwt_payload_query() and
jwt_verify(), which already refer to this converter for specificities.

(cherry picked from commit 67603162c1d5baaf17f6bf1a3a4c58d5c0524d35)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit d808c48fb926813438f58dad2654bd9a6a923ce4)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit e09bf0ff4e73819e32075fd37abefb746799f373)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MEDIUM: ssl: ca-file directory mode must read every certificates of a file next
William Lallemand [Fri, 26 Sep 2025 07:22:55 +0000 (09:22 +0200)]
BUG/MEDIUM: ssl: ca-file directory mode must read every certificates of a file

The httpclient is configured with @system-ca by default, which uses the
directory returned by X509_get_default_cert_dir().

On debian/ubuntu systems, this directory contains multiple certificate
files that are loaded successfully. However it seems that on other
systems the files in this directory is the direct result of
ca-certificates instead of its source. Meaning that you would only have
a bundle file with every certificates in it.

The loading was not done correctly in case of directory loading, and was
only loading the first certificate of each file.

This patch fixes the issue by using X509_STORE_load_locations() on each
file from the scandir instead of trying to load it manually with BIO.

Not that we can't use X509_STORE_load_locations with the `dir` argument,
which would be simpler, because it uses X509_LOOKUP_hash_dir() which
requires a directory in hash form. That wouldn't be suited for this use
case.

Must be backported in every stable branches.

Fix issue #3137.

(cherry picked from commit c52d69cc785c039c0b665a229350fff11cfeda13)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit a96a1ef0a48a9b5b3883346bb21c79b95fa653eb)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 8c014f305e7fd6ad9123f38067262c457fbe488f)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: pattern: Fix pattern lookup for map with opt@ prefix
Christopher Faulet [Thu, 25 Sep 2025 13:21:04 +0000 (15:21 +0200)]
BUG/MINOR: pattern: Fix pattern lookup for map with opt@ prefix

When we look for a map file reference, the file@ prefix is removed because
if may be omitted. The same is true with opt@ prefix. However this case was
not properly performed in pat_ref_lookup(). Let's do so.

This patch must be backported as far as 3.0.

(cherry picked from commit 7aa9f5ec98436182b2b5ebeb57828d2daf27f20a)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 0d07528f558509ee7b3d097e93842de2d6b273e1)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 6da9abc77d9f77a438856d13c1db15c5dd86b5d8)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: pattern: Properly flag virtual maps as using samples
Christopher Faulet [Thu, 25 Sep 2025 08:03:41 +0000 (10:03 +0200)]
BUG/MINOR: pattern: Properly flag virtual maps as using samples

When a map file is load, internally, the pattern reference is flagged as
based on a sample. However it is not performed for virtual maps. This flag
is only used during startup to check the map compatibility when it used at
different places. At runtime this does not change anything. But errors can
be triggered during configuration parsing. For instance, the following valid
config will trigger an error:

    http-request set-map(virt@test) foo bar if !{ str(foo),map(virt@test) -m found }
    http-request set-var(txn.foo) str(foo),map(virt@test)

The fix is quite obvious. PAT_REF_SMP flag must be set for virtual map as
any other map.

A workaround is to use optional map (opt@...) by checking the map id cannot
reference an existing file.

This patch must be backported as far as 3.0.

(cherry picked from commit 3be8b06a60a37756a2c596f36727268cbfc4edf9)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 11a5bd0b87a26ac22f98fbffffd21fd8660b3458)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 7d2be4e74ec7bda906adfaf95ecf99e1414d39a0)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoMINOR: ssl: add the ssl_bc_sni sample fetch function to retrieve backend SNI
Willy Tarreau [Mon, 29 Sep 2025 11:30:12 +0000 (13:30 +0200)]
MINOR: ssl: add the ssl_bc_sni sample fetch function to retrieve backend SNI

Sometimes in order to debug certain difficult situations it can be useful
to know what SNI was configured on a connection going to a server, for
example to match it against what the server saw or to detect cases where
a server would route on SNI instead of Host. This sample fetch function
simply retrieves the SNI configured on the backend connection, if any.

(cherry picked from commit dae4cfe8c57dc7644a7afd847d964c8d7444deda)
[wt: backported in order to help tracking some issues]
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit ca6a7b4635ab9417e4f8a171b28269c145e1da33)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit a60a266393ad52b3f9e50e96348e7970ba9d17fd)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUILD: halog: misleading indentation in halog.c
William Lallemand [Fri, 26 Sep 2025 13:58:49 +0000 (15:58 +0200)]
BUILD: halog: misleading indentation in halog.c

admin/halog/halog.c: In function 'filter_count_url':
admin/halog/halog.c:1685:9: error: this 'if' clause does not guard... [-Werror=misleading-indentation]
 1685 |         if (unlikely(!ustat))
      |         ^~
admin/halog/halog.c:1687:17: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
 1687 |                 if (unlikely(!ustat)) {
      |                 ^~

This patch fixes the indentation.

Must be backported where fbd0fb20a22 ("BUG/MINOR: halog: Add OOM checks
for calloc() in filter_count_srv_status() and filter_count_url()") was
backported.

(cherry picked from commit f1f5877ce1e7d162045b425b53de382ab9ee217e)
Signed-off-by: William Lallemand <wlallemand@haproxy.com>
(cherry picked from commit b3b245af10ee8411e9d3aaddd368a390ecacbce8)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 9eed3e5df85a08deeb55be3a6643b81176401461)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MEDIUM: stick-tables: Don't let table_process_entry() handle refcnt
Olivier Houchard [Thu, 11 Sep 2025 16:22:34 +0000 (18:22 +0200)]
BUG/MEDIUM: stick-tables: Don't let table_process_entry() handle refcnt

Instead of having table_process_entry() decrement the session's ref
counter, do it outside, from the caller. Some were missed, such as when
an action was invalid, which would lead to the ref counter not being
decremented, and the session not being destroyable.
It makes more sense to do that from the caller, who just obtained the
ref counter, anyway.
This should be backporter up to 2.8.

(cherry picked from commit 71199e394c5e63fda7070cd7ae5b4b691411259d)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 1b2a06b994c0d537ca2da0af101c2b84735d67f9)
[cf: ctx adjt]
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit e9c299c31d67bebe68c22503a98b51da485cdca7)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoOPTIM: sink: reduce contention on sink_announce_dropped()
Willy Tarreau [Thu, 18 Sep 2025 06:38:34 +0000 (08:38 +0200)]
OPTIM: sink: reduce contention on sink_announce_dropped()

perf top shows that sink_announce_dropped() consumes most of the CPU
on a 128-thread x86 system. Digging further reveals that the atomic
fetch_or() on the dropped field used to detect the presence of another
thread is entirely responsible for this. Indeed, the compiler implements
it using a CAS that loops without relaxing and makes all threads wait
until they can synchronize on this one, only to discover later that
another thread is there and they need to give up.

Let's just replace this with a hand-crafted CAS loop that will detect
*before* attempting the CAS if another thread is there. Doing so
achieves the same goal without forcing threads to agree. With this
simple change, the sustained request rate on h1 with all traces on
bumped from 110k/s to 244k/s!

This should be backported to stable releases where it's often needed
to help debugging.

(cherry picked from commit 4431e3bd26f5e7af6e229d1d06bbc2749c2272c0)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit e7c281fc6e11e774d0f4010758f59f6016c406d7)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit a61a2d3c5a16dcc9e02e03a2076e852ec03bbbea)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: server: Update healthcheck when server settings are changed via CLI
Christopher Faulet [Wed, 3 Sep 2025 14:36:25 +0000 (16:36 +0200)]
BUG/MINOR: server: Update healthcheck when server settings are changed via CLI

not all changes are concerned. But when the SSL is enabled or disabled for a
server, the healthcheck xprt must be eventually be updated too. This happens
when the healthcheck relies on the server settings.

In the same spirit, when the healthcheck address and port are updated, we
must fallback on the raw xprt if the SSL is not explicitly enabled for the
healthcheck with a "check-ssl" parameter.

This patch should be backported to all stable versions.

(cherry picked from commit a97bd0f50520b8f70fe0d543a6be863b4b84ac9d)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit fb289e8492da7859c43ecb7f4307e0ebfe2c5b80)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 7015fbf066d155b4df9d769c2b348e7038aa7df9)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MEDIUM: server: Use sni as pool connection name for SSL server only
Christopher Faulet [Wed, 3 Sep 2025 13:29:56 +0000 (15:29 +0200)]
BUG/MEDIUM: server: Use sni as pool connection name for SSL server only

By default, for a given server, when no pool-conn-name is specified, the
configured sni is used. However, this must only be done when SSL is in-use
for the server. Of course, it is uncommon to have a sni expression for
now-ssl server. But this may happen.

In addition, the SSL may be disabled via the CLI. In that case, the
pool-conn-name must be discarded if it was copied from the sni. And, we must
of course take care to set it if the ssl is enabled.

Finally, when the attac-srv action is checked, we now checked the
pool-conn-name expression.

This patch should be backported as far as 3.0. It relies on "MINOR: server:
Parse sni and pool-conn-name expressions in a dedicated function" which
should be backported too.

(cherry picked from commit f8f94ffc9c26bb8c2ff261972ce2f6c4fd731f6d)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 0d57285653b93428368112a9fbfbe59a40848707)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 5ff4c9da3720c4e1fd194c72670bfb4b108b7ce1)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoMINOR: server: Parse sni and pool-conn-name expressions in a dedicated function
Christopher Faulet [Wed, 3 Sep 2025 12:45:07 +0000 (14:45 +0200)]
MINOR: server: Parse sni and pool-conn-name expressions in a dedicated function

This change is mandatory to fix an issue. The parsing of sni and
pool-conn-name expressions (from string to expression) is now handled in a
dedicated function. This will avoid to duplicate the same code at different
places.

(cherry picked from commit 086a248645c8edca681adba50b34d9970e455a98)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 79a6520cea23728ebcb138612bec1d077fd64cca)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit c2a750108a2a1f0fe78e484bc103416ba879051a)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MEDIUM: ring: invert the length check to avoid an int overflow
Willy Tarreau [Wed, 17 Sep 2025 16:45:13 +0000 (18:45 +0200)]
BUG/MEDIUM: ring: invert the length check to avoid an int overflow

Vincent Gramer reported in GH issue #3125 a case of crash on a BUG_ON()
condition in the rings. What happens is that a message that is one byte
less than the maximum ring size is emitted, and it passes all the checks,
but once inflated by the extra +1 for the refcount, it can no longer. But
the check was made based on message size compared to space left, except
that this space left can now be negative, which is a high positive for
size_t, so the check remained valid and triggered a BUG_ON() later.

Let's compute the size the other way around instead (i.e. current +
needed) since we can't have rings as large as half of the memory space
anyway, thus we have no risk of overflow on this one.

This needs to be backported to all versions supporting multi-threaded
rings (3.0 and above).

Thanks to Vincent for the easy and working reproducer.

(cherry picked from commit d53ad49ad1713ee874097fff1b4a777141ca2a49)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 800da9eb7f13029b2f31cbafab13e4ddbbe5a2de)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 26a640832f0bdc4ccb50d7933bce262d92a49a08)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: resolvers: always normalize FQDN from response
Valentine Krasnobaeva [Wed, 10 Sep 2025 16:30:19 +0000 (18:30 +0200)]
BUG/MINOR: resolvers: always normalize FQDN from response

RFC1034 states the following:

By convention, domain names can be stored with arbitrary case, but
domain name comparisons for all present domain functions are done in a
case-insensitive manner, assuming an ASCII character set, and a high
order zero bit. This means that you are free to create a node with
label "A" or a node with label "a", but not both as brothers; you could
refer to either using "a" or "A".

In practice, most DNS resolvers normalize domain labels (i.e., convert
them to lowercase) before performing searches or comparisons to ensure
this requirement is met.

While HAProxy normalizes the domain name in the request, it currently
does not do so for the response. Commit 75cc653 ("MEDIUM: resolvers:
replace bogus resolv_hostname_cmp() with memcmp()") intentionally
removed the `tolower()` conversion from `resolv_hostname_cmp()` for
safety and performance reasons.

This commit re-introduces the necessary normalization for FQDNs received
in the response. The change is made in `resolv_read_name()`, where labels
are processed as an unsigned char string, allowing `tolower()` to be
applied safely. Since a typical FQDN has only 3-4 labels, replacing
`memcpy()` with an explicit copy that also applies `tolower()` should
not introduce a significant performance degradation.

This patch addresses the rare edge case, as most resolvers perform this
normalization themselves.

This fixes the GitHub issue #3102. This fix may be backported in all stable
versions since 2.5 included 2.5.

(cherry picked from commit f8acac653e104e90f06dd8c774ccd9d14b531546)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 877a36ef246372d5c4ac6471b2961700737a9a73)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 1fef81acbb94f9026156123bb4ff394b6ead4c52)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: ocsp: Crash when updating CA during ocsp updates
Remi Tricot-Le Breton [Mon, 15 Sep 2025 13:32:40 +0000 (15:32 +0200)]
BUG/MINOR: ocsp: Crash when updating CA during ocsp updates

If an ocsp response is set to be updated automatically and some
certificate or CA updates are performed on the CLI, if the CLI update
happens while the OCSP response is being updated and is then detached
from the udapte tree, it might be wrongly inserted into the update tree
in 'ssl_sock_load_ocsp', and then reinserted when the update finishes.

The update tree then gets corrupted and we could end up crashing when
accessing other nodes in the ocsp response update tree.

This patch must be backported up to 2.8.
This patch fixes GitHub #3100.

(cherry picked from commit 257df69fbdcff5c1feb3b24a4cf6141f86984447)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit f885845e2b2c50996d3373eb5d2e84d3e7fcfbb8)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 7a2c66c5e90e2f69ba59dbdc6818e1f2dba27f41)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MAJOR: stream: Force channel analysis on successful synchronous send
Christopher Faulet [Thu, 11 Sep 2025 07:38:41 +0000 (09:38 +0200)]
BUG/MAJOR: stream: Force channel analysis on successful synchronous send

This patchs reverts commit a498e527b ("BUG/MAJOR: stream: Remove READ/WRITE
events on channels after analysers eval") because of a regression. It was an
attempt to properly detect synchronous sends, even when the stream was woken
up on a write event. However, the fix was wrong because it could mask
shutdowns performed during process_stream() and block the stream.

Indeed, when a shutdown is performed, because an error occurred for
instance, a write event is reported. The commit above could mask this event
while the shutdown prevent any synchronous sends. In such case, the stream
could remain blocked infinitly because an I/O event was missed.

So to properly fix the original issue (#3070), the write event must not be
masked before a synchronous send. Instead, we now force the channel analysis
by setting explicitly CF_WAKE_ONCE flags on the corresponding channel if a
write event is reported after the synchronous send. CF_WRITE_EVENT flag is
remove explicitly just before, so it is quite easy to detect.

This patch must be backport to all stable version in same time of the commit
above.

(cherry picked from commit 5354c24c7609002c4daeb58e15a6057eeae367ac)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 2e6fb599304bf85f89d501da54ecf52ade1f3fdc)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 6167935cb4d7e812b7507ba69b5ff6068da2a7bf)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MAJOR: stream: Remove READ/WRITE events on channels after analysers eval
Christopher Faulet [Thu, 21 Aug 2025 14:27:42 +0000 (16:27 +0200)]
BUG/MAJOR: stream: Remove READ/WRITE events on channels after analysers eval

It is possible to miss a synchronous write event in process_stream() if the
stream was woken up on a write event. In that case, it is possible to freeze
the stream until the next I/O event or timeout.

Concretely, the stream is woken up with CF_WRITE_EVENT on a channel. this
flag is removed from the channel when we leave proces_stream(). But before
leaving process_stream(), when a synchronous send is tried on this channel,
the flag is removed and eventually set again on success. But this event is
masked by the previous one, and the channel is not resync as it should be.

To fix the bug, CF_READ_EVENT and CF_WRITE_EVENT flags are removed from a
channel after the corresponding analysers evaluation. This way, we will be
able to detect a successful synchronous send to restart analysers evaluation
based on the new channel state. It is safe (or it should be) to do so
becaues these flags are only used by analysers and tested to resync the
stream inside process_stream().

It is a very old bug and I guess all versions are affected. It was observed
on 2.9 and higher, and with the master/worker only. But it could affect any
stream. It is tagged a MAJOR because this area is really sensitive to any
change.

This patch should fix the issue #3070. It should probably be backported to
all stable versions, but only after a period of observation and with a
special care because this area is really sensitive to changes. It is
probably reasonnable to backport it as far as 3.0 and wait for older
versions.

Thanks to Valentine for its help on this issue !

(cherry picked from commit a498e527b412d8b66e27d2175bfad3101f6dbedb)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit d065cdb03342b2eaee857cd261488bf14382f144)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 711e2d4ed0b0458dddd6f001c2d14ba76aa6931a)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: activity: fix reporting of task latency
Willy Tarreau [Wed, 10 Sep 2025 08:36:27 +0000 (10:36 +0200)]
BUG/MINOR: activity: fix reporting of task latency

In 2.4, "show tasks" was introduced by commit 7eff06e162 ("MINOR:
activity: add a new "show tasks" command to list currently active tasks")
to expose some info about running tasks. The latency is not correct
because it's a u32 subtracted from a u64. It ought to have been casted
to u32 for the operation, which is what this patch does.

This can be backported to 2.4.

(cherry picked from commit 17d33923484ba5661f8938b55cc825b156766955)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 38233771977e142264a76b51c5d56068180d5fa2)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 885d50f802aa9b8c79eba8db1925cdb1ed4c3a01)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MEDIUM: ssl: create the mux immediately on early data
Olivier Houchard [Tue, 9 Sep 2025 13:34:32 +0000 (15:34 +0200)]
BUG/MEDIUM: ssl: create the mux immediately on early data

If we received early data, and an ALPN has been negociated, then
immediately try to create a mux if we did not have one already.
Generally, at this point we would not have one, as the mux is decided by
the ALPN, however at this point, even if the handshake is not done yet,
we have enough to determine the ALPN, so we can immediately create the
mux.
Doing so makes up able to treat the request immediately, without waiting
for the handshake to be done.

This should be backported up to 2.8.

(cherry picked from commit 6b78af837d7b5b75b7c22a5fa39bf50ed727d904)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 8b633e68e3d5929b7ad6058310e48cef9feb4c76)
[cf: trace message was removed]
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 45543e72024284c4687ee16bc6df02b05be52475)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MEDIUM: h1: Allow reception if we have early data
Olivier Houchard [Tue, 9 Sep 2025 15:32:18 +0000 (17:32 +0200)]
BUG/MEDIUM: h1: Allow reception if we have early data

In h1_recv_allowed(), do not forbid the reception if we are yet to
complete the connection, if we have received early data on it. That way,
we can deal with them right away, instead of waiting for the handshake
to be done.

This should be backported up to 2.8.

(cherry picked from commit aa25ddb773e484793a5c245bfa3f98b917c215be)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 1e4b80a8be585024e1993c6fdd460edcbf239d12)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 00beb362dde7fad080a3e0e768738bfef7f46c39)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MEDIUM: checks: fix ALPN inheritance from server
Amaury Denoyelle [Tue, 9 Sep 2025 13:34:25 +0000 (15:34 +0200)]
BUG/MEDIUM: checks: fix ALPN inheritance from server

If no specific check settings are defined on a server line, it is
expected that these checks will be performed with the same parameters as
normal connections on the same server.

ALPN must be carefully taken into account for checks. Most notably, MUX
initialization is delayed so that it is performed only after SSL
handshake.

Prior to this patch, MUX init delay was only performed if ALPN was
defined via check settings. Thus, with the following settings, checks
would be performed on HTTP/1.1 without consulting ALPN negotiation
result from the server :

  server s1 127.0.0.1:443 ssl crt <...> alpn h2 check

This bug may result in checks reporting failure, for example in case of
a server answering HTTP/2 to ALPN negotiation to the configuration
above. Besides, there is incoherency between normal and check
connections, which is not what the documentation specifies.

This patch fixes this code. Now server parameters are also taken into
account. This ensures that checks and normal connections by default
use the same connection method.

This must be backported up to 2.4.

(cherry picked from commit c6d33c09fc2c60fe0ffb54464a550e1b7bd69c4c)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 1d606e7e8c9789b8a0f9212eae6573cafb21ff82)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 5cf8f3e7d070eb258cf15b77a307acc02927746b)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoOPTIM: check: do not delay MUX for ALPN if SSL not active
Amaury Denoyelle [Tue, 9 Sep 2025 12:27:24 +0000 (14:27 +0200)]
OPTIM: check: do not delay MUX for ALPN if SSL not active

To ensure ALPN is properly applied on checks, MUX initialization is
delayed so that it is created on SSL handshake completion. However, this
does not check if SSL is really active for the connection.

This patch adjusts the condition so that MUX init is not delayed if SSL
is not active for the check connection. A similar process is already
conducted for normal connections via connect_server().

This must be backported up to 2.4. Despite not being a bug, it must be
backported for the following patch which fixes check ALPN inheritance
from server settings.

(cherry picked from commit fee3bd48b414c88f7e5abc37775f944aa94c808b)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 5fcadcb9755b7fc8b28638cbfd5696e72841a316)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 92264762e5e3caf6a8030c874e9ea57998cc841e)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoCLEANUP: quic: fix typo in quic_tx trace
Amaury Denoyelle [Mon, 8 Sep 2025 09:56:12 +0000 (11:56 +0200)]
CLEANUP: quic: fix typo in quic_tx trace

Fix trace in qc_may_build_pkt().

This can be backported up to 3.0.

(cherry picked from commit fb8c6e20305a866af0a48dc5b3c82bfadbae6bf8)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 78489c1fb6d84f3712678399e40db3ba79e1551e)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 6b6c649811619ce2b4ccfc573ba99ff400fcfe43)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: cpu_topo: work around a small bug in musl's CPU_ISSET()
Willy Tarreau [Sat, 6 Sep 2025 08:50:31 +0000 (10:50 +0200)]
BUG/MINOR: cpu_topo: work around a small bug in musl's CPU_ISSET()

As found in GH issue #3103, CPU_ISSET() on musl 1.25 doesn't match the man
page which says it's returning an int. The reason is pretty simple, it's
a macro that operates on the bits directly and returns the result of the
bit field applied to the mask as an unsigned long. Bits above 31 will
simply be dropped if returned as an int, which causes CPUs 32..63 to
appear as absent from cpu_sets.

The fix is trivial, it consists in just comparing the result against zero
(i.e. turning it to a boolean), but before it's merged and deployed we'll
have to face such deployments, so better implement the same workaround
in the code here since we have access to the raw long value.

This workaround should be backported to 3.0.

(cherry picked from commit 75bd9255dd04d9247f1e555023cc45f5e17936ca)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 3847df920f4610c5b03061b9f3da6ca295fda228)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit ac35ac8af7232002a0692ea03b25129fd9dd7edb)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUILD: trace: silence a bogus build warning at -Og
Willy Tarreau [Fri, 5 Sep 2025 07:15:05 +0000 (09:15 +0200)]
BUILD: trace: silence a bogus build warning at -Og

gcc-13.3 at -Og emits an incorrect build warning in trace.c about a
possibly initialized variable:

  In file included from include/haproxy/api.h:35,
                   from src/trace.c:22:
  src/trace.c: In function 'trace_parse_cmd':
  include/haproxy/bug.h:431:17: warning: 'arg' may be used uninitialized [-Wmaybe-uninitialized]
    431 |                 free(*__x);                                             \
        |                 ^~~~~~~~~~
  src/trace.c:1136:9: note: in expansion of macro 'ha_free'
   1136 |         ha_free(&oarg);
        |         ^~~~~~~
  src/trace.c:1008:15: note: 'arg' was declared here
   1008 |         char *arg, *oarg;
        |               ^~~

The warning is obviously wrong since the field is initialized in one of
the two branches of an "if" whose complementary one returns. But the
compiler doesn't seem to see this because the if is in fact two ifs each
with an opposite condition: "if (arg_src)" then "if (!arg_src)". Let's
just move upwards the default one that returns and eliminate the other
one. Reading the diff with "git diff -b" better shows the tiny change.

It could be backported to 3.0.

(cherry picked from commit abfd6f3b93db72f65015cb3278fe5182bf174493)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 77fda88fd1147d1a7d7daa6618809cb0df454791)
[cf: Remove help message]
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 95fbc12290969eee8b65a29aa4bb070de4039c7c)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: log: fix potential memory leak upon error in add_to_logformat_list()
Aurelien DARRAGON [Thu, 4 Sep 2025 08:26:37 +0000 (10:26 +0200)]
BUG/MINOR: log: fix potential memory leak upon error in add_to_logformat_list()

As reported on GH #3099, upon memory error add_to_logformat_list() will
return and error but it fails to properly memory which was allocated
within the function, which could result in memory leak.

Let's free all relevant variables allocated by the function before returning.

No backport needed unless 22ac1f5ee ("("BUG/MINOR: log: Add OOM checks for
calloc() and malloc() in logformat parser and dup_logger()") is.

(cherry picked from commit c97ced3f938271c9d648594d6c4bfcd194c36a7d)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 5d0cd28ce889a85fb4ef8d1617f8f61abd1ebea7)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 9ac6454aa1ebcb813f61f7b4fb6ac07dbb21d7ec)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: connection: streamline conn detach from lists
Amaury Denoyelle [Thu, 4 Sep 2025 14:26:19 +0000 (16:26 +0200)]
BUG/MINOR: connection: streamline conn detach from lists

Over their lifetime, connections are attached to different list. These
lists depends on whether connection is on frontend or backend side.
Attach point members are stored via a union in struct connection. The
next commit reorganizes them so that a proper frontend/backend
separation is performed :

  commit a96f1286a75246fef6db3e615fabdef1de927d83
  BUG/MINOR: connection: rearrange union list members

On conn_free(), connection instance must be removed from these lists to
ensure there is no use-after-free case. However code was still shaky
there, despite no real issue. Indeed, <toremove_list> was detached for
all connections, despite being only used on backend side only.

This patch streamlines the freeing of connection. Now, <toremove_list>
detach is performed in conn_backend_deinit(). Moreover, a new helper
conn_frontend_deinit() is defined. It ensures that <stopping_list>
detach is done. Prior it was performed individually by muxes.

Note that a similar procedure is performed when the connection is
reversed. Hence, conn_frontend_deinit() is now used here as well,
rendering reversal from FE to BE or vice versa symmetrical.

As mentionned above, no crash occured prior to this patch, but the code
was fragile, in particular access to <toremove_list> for frontend
connections. Thus this patch is considered as a bug fix worthy of a
backport along with above mentionned patch, currently up to 3.0.

(cherry picked from commit 687df405fe6c1bd95fdebba03f3491c26f82692d)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 1636d094b23fe56b5dd672d46e6de32aeb7efe6f)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 55c056cdd8d4d3ef9b0e400a3f0b6c4a823c815b)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MEDIUM: conn: fix UAF on connection after reversal on edge
Amaury Denoyelle [Thu, 4 Sep 2025 14:35:49 +0000 (16:35 +0200)]
BUG/MEDIUM: conn: fix UAF on connection after reversal on edge

When a connection is reversed, some elements must be resetted prior to
reusing it. Most notably, connection must be removed from lists specific
on frontend/backend sides.

When reverse was performed for frontend to backend side, connection was
not removed via its <stopping_list> attach point. On previous releases,
this did not cause any issue. However, crashes start to occur recently,
probably due to the recent reorganization of connection list attach
points from the following patch.

  commit a96f1286a75246fef6db3e615fabdef1de927d83
  BUG/MINOR: connection: rearrange union list members

To fix this, simply ensure that <stopping_list> detach is performed via
conn_reverse().

This patch must be backported up to 3.0 release.

(cherry picked from commit 27ff7ff296dec073e84cf03106a3e285181c24d8)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit f656fb45fe7e2873541db31308c010fbc78ff6e3)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 8faba2b9062ce4ade65cee5ec556c111b54c2390)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoREGTESTS: explicitly use "balance roundrobin" where RR is needed
Willy Tarreau [Thu, 4 Sep 2025 06:18:53 +0000 (08:18 +0200)]
REGTESTS: explicitly use "balance roundrobin" where RR is needed

A few tests explicitly rely on the server ordering granted by
"balance roundrobin", but didn't specify the balance algorithm.
As it will change soon, let's explicit it.

(cherry picked from commit 60931ceae9bd52db27dde002af2fe3232cd2b811)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 7f5293656fa3963cf4cee6376b20eb8a15703901)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 0cc80c44505dfa528fecc68c3a460ab15e28d6ed)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoMINOR: quic: Add more information about RX packets
Frederic Lecaille [Tue, 2 Sep 2025 08:48:33 +0000 (10:48 +0200)]
MINOR: quic: Add more information about RX packets

This patch is very useful to debug issues at RX packet processing level.

Should be easily backported as far as 2.6 (for debug purposes).

(cherry picked from commit 58b153b8824a12493ac9808403883db35496517a)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit df2c048d089454f6d1426df0a5a0e43c79615a36)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit f93e6193ae69072931ec8dd3add4cc488f18eb51)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUILD: acl: silence a possible null deref warning in parse_acl_expr()
Willy Tarreau [Tue, 2 Sep 2025 15:41:51 +0000 (17:41 +0200)]
BUILD: acl: silence a possible null deref warning in parse_acl_expr()

The fix in commit 441cd614f9 ("BUG/MINOR: acl: set arg_list->kw to
aclkw->kw string literal if aclkw is found") involves an unchecked
access to "al" after that one is tested for possibly being NULL. This
rightfully upsets Coverity (GH #3095) and might also trigger warnings
depending on the compilers. However, no known caller to date passes
a NULL arg list here so there's no way to trigger this theoretical
bug.

This should be backported along with the fix above to avoid emitting
warnings, possibly as far as 2.6 since that fix was tagged as such.

(cherry picked from commit 4902195313f16eeca44507bfbc9e5b3b8016a61f)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 137dccf2c7c0e066ed5008ebc2b6ac66bd143752)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit eb39181b955a677651e29eb2a276715d0be36b53)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: haproxy: be sure not to quit too early on soft stop
Willy Tarreau [Tue, 2 Sep 2025 09:26:50 +0000 (11:26 +0200)]
BUG/MINOR: haproxy: be sure not to quit too early on soft stop

The fix in 4a9e3e102e ("BUG/MINOR: haproxy: only tid 0 must not sleep
if got signal") had the nasty side effect of breaking the graceful
reload operations: threads whose id is non-zero could quit too early and
not process incoming traffic, which is visible with broken connections
during reloads. They just need to ignore the the stopping condition
until the signal queue is empty. In any case, it's the thread in charge
of the signal queue which will notify them once it receives the signal.

It was verified that connections are no longer broken with this fix,
and that the issue that required it (#2537, looping threads on reload)
does not re-appear with the reproducer, while it still did without the
fix above. Since the fix above was backported to every stable version,
this one will also have to.

(cherry picked from commit c128887b8ef1a9b010b5de6cef2879f1d8bc204c)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 9462ca9ba5e0c24cd426c8e2611c38e35277a4cd)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit a8ce27cc8fcef0b7b49b031c4735bc8b4118c4df)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: quic: fix padding issue on INITIAL retransmit
Amaury Denoyelle [Fri, 29 Aug 2025 12:07:47 +0000 (14:07 +0200)]
BUG/MINOR: quic: fix padding issue on INITIAL retransmit

On loss detection timer expiration, qc_dgrams_retransmit() is used to
reemit lost packets. Different code paths are present depending on the
active encryption level.

If Initial level is still initialized, retransmit is performed both for
Initial and Handshake spaces, by first retrieving the list of lost
frames for each of them.

Prior to this patch, Handshake level was always registered for emission
after Initial, even if it dit not have any frame to reemit. In this
case, most of the time it would result in a datagram containing Initial
reemitted frames packet coalesced with a Handshake packet consisting
only of a PADDING frame. This is because padding is only added for the
last registered QEL.

For QUIC backend support, this may cause issues. This is because
contrary to QUIC server side, Initial and Handshake levels keys are not
derived simultaneously for a QUIC client. Thus, if the latter keys are
unavailable, Handshake packet cannot be encoded in sending, leaving a
single Initial packet. However, this is now too late to add PADDING.
Thus the resulting datagram is invalid : this triggers the BUG_ON()
assert failure located on qc_txb_store().

This patch fixes this by amending qc_dgrams_retransmit(). Now, Handshake
level is only registered for emission if there is frame to retransmit,
which implies that Handshake keys are already available. Thus, PADDING
will now either be added at Initial or Handshake level as expected.

Note that this issue should not be present on QUIC frontend, due to
Initial and Handshake keys derivation almost simultaneously. However,
this should still be backported up to 3.0.

(cherry picked from commit e9b78e3fb17d91cb7502ed481e2fdfec5ad2a174)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit c7c033642e068c81c662e5a249e0c2dafe645873)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 61b5731dd90c58282c0f605d5117ef23ac0ca15f)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: quic: fix room check if padding requested
Amaury Denoyelle [Fri, 29 Aug 2025 12:17:44 +0000 (14:17 +0200)]
BUG/MINOR: quic: fix room check if padding requested

qc_prep_pkts() activates padding when building an Initial packet. This
ensures that resulting datagram will always be at least 1.200 bytes,
which is mandatory to prevent deadlock over anti-amplication.

Prior to padding activation, a check is performed to ensure that output
buffer is big enough for a padded datagram. However, this did not take
into account previously built packets which would be coalesced in the
same datagram. Thus this patch fixes this comparison check.

In theory, prior to this patch, in some cases Initial packets could not
be built despite a datagram of the proper size. Currently, this probably
never happens as Initial packet is always the first encoded in a
datagram, thus there is no coalesced packet prior to it. However, there
is no hard requirement on this, so it's better to reflect this in the
code.

This should be backported up to 2.6.

(cherry picked from commit 34d5bfd23c30e08228d7939ba94a839b03716489)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 0ecea5e96a3322c74b8eb2478f45d286bf43a6f9)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit ffe81c3628e64800156d276c6716077d18f327e4)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: quic: ignore AGAIN ncbuf err when parsing CRYPTO frames
Frederic Lecaille [Mon, 1 Sep 2025 12:35:14 +0000 (14:35 +0200)]
BUG/MINOR: quic: ignore AGAIN ncbuf err when parsing CRYPTO frames

This fix follows this previous one:

    BUG/MINOR: quic: reorder fragmented RX CRYPTO frames by their offsets

which is not sufficient when a client fragments and mixes its CRYPTO frames AND
leaveswith holes by packets. ngtcp2 (and perhaps chrome) splits theire CRYPTO
frames but without hole by packet. In such a case, the CRYPTO parsing leads to
QUIC_RX_RET_FRM_AGAIN errors which cannot be fixed when the peer resends its packets.
Indeed, even if the peer resends its frames in a different order, this does not
help because since the previous commit, the CRYPTO frames are ordered on haproxy side.

This issue was detected thanks to the interopt tests with quic-go as client. This
client fragments its CRYPTO frames, mixes them, and generate holes, and most of
the times with the retry test.

To fix this, when a QUIC_RX_RET_FRM_AGAIN error is encountered, the CRYPTO frames
parsing is not stop. This leaves chances to the next CRYPTO frames to be parsed.

Must be backported as far as 2.6 as the commit mentioned above.

(cherry picked from commit fba80c7fe84707afe134a5b240a2842a0a51f78f)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 02d7f2b30df2c6dd4de371c31eab423e9e7bce1f)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 47a60d8c8e446456cc3406ac5540fbc4180d9ff5)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: tools: Add OOM check for malloc() in indent_msg()
Alexander Stephan [Mon, 1 Sep 2025 10:01:50 +0000 (10:01 +0000)]
BUG/MINOR: tools: Add OOM check for malloc() in indent_msg()

This patch adds a missing out-of-memory (OOM) check after
the call to `malloc()` in `indent_msg()`. If memory
allocation fails, the function returns NULL to prevent
undefined behavior.

Co-authored-by: Christian Norbert Menges <christian.norbert.menges@sap.com>
(cherry picked from commit 26776c7b8f963299585300472a2b29ad39e47943)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 35c11b9b05b1adbfc75338a08660460458507e6f)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit ffbcd48e5af6bcfd25a14ab8bb0553e2954ff0e6)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: compression: Add OOM check for calloc() in parse_compression_options()
Alexander Stephan [Mon, 1 Sep 2025 09:57:51 +0000 (09:57 +0000)]
BUG/MINOR: compression: Add OOM check for calloc() in parse_compression_options()

This patch adds a missing out-of-memory (OOM) check after
the call to `calloc()` in `parse_compression_options()`. If
memory allocation fails, an error message is set, the function
returns -1, and parsing is aborted to ensure safe handling
of low-memory conditions.

Co-authored-by: Christian Norbert Menges <christian.norbert.menges@sap.com>
(cherry picked from commit aa20905ac9e45c6caa8929f4686020708209e2bf)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit e39edf65b0076a106a4475d73e3496df809f44ef)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 077efc51806cf6b65b26371fcb972ef8dff60869)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: cfgparse: Add OOM check for calloc() in cfg_parse_listen()
Alexander Stephan [Mon, 1 Sep 2025 09:51:19 +0000 (09:51 +0000)]
BUG/MINOR: cfgparse: Add OOM check for calloc() in cfg_parse_listen()

This commit adds a missing out-of-memory (OOM) check
after the call to `calloc()` in `cfg_parse_listen()`.
If memory allocation fails, an alert is logged, error
codes are set, and parsing is aborted to prevent
undefined behavior.

Co-authored-by: Christian Norbert Menges <christian.norbert.menges@sap.com>
(cherry picked from commit 73f9a75894c660dd034439e0bc343aa00489dbc9)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 8a4bc5b7fc474e1b7178f8cf25428077c3fb7c34)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit e9065b50776baca3c6d475539b89b2e7ab994b7c)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: acl: Add OOM check for calloc() in smp_fetch_acl_parse()
Alexander Stephan [Mon, 1 Sep 2025 09:47:30 +0000 (09:47 +0000)]
BUG/MINOR: acl: Add OOM check for calloc() in smp_fetch_acl_parse()

This patch adds a missing out-of-memory (OOM) check after
the call to `calloc()` in `smp_fetch_acl_parse()`. If
memory allocation fails, an error message is set and
the function returns 0, improving robustness in
low-memory situations.

Co-authored-by: Christian Norbert Menges <christian.norbert.menges@sap.com>
(cherry picked from commit c3e69cf065c59acbe01db5452f29b7ac199354d5)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 1801fc6dd7041cc567a0fd38e5cf18963ea3cd69)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 68f494f900443f5e630e554031308c93b366425c)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: log: Add OOM checks for calloc() and malloc() in logformat parser and...
Alexander Stephan [Mon, 1 Sep 2025 09:36:07 +0000 (09:36 +0000)]
BUG/MINOR: log: Add OOM checks for calloc() and malloc() in logformat parser and dup_logger()

This patch adds missing out-of-memory (OOM) checks after calls
to `calloc()` and `malloc()` in the logformat parser and the
`dup_logger()` function. If memory allocation fails, an error
is reported or NULL is returned, preventing undefined behavior
in low-memory conditions.

Co-authored-by: Christian Norbert Menges <christian.norbert.menges@sap.com>
(cherry picked from commit 22ac1f5ee9889eb7273201de0d92449d9fc5e3fa)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 0fd91432f06ee6a7b427664be127b02c854e34ab)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit de370ed1e1925fa54778ae021f92c97f96ca1a03)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: halog: Add OOM checks for calloc() in filter_count_srv_status() and filter...
Alexander Stephan [Mon, 1 Sep 2025 09:32:04 +0000 (09:32 +0000)]
BUG/MINOR: halog: Add OOM checks for calloc() in filter_count_srv_status() and filter_count_url()

This patch adds missing out-of-memory (OOM) checks after calls to
calloc() in the functions `filter_count_srv_status()` and `filter_count_url()`.
If memory allocation fails, an error message is printed to stderr
and the process exits with status 1. This improves robustness
and prevents undefined behavior in low-memory situations.

Co-authored-by: Christian Norbert Menges <christian.norbert.menges@sap.com>
(cherry picked from commit fbd0fb20a22a77f85ca2ec0e41cc5df51de3d30a)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 3e7e85cd7bee9aea13505a19096fa35e7652a967)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 670df778d8acfe77a6d259c217a490dccc00509b)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MEDIUM: server: Duplicate healthcheck's alpn inherited from default server
Christopher Faulet [Mon, 1 Sep 2025 13:04:18 +0000 (15:04 +0200)]
BUG/MEDIUM: server: Duplicate healthcheck's alpn inherited from default server

When "check-alpn" parameter is inherited from the default server, the value
is not duplicated, the pointer of the default server is used. However, when
this parameter is overridden, the old value is released. So the "check-alpn"
value of the default server is released. So it is possible to have a UAF if
if another server inherit from the same the default server.

To fix the issue, the "check-alpn" parameter must be handled the same way
the "alpn" is. The default value is duplicated. So it could be safely
released if it is forced on the server line.

This patch should fix the issue #3096. It must be backported to all stable
versions.

(cherry picked from commit f7a04b428a47edeabfe40bf1a48a85b03c105633)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 361ae50063941df0d7269489646fc4e5978ea97f)
[cf: ctx adjt]
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 015732185bee1f75a3160a8a99369511a29c7aa4)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoREG-TESTS: map_redirect: Don't use hdr_dom in ACLs with "-m end" matching method
Christopher Faulet [Mon, 1 Sep 2025 13:37:50 +0000 (15:37 +0200)]
REG-TESTS: map_redirect: Don't use hdr_dom in ACLs with "-m end" matching method

hdr_dom() is a alias of "hdr() -m dom". So using it with another explicit
matching method does not work because the matching on the domain will never
be performed. Only the last matching method is used. The scripts was working
by chance because no port was set on host header values.

The script was fixed by using "host_only" converter. In addition, host
header values were changed to have a port now.

(cherry picked from commit d09d7676d024f12a92390d7589895a2c4bae8e2b)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit ec64dcd295b0aaae77a8dcc840978266256edad4)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 5ff7dde86be5c759976c79c98710890e59c666c7)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MAJOR: mux-quic: fix crash on reload during emission
Amaury Denoyelle [Mon, 1 Sep 2025 13:07:53 +0000 (15:07 +0200)]
BUG/MAJOR: mux-quic: fix crash on reload during emission

MUX QUIC restricts buffer allocation per connection based on the
underlying congestion window. If a QCS instance cannot allocate a new
buffer, it is put in a buf_wait list. Typically, this will cause stream
upper layer to subscribe for sending.

A BUG_ON() was present on snd_buf and nego_ff callback prologue to
ensure that these functions were not called if QCS is already in
buf_wait list. The objective was to guarantee that there is no wake up
on a stream if it cannot allocate a buffer.

However, this BUG_ON() is not correct, as it can be fired legitimely.
Indeed, stream layer can retry emission even if no wake up occured. This
case can happen on reload. Thus, BUG_ON() will cause an unexpected
crash.

Fix this by removing these BUG_ON(). Instead, snd_buf/nego_ff callbacks
ensure that QCS is not subscribed in buf_wait list. If this is the case,
a nul value will be returned, which is sufficient for the stream layer
to pause emission and subscribe if necessary.

Occurences for this crash have been reported on the mailing list. It is
also the subject of github issue #3080, which should be fixed with this
patch.

This must be backported up to 3.0.

(cherry picked from commit dcf22616123432e3230c0a084cf13c5adc57b851)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 49fd57fe90939f15e7f75040a968266d7fa0112a)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 54115fc2205ffbfe19a36212178cd861a210883f)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MEDIUM: quic: CRYPTO frame freeing without eb_delete()
Frederic Lecaille [Mon, 1 Sep 2025 08:39:00 +0000 (10:39 +0200)]
BUG/MEDIUM: quic: CRYPTO frame freeing without eb_delete()

Since this commit:

BUG/MINOR: quic: reorder fragmented RX CRYPTO frames by their offsets

when they are parsed, the CRYPTO frames are ordered by their offsets into an ebtree.
Then their data are provided to the ncbufs.

But in case of error, when qc_handle_crypto_frm() returns QUIC_RX_RET_FRM_FATAL
or QUIC_RX_RET_FRM_AGAIN), they remain attached to their tree. Then
from <err> label, they are deteleted and deleted (with a while(node) { eb_delete();
qc_frm_free();} loop). But before this loop, these statements directly
free the frame without deleting it from its tree, if this is a CRYPTO frame,
leading to a use after free when running the loop:

     if (frm)
    qc_frm_free(qc, &frm);

This issue was detected by the interop tests, with quic-go as client. Weirdly, this
client sends CRYPTO frames by packet with holes.
Must be backported as far as 2.6 as the commit mentioned above.

(cherry picked from commit 800ba73a9ca39dc0e0c33230c87ececd540f5541)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit ed1b2dc1f8ec5a68dbf3e075d4bffd5bc738bf2b)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit e3b7cd5d61b6ea1c1b42ddcd5539e1fdf9cfe542)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoCLEANUP: quic: remove a useless CRYPTO frame variable assignment
Frederic Lecaille [Mon, 1 Sep 2025 07:29:16 +0000 (09:29 +0200)]
CLEANUP: quic: remove a useless CRYPTO frame variable assignment

This modification should have arrived with this commit:

MINOR: quic: remove ->offset qf_crypto struct field

Since this commit, the CRYPTO offset node key assignment is done at parsing time
when calling qc_parse_frm() from qc_parse_pkt_frms().

This useless assigment has been reported in GH #3095 by coverity.

This patch should be easily backported as far as 2.6 as the one mentioned above
to ease any further backport to come.

(cherry picked from commit 90126ec9b733694d4c5ad0f20c221cff639db95f)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit daf26577556f36c208a8eb0b06cbc5bb1ffe74e2)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit c410e74be38562a4f9a244c2025823e35e8e0f65)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoMINOR: doc: add missing statistics column
Amaury Denoyelle [Thu, 28 Aug 2025 16:34:54 +0000 (18:34 +0200)]
MINOR: doc: add missing statistics column

Complete documentation with missing description of newly added columns.

This must be backported up to 2.8.

(cherry picked from commit fb43343f6fba7333b7138992841a7536e601166a)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit da07f7325fdf5a8e7d7da579c0eeeb6644824837)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 80447b35feaaa5224fd2106ddc54c8d96f191cf3)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoMINOR: doc: add missing statistics column
Amaury Denoyelle [Thu, 28 Aug 2025 16:27:26 +0000 (18:27 +0200)]
MINOR: doc: add missing statistics column

Complete documentation with missing description of newly added columns.

This should be backported up to 2.4

(cherry picked from commit f0710a1fbcf054bb7da843670fc68cf69f5f9705)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 09135aecf62234d16206521b7ff3277801969876)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 91fccab6782a117bea4cb6bc523d5f48aa9aaa62)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoDOC: configuration: confuse "strict-mode" with "zero-warning"
William Lallemand [Thu, 28 Aug 2025 15:31:27 +0000 (17:31 +0200)]
DOC: configuration: confuse "strict-mode" with "zero-warning"

4b10302fd8 ("MINOR: cfgparse: implement a simple if/elif/else/endif
macro block handler") introduces a confusion between "strict-mode" and
"zero-warning".

This patch fixes the issue by changing "strict-mode" by "zero-warning"
in section 2.4. Conditional blocks.

Must be backported as far as 2.4.

(cherry picked from commit e0ec01849fc6eff6a6e9ac67e23dea03d779fe70)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 98d4d720e11ef808e849bba76e902fee7f6419d1)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 46cf247231358866b5c6c03e0176f7e5290a2492)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoDOC: unreliable sockpair@ on macOS
William Lallemand [Thu, 28 Aug 2025 13:23:02 +0000 (15:23 +0200)]
DOC: unreliable sockpair@ on macOS

We discovered that the sockpair@ protocol is unreliable in macOS, this
is the same problem that we fixed in d7f6819. But it's not possible to
implement a acknowledgment once the socket are in non-blocking mode.

The problem was discovered in issue #3045.

Must be backported in every stable versions.

(cherry picked from commit 8a456399dba70c9880394a7e85f9523feb1505c5)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 0746af209c3600a908b141f213c8ba7bb807840a)
[cf: ctx adjt]
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 16ab3761721b11803d6b5df38a487a8bf48a8b49)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: server: decrement session idle_conns on del server
Amaury Denoyelle [Tue, 19 Aug 2025 13:41:43 +0000 (15:41 +0200)]
BUG/MINOR: server: decrement session idle_conns on del server

When a server is deleted, each of its idle connections are removed. This
is also performed for every private connections stored on sessions which
referenced the target server.

As mentionned above, these private connections are idle, guaranteed by
srv_check_for_deletion(). A BUG_ON() on CO_FL_SESS_IDLE is already
present to guarantee this. Thus, these connections are accounted on the
session to enforce max-session-srv-conns limit.

However, this counter is not decremented during private conns cleanup on
"del server" handler. This patch fixes this by adding a decrement for
every private connections removed via "del server".

This should be backported up to 3.0.

(cherry picked from commit 0be225f341485a46d17bc17ccc7906613bfbc3d0)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 15805ddc6ddfcde5e0b777f295f2fce1bef2d01a)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit f8d6215a9e4a1442ece0b7fcef10ab24c6f83973)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: connection: remove extra session_unown_conn() on reverse
Amaury Denoyelle [Thu, 21 Aug 2025 15:30:10 +0000 (17:30 +0200)]
BUG/MINOR: connection: remove extra session_unown_conn() on reverse

When a connection is reversed via rhttp protocol on the edge endpoint,
it migrates from frontend to backend side. This operation is performed
by conn_reverse(). During this transition, the conn owning session is
freed as it becomes unneeded.

Prior to this patch, session_unown_conn() was also called during
frontend to backend migration. However, this is unnecessary as this
function is only used for backend connection reuse. As such, this patch
removes this unnecessary call.

This does not cause any harm to the process as session_unown_conn() can
handle a connection not inserted yet. However, for clarity purpose it's
better to backport this patch up to 3.0.

(cherry picked from commit 04f05f188058e8931f203efc44f72a009bc85c0f)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit d04278827974e55f1e29746b23e5a030876aeeb5)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit bdd74840c89b9eb0791f3ab8e2a08d0ee8054705)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: connection: rearrange union list members
Amaury Denoyelle [Wed, 27 Aug 2025 12:58:59 +0000 (14:58 +0200)]
BUG/MINOR: connection: rearrange union list members

A connection can be stored in several lists, thus there is several
attach points in struct connection. Depending on its proxy side, either
frontend or backend, a single connection will only access some of them
during its lifetime.

As an optimization, these attach points are organized in a union.
However, this repartition was not correctly achieved along
frontend/backend side delimitation.

Furthermore, reverse HTTP has recently been introduced. With this
feature, a connection can migrate from frontend to backend side or vice
versa. As such, it becomes even more tedious to ensure that these
members are always accessed in a safe way.

This commit rearrange these fields. First, union is now clearly splitted
between frontend and backend only elements. Next, backend elements are
initialized with conn_backend_init(), which is already used during
connection reversal on an edge endpoint. A new function
conn_frontend_init() serves to initialize the other members, called both
on connection first instantiation and on reversal on a dialer endpoint.

This model is much cleaner and should prevent any access to fields from
the wrong side.

Currently, there is no known case of wrong access in the existing code
base. However, this cleanup is considered an improvement which must be
backported up to 3.0 to remove any possible undefined behavior.

(cherry picked from commit a96f1286a75246fef6db3e615fabdef1de927d83)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit efed852704238d4a523a1154c061e47ca704b951)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 284a60cbbd00409a98e8b2f238ab6667748f0cd1)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: acl: set arg_list->kw to aclkw->kw string literal if aclkw is found
Valentine Krasnobaeva [Tue, 26 Aug 2025 22:33:48 +0000 (00:33 +0200)]
BUG/MINOR: acl: set arg_list->kw to aclkw->kw string literal if aclkw is found

During configuration parsing *args can contain different addresses, it is
changing from line to line. smp_resolve_args() is called after the
configuration parsing, it uses arg_list->kw to create an error message, if a
userlist referenced in some ACL is absent. This leads to wrong keyword names
reported in such message or some garbage is printed.

It does not happen in the case of sample fetches. In this case arg_list->kw is
assigned to a string literal from the sample_fetch struct returned by
find_sample_fetch(). Let's do the same in parse_acl_expr(), when find_acl_kw()
lookup returns a corresponding acl_keyword structure.

This fixes the issue #3088 at GitHub.
This should be backported in all stable versions since 2.6 including 2.6.

(cherry picked from commit 441cd614f92bd3d7d66003e509ae71bcb779b0f5)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 802fc568c81c67af3461d3b58a324a4d8aef5508)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 789c30fc9b6f3ed1fcb9e12b8133db7e2ea36393)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: mux-quic: trace with non initialized qcc
Frederic Lecaille [Thu, 28 Aug 2025 05:58:00 +0000 (07:58 +0200)]
BUG/MINOR: mux-quic: trace with non initialized qcc

This issue leads to crashes when the QUIC mux traces are enabled and could be
reproduced with -dMfail. When the qcc allocation fails (qcc_init()) haproxy
crashes into qmux_dump_qcc_info() because ->conn qcc member is initialized:

Program terminated with signal SIGSEGV, Segmentation fault.
    at src/qmux_trace.c:146
146             const struct quic_conn *qc = qcc->conn->handle.qc;
[Current thread is 1 (LWP 1448960)]
(gdb) p qcc
$1 = (const struct qcc *) 0x7f9c63719fa0
(gdb) p qcc->conn
$2 = (struct connection *) 0x155550508
(gdb)

This patch simply fixes the TRACE() call concerned to avoid <qcc> object
dereferencing when it is NULL.

Must be backported as far as 3.0.

(cherry picked from commit ffa926ead3f17cd8da773daa137184619bfc1a0a)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 46a8238ca06f28a057658c2dade22ac894c571cf)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit cc3c9a786f8eeba582342838014c2c2e29c3b4da)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoMINOR: quic: remove ->offset qf_crypto struct field
Frederic Lecaille [Wed, 27 Aug 2025 14:28:04 +0000 (16:28 +0200)]
MINOR: quic: remove ->offset qf_crypto struct field

This patch follows this previous bug fix:

    BUG/MINOR: quic: reorder fragmented RX CRYPTO frames by their offsets

where a ebtree node has been added to qf_crypto struct. It has the same
meaning and type as ->offset_node.key field with ->offset_node an eb64tree node.
This patch simply removes ->offset which is no more useful.

This patch should be easily backported as far as 2.6 as the one mentioned above
to ease any further backport to come.

(cherry picked from commit 31c17ad837195c70fb6d4e427845ded1c6acffaa)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 4a1a08be4f34feafb637115a1d8536ad70a2df33)
[cf: Some changes were made inlined in quic_tx.c because some functions does
 not exist in 3.2 and lower]
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 565d73a3b1d6fa562408392bb55340a5e7b8b967)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: quic: reorder fragmented RX CRYPTO frames by their offsets
Frederic Lecaille [Wed, 27 Aug 2025 12:18:25 +0000 (14:18 +0200)]
BUG/MINOR: quic: reorder fragmented RX CRYPTO frames by their offsets

This issue impacts the QUIC listeners. It is the same as the one fixed by this
commit:

BUG/MINOR: quic: repeat packet parsing to deal with fragmented CRYPTO

As chrome, ngtcp2 client decided to fragment its CRYPTO frames but in a much
more agressive way. This could be fixed with a list local to qc_parse_pkt_frms()
to please chrome thanks to the commit above. But this is not sufficient for
ngtcp2 which often splits its ClientHello message into more than 10 fragments
with very small ones. This leads the packet parser to interrupt the CRYPTO frames
parsing due to the ncbuf gap size limit.

To fix this, this patch approximatively proceeds the same way but with an
ebtree to reorder the CRYPTO by their offsets. These frames are directly
inserted into a local ebtree. Then this ebtree is reused to provide the
reordered CRYPTO data to the underlying ncbuf (non contiguous buffer). This way
there are very few less chances for the ncbufs used to store CRYPTO data
to reach a too much fragmented state.

Must be backported as far as 2.6.

(cherry picked from commit d753f24096dafdef227fe66621513086c2c663c1)
[cf: ctx adjt]
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 9146b06962565992724ec12e35b3b77bb3274805)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit b673c57a165614598919f3b7ccfe1344bc7e3d97)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MEDIUM: Remove sync sends from streams to applets
Christopher Faulet [Tue, 22 Jul 2025 13:15:34 +0000 (15:15 +0200)]
BUG/MEDIUM: Remove sync sends from streams to applets

When the applet API was reviewed to use dedicated buffers, the support for
sends from the streams to applets was added. Unfortunately, it was not a
good idea because this way it is possible to deliver data to an applet and
release it just after, truncated data. Indeed, the release stage for applets
is related to the stream release itself. However, unlike the multiplexers,
the applets cannot survive to a stream for now.

So, for now, the sync sends from the streams is removed for applets, waiting
for a better way to handle the applets release stage.

Note that this only concerns applets using their own buffers. And of now,
the bug is harmless because all refactored applets are on server side and
consume data first. But this will be an issue with the HTTP client.

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

(cherry picked from commit d9855102cf303948ffc842e8c0f7939e67a29bd9)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 72ca5e5e8f3fcbc2f2ef6ed312e424a22235730d)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 99039c8e6ece475b5e19b1df4d0c7a9702bd6dc2)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MEDIUM: stconn: Fix conditions to know an applet can get data from stream
Christopher Faulet [Fri, 18 Jul 2025 07:09:28 +0000 (09:09 +0200)]
BUG/MEDIUM: stconn: Fix conditions to know an applet can get data from stream

sc_is_send_allowed() function is used to know if an applet is able to
receive data from the stream. But this function was designed for applets
using the channels buffer. It is not adapted to applets using their own
buffers.

when the SE_FL_WAIT_DATA flag is set, it means the applet is waiting for
more data and should not be woken up without new data. For applets using
channels buffer, just testing the flag is enough because process_stream()
will remove if when more data will be available. For applets using their own
buffers, it is more complicated. Some data may be blocked in the output
channel buffer. In that case, and when the applet input buffer can receive
daa, the applet can be woken up.

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

(cherry picked from commit 41a40680ce1c513d49a40d5e9f3c80a8a70a369f)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit ed3273f771c778527a19f85bd646b7c4a21ce0d9)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 22210bb66f77d87cd8004105e029ef3f893ed3d7)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoMINOR: quic: centralize padding for HP sampling on packet building
Amaury Denoyelle [Tue, 12 Aug 2025 08:40:06 +0000 (10:40 +0200)]
MINOR: quic: centralize padding for HP sampling on packet building

The below patch has simplified INITIAL padding on emission. Now,
qc_prep_pkts() is responsible to activate padding for this case, and
there is no more special case in qc_do_build_pkt() needed.

  commit 8bc339a6ad4702f2c39b2a78aaaff665d85c762b
  BUG/MAJOR: quic: fix INITIAL padding with probing packet only

However, qc_do_build_pkt() may still activate padding on its own, to
ensure that a packet is big enough so that header protection decryption
can be performed by the peer. HP decryption is performed by extracting a
sample from the ciphered packet, starting 4 bytes after PN offset.
Sample length is 16 bytes as defined by TLS algos used by QUIC. Thus, a
QUIC sender must ensures that length of packet number plus payload
fields to be at least 4 bytes long. This is enough given that each
packet is completed by a 16 bytes AEAD tag which can be part of the HP
sample.

This patch simplifies qc_do_build_pkt() by centralizing padding for this
case in a single location. This is performed at the end of the function
after payload is completed. The code is thus simpler.

This is not a bug. However, it may be interesting to backport this patch
up to 2.6, as qc_do_build_pkt() is a tedious function, in particular
when dealing with padding generation, thus it may benefit greatly from
simplification.

(cherry picked from commit 1529ec1a25cc216f7613517e5e8c936852d18007)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 6dfdf20e00b491f6fc4708917024a51620850a09)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 4a2a5ee5dde65c8f3cfb2ce6765e93b9ae728388)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MAJOR: quic: fix INITIAL padding with probing packet only
Amaury Denoyelle [Mon, 11 Aug 2025 15:54:39 +0000 (17:54 +0200)]
BUG/MAJOR: quic: fix INITIAL padding with probing packet only

A QUIC datagram that contains an INITIAL packet must be padded to 1.200
bytes to prevent any deadlock due to anti-amplification protection. This
is implemented by encoding a PADDING frame on the last packet of the
datagram if necessary.

Previously, qc_prep_pkts() was responsible to activate padding when
calling qc_do_build_pkt(), as it knows which packet is the last to
encode. However, this has the side-effect of preventing PING emission
for probing with no data as this case was handled in an else-if branch
after padding. This was fixed by the below commit

  217e467e89d15f3c22e11fe144458afbf718c8a8
  BUG/MINOR: quic: fix malformed probing packet building

Above logic was altered to fix the PING case : padding was set to false
explicitely in qc_prep_pkts(). Padding was then added in a specific
block dedicated to the PING case in qc_do_build_pkt() itself for INITIAL
packets.

However, the fix is incorrect if the last QEL used to built a packet is
not the initial one and probing is used with PING frame only. In this
case, specific block in qc_do_build_pkt() does not add padding. This
causes a BUG_ON() crash in qc_txb_store() which catches these packets as
irregularly formed.

To fix this while also properly handling PING emission, revert to the
original padding logic : qc_prep_pkts() is responsible to activate
INITIAL padding. To not interfere with PING emission, qc_do_build_pkt()
body is adjusted so that PING block is moved up in the function and
detached from the padding condition.

The main benefit from this patch is that INITIAL padding decision in
qc_prep_pkts() is clearer now.

Note that padding can also be activated by qc_do_build_pkt(), as packets
should be big enough for header protection decipher. However, this case
is different from INITIAL padding, so it is not covered by this patch.

This should be backported up to 2.6.

(cherry picked from commit 8bc339a6ad4702f2c39b2a78aaaff665d85c762b)
[cf: context adjustment]
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 613457413b4edb5dc21c9a8b8b741556b019f129)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit d6365e5197bea8ee8dee8beaf0bcb10de687ee0a)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: quic: do not emit probe data if CONNECTION_CLOSE requested
Amaury Denoyelle [Tue, 12 Aug 2025 09:30:03 +0000 (11:30 +0200)]
BUG/MINOR: quic: do not emit probe data if CONNECTION_CLOSE requested

If connection closing is activated, qc_prep_pkts() can only built a
datagram with a single packet. This is because we consider that only a
single CONNECTION_CLOSE frame is relevant at this stage.

This is handled both by qc_prep_pkts() which ensure that only a single
packet datagram is built and also qc_do_build_pkt() which prevents the
invokation of qc_build_frms() if <cc> is set.

However, there is an incoherency for probing. First, qc_prep_pkts()
deactivates it if connection closing is requested. But qc_do_build_pkt()
may still emit probing frame as it does not check its <probe> argument
but rather <pto_probe> QEL field directly. This can results in a packet
mixing a PING and a CONNECTION close frames, which is useless.

Fix this by adjusting qc_do_build_pkt() : closing argument is also
checked on PING probing emission. Note that there is still shaky code
here as qc_do_build_pkt() should rely only on <probe> argument to ensure
this.

This should be backported up to 2.6.

(cherry picked from commit 0376e66112f17d79cfd1824ae75d7288eb383059)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 6d0cdabc754d94c1e5036ca4ce4b01085afcdfa1)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 0937c7e85bc541a15ec0d51e2397a9799bdbcf33)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: mux-h1: fix wrong lock label
Amaury Denoyelle [Fri, 8 Aug 2025 13:12:59 +0000 (15:12 +0200)]
BUG/MINOR: mux-h1: fix wrong lock label

Wrong lock label is used when manipulating idle lock on h1_timeout_task.
Fix this by replacing OTHER_LOCK by IDLE_CONNS_LOCK.

This only concerns thread debugging statistics.

This must be backported up to 2.4.

(cherry picked from commit 8ac54cafcda749a5b50532b3a10d39a5a37ce9b3)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 8969387e94cb5ac0562b1bfe8d01cc0131b9652e)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 50a5aa77a1811fde4787fed552126f329eb1e744)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MEDIUM: http-client: Test HTX_FL_EOM flag before commiting the HTX buffer
Christopher Faulet [Tue, 8 Jul 2025 06:24:45 +0000 (08:24 +0200)]
BUG/MEDIUM: http-client: Test HTX_FL_EOM flag before commiting the HTX buffer

when htx_to_buf() function is called, if the HTX message is empty, the
buffer is reset. So HTX flags must not be tested after because the info may
be lost.

So now, we take care to test HTX_FL_EOM flag before calling htx_to_buf().

This patch must be backported as far as 2.8.

(cherry picked from commit 4bdb2e5a26587120101234c8f73cbc40d1777656)
[wla: API does not emit HTX in response for 3.2, some adjutements were
made to better match the 3.3 behavior]
Signed-off-by: William Lallemand <wlallemand@haproxy.com>
(cherry picked from commit d01fa873acdd5ac40819d311923a28159e01040b)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 03d4267efa7d815efd97366e9db5f9770f804370)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoDOC: config: recommend single quoting passwords
Lukas Tribus [Tue, 12 Aug 2025 16:28:55 +0000 (16:28 +0000)]
DOC: config: recommend single quoting passwords

Suggests single quoting passwords and update examples to avoid unexpected
behaviors due to special characters.

Should be backported to stable versions.

Link: https://discourse.haproxy.org/t/enhance-documentation-for-insecure-passwords-and-invald-characters/11959
(cherry picked from commit 9432e7d6887ade0db69947f343c5b5535a33e303)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 456d7dc170fd4a3e6541cc5816810f398efe2d07)
[cf: context adjustment]
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 99dc78982db90181de548a9051e21069628ec6c5)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoDOC: management: fix typo in commit f4f93c56
Lukas Tribus [Tue, 12 Aug 2025 16:28:22 +0000 (16:28 +0000)]
DOC: management: fix typo in commit f4f93c56

Fixes a small typo in commit f4f93c56 ("DOC: management: clarify usage
of -V with -c").

Must be backported as far as 2.8 along commit f4f93c56.

(cherry picked from commit faacc6c0842d2409abaf655d1967330af1790048)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit e4bc87caaa08b3c8fbe46bd8c988aa486b571425)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 33bb9f423f8c14aaf3753724a2d0a492fc8b7c39)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: init: Initialize random seed earlier in the init process
Remi Tricot-Le Breton [Mon, 11 Aug 2025 13:55:35 +0000 (15:55 +0200)]
BUG/MINOR: init: Initialize random seed earlier in the init process

The random seed used in ha_random functions needs to be first
initialized by calling ha_random_boot. This function was called rather
late in the init process, after the init functions (INITCALLS) are
called and after the configuration parsing for instance which means that
any ha_random call in an init function would return 0. This was the case
in 'vars_init' and 'cache_init' which tried to build seeds for specific
hash calculations but ended up not being seeded.

This patch can be backported on all stable branches.

(cherry picked from commit 15ee49e8222be2b34663fac838aa74e62f6c82ea)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit f7fbb55f0dcbbb44f6d20950bc1c0835699c85b6)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 0429f236a3adae23ca173cf11b74ccfd8099168f)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MEDIUM: ssl: fix build with AWS-LC
Olivier Houchard [Fri, 8 Aug 2025 18:17:55 +0000 (20:17 +0200)]
BUG/MEDIUM: ssl: fix build with AWS-LC

AWS-LC doesn't provide SSL_in_before(), and doesn't provide an easy way
to know if we already started the handshake or not. So instead, just add
a new field in ssl_sock_ctx, "can_write_early_data", that will be
initialized to 1, and will be set to 0 as soon as we start the
handshake.

This should be backported up to 2.8 with
13aa5616c9f99dbca0711fd18f716bd6f48eb2ae.

(cherry picked from commit b6702d53427a22725c125425552074c622c2f25d)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 5ff41e99b8f68eb674231d99e546783b27c7e562)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 3fff6803385f325c6a87d00405978ab7a2b280e6)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MEDIUM: ssl: Fix 0rtt to the server
Olivier Houchard [Fri, 8 Aug 2025 16:26:29 +0000 (18:26 +0200)]
BUG/MEDIUM: ssl: Fix 0rtt to the server

In order to send early data, we have to make sure no handshake has been
initiated at all. To do that, we remove the CO_FL_SSL_WAIT_HS flag, so
that we won't attempt to start a handshake. However, by removing those
flags, we allow ssl_sock_to_buf() to call SSL_read(), as it's no longer
aware that no handshake has been done, and SSL_read() will begin the
handshake, thus preventing us from sending early data.
The fix is to just call SSL_in_before() to check if no handshake has
been done yet, in addition to checking CO_FL_SSL_WAIT_HS (both are
needed, as CO_FL_SSL_WAIT_HS may come back in case of renegociation).
In ssl_sock_from_buf(), fix the check to see if we may attempt to send
early data. Use SSL_in_before() instead of SSL_is_init_finished(), as
SSL_is_init_finished() will return 1 if the handshake has been started,
but not terminated, and if the handshake has been started, we can no
longer send early data.
This fixes errors when attempting to send early data (as well as
actually sending early data).

This should be backported up to 2.8.

(cherry picked from commit 13aa5616c9f99dbca0711fd18f716bd6f48eb2ae)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 1a54596e40d8599e3cc4b4e98ac69a90bf15f071)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 0f60a540425b123e2ae93b9e90bef25ba6680690)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: stick-table: cap sticky counter idx with tune.nb_stk_ctr instead of MAX_SE...
Valentine Krasnobaeva [Thu, 7 Aug 2025 09:54:58 +0000 (11:54 +0200)]
BUG/MINOR: stick-table: cap sticky counter idx with tune.nb_stk_ctr instead of MAX_SESS_STKCTR

Cap sticky counter index with tune.nb_stk_ctr instead of MAX_SESS_STKCTR for
sc-add-gpc. Same logic is already implemented for sc-inc-gpc and sc-set-gpt
keywords. So, it seems missed for sc-add-gpc.

This fixes the issue #3061 reported at GitHub. Thanks to @ma311 for
reporting their analysis of the issue.
This should be backported in all versions until 2.8, included 2.8.

(cherry picked from commit 21d5f43aa6e9513d11dff2d80a2a332d92c0a857)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 4b71a4c528876a37fee996ac1326b03622c90bc7)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 6ff65b14cc06550b10560d3bf6fc8d7eee9a4868)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUILD: compat: always set _POSIX_VERSION to ease comparisons
Willy Tarreau [Tue, 5 Aug 2025 13:59:11 +0000 (15:59 +0200)]
BUILD: compat: always set _POSIX_VERSION to ease comparisons

Sometimes we need to compare it to known versions, let's make sure it's
always defined. We set it to zero if undefined so that it cannot match
any comparison.

(cherry picked from commit e921fe894f6b992414e595be9450a9092f4df48e)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit a04c2d7ac5e4071da95230b128911d5b78bc996a)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 319077ed41e46975cbcb3f9e2d3b8af5623d42ce)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUILD: compat: provide relaxed versions of the MIN/MAX macros
Willy Tarreau [Wed, 6 Aug 2025 17:05:29 +0000 (19:05 +0200)]
BUILD: compat: provide relaxed versions of the MIN/MAX macros

In 3.0 the MIN/MAX macros were converted to compound expressions with
commit 0999e3d959 ("CLEANUP: compat: make the MIN/MAX macros more
reliable"). However with older compilers these are not supported out
of code blocks (e.g. to initialize variables or struct members). This
is the case on Solaris 10 with gcc-5.5 when QUIC doesn't compile
anymore with the future pool registration:

  In file included from include/haproxy/quic_tx.h:26:0,
                   from src/quic_tx.c:15:
  include/haproxy/compat.h:106:19: error: braced-group within expression allowed only inside a function
   #define MAX(a, b) ({    \
                     ^
  include/haproxy/pool.h:41:11: note: in definition of macro '__REGISTER_POOL'
     .size = _size,           \
             ^
  ...
  include/haproxy/quic_tx-t.h:6:29: note: in expansion of macro 'MAX'
   #define QUIC_MAX_CC_BUFSIZE MAX(QUIC_INITIAL_IPV6_MTU, QUIC_INITIAL_IPV4_MTU)

Let's provide the old relaxed versions as _MIN/_MAX for use with constants
like such cases where it's certain that there is no risk. A previous attempt
using __builtin_constant_p() to switch between the variants did not work,
and it's really not worth the hassle of going this far.

(cherry picked from commit cf8871ae40ae85f86b0d396b6af1eb657134ffc1)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit a245298b3c05826834d0c5925a1eb74fe22d4392)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 2ae6edb59f8acf7fe0342c08e1d939c691004cf2)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoDOC: list missing global QUIC settings
Amaury Denoyelle [Mon, 28 Jul 2025 09:10:12 +0000 (11:10 +0200)]
DOC: list missing global QUIC settings

Complete list of global keywords with missing QUIC entries.

This could be backported to stable versions. This requires to take into
account the version of introduction for each keyword.
* limited-quic, introduced in 2.8
* no-quic, introduced in 2.8
* tune.quic.cc.cubic.min-losses, introduced in 3.1

(cherry picked from commit 7fa812a1ac2721d9290900b3467fd80110f15cc7)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 0b4d823b3e6056a7a8465c744b7ad69537245871)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 282d1f28261ff9477ca5952fe1ef259453886b87)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MEDIUM: threads: Disable the workaround to load libgcc_s on macOS
Olivier Houchard [Thu, 17 Jul 2025 17:27:39 +0000 (19:27 +0200)]
BUG/MEDIUM: threads: Disable the workaround to load libgcc_s on macOS

Don't use the workaround to load libgcc_s on macOS. It is not needed
there, and it causes issues, as recent macOS dislike processes that fork
after threads where created (and the workaround creates a temporary
thread). This fixes crashes on macOS at least when using master-worker,
and using the system resolver.

This should fix Github issue #3035

This should be backported up to 2.8.

(cherry picked from commit f8e9545f700a4e3799bbac4cd1c94989b9c1fb61)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 0d87b8343f8780c1c677dd282dc7648cf038a00a)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit ba9ee8147702b5cc5c400b7521afc2f13659eb2c)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: halog: exit with error when some output filters are set simultaneosly
Valentine Krasnobaeva [Wed, 16 Jul 2025 12:35:28 +0000 (14:35 +0200)]
BUG/MINOR: halog: exit with error when some output filters are set simultaneosly

Exit with an error if multiple output filters (-ic, -srv, -st, -tc, -u*, etc.)
are used at the same time.

halog is designed to process and display output for only one filter at a time.
Using multiple filters simultaneously can cause a crash because the program is
not designed to manage multiple, separate result sets (e.g., one for
IP counts, another for URLs).

Supporting simultaneous filters would require a redesign to collect entries for
each filter in separate ebtree. This would negatively impact performance and is
not requested for the moment. This patch prevents the crash by checking filter
combinations just after the command line parsing.

This issue was reported in GitHUB #3031.
This should be backported in all stable versions.

(cherry picked from commit 254e4d59f75784c237e0c51596c6e0ca8730e717)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit dd276c752d5edfe26778ded9006dea40d5e33d23)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 8fc62dbff10a674cdd673d319b61a6aa0ab01b4a)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: applet: Don't trigger BUG_ON if the tid is not on appctx init
Christopher Faulet [Wed, 16 Jul 2025 09:29:49 +0000 (11:29 +0200)]
BUG/MINOR: applet: Don't trigger BUG_ON if the tid is not on appctx init

When an appctx is initialized, there is a BUG_ON() to be sure the appctx is
really initialized on the right thread to avoid bugs on the thread
affinity. However, it is possible to not choose the thread when the appctx
is created and let it starts on any thread. In that case, the thread
affinity is set when the appctx is initialized. So, we must take cate to not
trigger the BUG_ON() in that case.

For now, we never hit the bug because the thread affinity is always set
during the appctx creation.

This patch must be backport as far as 2.8.

(cherry picked from commit 4f7c26cbb33fac44b255c714610191ffad2ec653)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit be0148c5ccbe5711c201020b1eba2af297acacf6)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 0b854dfaf028a8836e3e460738370ef7210f1854)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: quic: Wrong source address use on FreeBSD
Frederic Lecaille [Fri, 11 Jul 2025 07:02:22 +0000 (09:02 +0200)]
BUG/MINOR: quic: Wrong source address use on FreeBSD

The bug is a listener only one, and only occured on FreeBSD.

The FreeBSD issue has been reported here:
https://forums.freebsd.org/threads/quic-http-3-with-haproxy.98443/
where QUIC traces could reveal that sendmsg() calls lead to EINVAL
syscall errnos.

Such a similar issue could be reproduced from a FreeBSD 14-2 VM
with reg-tests/quic/retry.vtc as reg test.

As noted by Olivier, this issue could be fixed within the VM binding
the listener socket to INADDR_ANY.

That said, the symptoms are not exactly the same as the one reporte by the user.
What could be observed from such a VM is that if the first recvmsg() call
returns the datagram destination address, and if the listener
listening address is bound to a specific address, the calls to
sendmsg() fail because of the IP_SENDSRCADDR ip option value
set by cmsg_set_saddr(). According to the ip(4) freebsd manual
such an IP options must be used if the listening socket is
bound to a specific address. It is to be noted that into a VM
the first call to recvmsg() of the first connection does not return the datagram
destination address. This leads the first quic_conn to be initialized without
->local_addr value. This is this value which is used by IP_SENDSRCADDR
ip option. In this case, the sendmsg() calls (without IP_SENDSRCADDR)
never fail. The issue appears at the second condition.

This patch replaces the conditions to use IP_SENDSRCADDR to a call to
qc_may_use_saddr(). This latter also checks that the listener listening
address is not INADDR_ANY to allow the use of the source address.
It is generalized to all the OSes. Indeed, there is no reason to set the source
address when the listener is bound to a specific address.

Must be backported as far as 2.8.

(cherry picked from commit 1c33756f7803247c81354f55678322b636279089)
[ad: replace <target> by <li> qc member]
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 6c237bb64b9d19cc927ed72aee360d8e22138969)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 34f540f57240b3ebab0c225c9c2820c927ed8d67)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MEDIUM: http-client: Notify applet has more data to deliver until the EOM
Christopher Faulet [Wed, 9 Jul 2025 13:20:41 +0000 (15:20 +0200)]
BUG/MEDIUM: http-client: Notify applet has more data to deliver until the EOM

When we leave the I/O handler with an unfinished request, we must report the
applet has more data to deliver. Otherwise, when the channel request buffer
is emptied, the http-client applet is not always woken up to forward the
remaining request data.

This issue was probably revealed by commit "BUG/MEDIUM: http-client: Don't
wake http-client applet if nothing was xferred". It is only an issue with
large POSTs, when the payload is streamed.

This patch must be backported as far as 2.6 with the commit above. But on
older versions, the applet API may differ. So be careful.

(cherry picked from commit 0b97bf36fad6fbced8077ac416a1399c05806c7d)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit dd3ba78fc13a99e79052496d1851cff65c24f73c)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 91f19003114ad4afcb189233d0784c6f7ce923f4)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MEDIUM: http-client: Drain the request if an early response is received
Christopher Faulet [Tue, 8 Jul 2025 06:45:10 +0000 (08:45 +0200)]
BUG/MEDIUM: http-client: Drain the request if an early response is received

When a large request is sent, it is possible to have a response before the
end of the request. It is valid from HTTP perspective but it is an issue
with the current design of the http-client. Indded, the request and the
response are handled sequentially. So the response will be blocked, waiting
for the end of the request. Most of time, it is not an issue, except when
the request transfer is blocked. In that case, the applet is blocked.

With the current API, it is not possible to handle early response and
continue the request transfer. So, this case cannot be handle. In that case,
it seems reasonnable to drain the request if a response is received. This
way, the request transfer, from the caller point of view, is never blocked
and the response can be properly processed.

To do so, the action flag HTTPCLIENT_FA_DRAIN_REQ is added to the
http-client. When it is set, the request payload is just dropped. In that
case, we take care to not report the end of input to properly report the
request was truncated, especially in logs.

It is only an issue with large POSTs, when the payload is streamed.

This patch must be backported as far as 2.6.

(cherry picked from commit 25b0625d5c27a209c38dcac6a81c58495e5360af)
[ad: context adjustement due to missing HTTPCLIENT_O_RES_HTX in 3.2]
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit eadb777452f8470ddaeb0ffdb59c130ce1621823)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit fff555a50b229a32341931e7928d19fc7b023789)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: http-client: Reject any 101-switching-protocols response
Christopher Faulet [Tue, 8 Jul 2025 06:57:16 +0000 (08:57 +0200)]
BUG/MINOR: http-client: Reject any 101-switching-protocols response

Protocol updages are not supported by the http-client. So report an error is
a 101-switching-protocols response is received. Of course, it is unexpected
because the API is not designed to support upgrades. But it is better to
properly handle this case.

This patch could be backported as far as 2.6. It depends on the commit
"BUG/MINOR: http-client: Ignore 1XX interim responses in non-HTX mode".

(cherry picked from commit 8ba754108d70d25d796e3dc166155503aab180b2)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 0bfaef56d630a355d85fcdf2b733e479fee8595b)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 31ff75c23d25eb6b10dbe9f1af09e63083428df2)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: http-client: Ignore 1XX interim responses in non-HTX mode
Christopher Faulet [Tue, 8 Jul 2025 06:38:31 +0000 (08:38 +0200)]
BUG/MINOR: http-client: Ignore 1XX interim responses in non-HTX mode

When the response is re-formatted in raw message, the 1XX interim responses
must be skipped. Otherwise, information of the first interim response will
be saved (status line and headers) and those from the final response will be
dropped.

Note that for now, in HTX-mode, the interim messages are removed.

This patch must be backported as far as 2.6.

(cherry picked from commit 9d10be33aebb08058c37d7dcd15874e42be74a29)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 8abebc8d061c29dcdf511efba2321cf2a6df00d6)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 39b319f6c9d615c546631ea918daff11684c7b1b)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MEDIUM: http-client: Ask for more room when request data cannot be xferred
Christopher Faulet [Tue, 8 Jul 2025 06:17:49 +0000 (08:17 +0200)]
BUG/MEDIUM: http-client: Ask for more room when request data cannot be xferred

When the request payload cannot be xferred to the channel because its buffer
is full, we must request for more room by calling sc_need_room(). It is
important to be sure the httpclient applet will not be woken up in loop to
push more data while it is not possible.

It is only an issue with large POSTs, when the payload is streamed.

This patch must be backported as far as 2.6. Note that on 2.6,
sc_need_room() only takes one argument.

(cherry picked from commit e4a0d40c62594b4504fd7443158731fef54e040a)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 5377ea587fba88b56e5249008be153cb529f066b)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit e1aa83ce71f826ed446b763a16e19114f4e15e83)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MEDIUM: http-client: Properly inc input data when HTX blocks are xferred
Christopher Faulet [Tue, 8 Jul 2025 06:04:01 +0000 (08:04 +0200)]
BUG/MEDIUM: http-client: Properly inc input data when HTX blocks are xferred

When HTX blocks from the requests are transferred into the channel buffer,
the return value of htx_xfer_blks() function must not be used to increment
the channel input value because meta data are counted here while they are
not part of input data. Because of this bug, it is possible to forward more
data than these present in the channel buffer.

Instead, we look at the input data before and after the transfer and the
difference is added.

It is only an issue with large POSTs, when the payload is streamed.

This patch must be backported as far as 2.6.

(cherry picked from commit d9ca8f6b71cd17bae0718f0b1e9da919fc00264d)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 208ef1d7aebc11133e8c64966be475a521da5409)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 90167928a38f05680852fd0943b86ef66496ee18)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MEDIUM: http-client: Don't wake http-client applet if nothing was xferred
Christopher Faulet [Tue, 8 Jul 2025 05:46:26 +0000 (07:46 +0200)]
BUG/MEDIUM: http-client: Don't wake http-client applet if nothing was xferred

When data are transferred to or from the htt-pclient, the applet is
systematically woken up, even when no data are transferred. This could lead
to needlessly wakeups. When called from a lua script, if data are blocked
for a while, this leads to a wakeup ping-pong loop where the http-client
applet is woken up by the lua script which wakes back the script.

To fix the issue, in httpclient_req_xfer() and httpclient_res_xfer()
functions, we now take care to not wake the http-client applet up when no
data are transferred.

This patch must be backported as far as 2.6.

(cherry picked from commit fffdac42df4848420028f89b14c2a90c12dbf9ab)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit b35b0aaf82d625c8f78f734fb5b4c0deebd1697a)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 9dab53c6b7ba9928b61d68e5243930b1f72431f3)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

2 weeks agoBUG/MINOR: listener: really assign distinct IDs to shards
Willy Tarreau [Wed, 9 Jul 2025 13:52:33 +0000 (15:52 +0200)]
BUG/MINOR: listener: really assign distinct IDs to shards

A fix was made in 3.0 for the case where sharded listeners were using
a same ID with commit 0db8b6034d ("BUG/MINOR: listener: always assign
distinct IDs to shards"). However, the fix is incorrect. By checking the
ID of temporary node instead of the kept one in bind_complete_thread_setup()
it ends up never inserting the used nodes at this point, thus not reserving
them. The side effect is that assigning too close IDs to subsequent
listeners results in the same ID still being assigned twice since not
reserved. Example:

   global
       nbthread 20

   frontend foo
       bind :8000 shards by-thread id 10
       bind :8010 shards by-thread id 20

The first one will start a series from 10 to 29 and the second one a
series from 20 to 39. But 20 not being inserted when creating the shards,
it will remain available for the post-parsing phase that assigns all
unassigned IDs by filling holes, and two listeners will have ID 20.

By checking the correct node, the problem disappears. The patch above
was marked for backporting to 2.6, so this fix should be backported that
far as well.

(cherry picked from commit dd49f1ee6230eaf608f3afa880ef0a6d2b84456e)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit c12e3b66be1eec8e5ccf6ca25871df77864c2b79)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 68c664f407bbc6d602f832344953e3c132da7217)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>