]> git.ipfire.org Git - thirdparty/haproxy.git/log
thirdparty/haproxy.git
2 weeks agoBUILD: openssl-compat: fix build failure with OPENSSL=0 and KTLS=1
Willy Tarreau [Fri, 24 Oct 2025 08:42:06 +0000 (10:42 +0200)] 
BUILD: openssl-compat: fix build failure with OPENSSL=0 and KTLS=1

The USE_KTLS test is currently being done outside of the USE_OPENSSL
guard so disabling USE_OPENSSL still results in build failures on
libcs built with support for kernels before 4.17, because we enable
KTLS by default on linux. Let's move the KTLS block inside the
USE_OPENSSL guard instead.

No backport is needed since KTLS is only in 3.3.

2 weeks agoBUG/MINOR: stick-tables: properly index string-type keys
Willy Tarreau [Fri, 24 Oct 2025 05:46:53 +0000 (07:46 +0200)] 
BUG/MINOR: stick-tables: properly index string-type keys

This is one of the rare pleasant surprises of fixing an almost 16-years
old bug that remained unnoticed since the feature was implemented. In
1.4-dev7, commit 3bd697e071 ("[MEDIUM] Add stick table (persistence)
management functions and types") introduced stick-tables with multiple
key types, including strings, IP addresses and integers. Entries are
coded in binary and their binary representation is indexed. A special
case was made for strings in order to index them as zero-terminated
strings. However, there's one subtlety. While strings indeed have a
zero appended, they're still indexed using ebmb_insert(), which means
that all the bytes till the configured size are indexed as well. And
while these bytes generally come from a temporary storage that often
contains zeroes, or that is longer than the configured string length
and will result in truncation, it's not always the case and certain
traffic patterns with certain configurations manage to occasionally
present unpadded strings resulting in apparent duplicate keys appearing
in the dump, as shown in GH issue #3161. It seems to be essentially
reproducible at boot, and not to be particularly affected by mixed
patterns. These keys are in fact not exact duplicates in memory, but
everywhere they're used (including during synchronization), they are
equal.

What's interesting is that when this happens, one key can be presented
to a peer with its own data and will be indexed as the only one, possibly
replacing contents from the previous key, which might replace them again
later once updated in turn. This is visible in the dump of the issue
above, where key "localhost:8001" was split into two entries, one with a
request count of one and the other with a request count of 499999, and
indeed, all peers see only that last value, which overwrote the first
one.

This fix must be backported to all stable branches. Special kudos to
Mark Wort for undelining that one.

2 weeks agoBUG/MAJOR: stats-file: ensure shm_stats_file_object struct mapping consistency (2nd...
Aurelien DARRAGON [Fri, 24 Oct 2025 07:11:21 +0000 (09:11 +0200)] 
BUG/MAJOR: stats-file: ensure shm_stats_file_object struct mapping consistency (2nd attempt)

This is a second attempt at fixing issues on 32bits systems which would
trigger the following BUG_ON() statement:

 FATAL: bug condition "sizeof(struct shm_stats_file_object) != 544" matched at src/stats-file.c:825 shm_stats_file_object struct size changed, is is part of the exported API: ensure all precautions were taken (ie: shm_stats_file version change) before adjusting this

This is a drop-in replacement for d30b88a6c + 4693ee0ff, as suggested by
Willy.

Indeed, on supported platforms unsigned int can be assumed to be 4 bytes
long, and long can be assumed to be 8 bytes long. As such, the previous
attempt was overkill and added unecessary maintenance complexity which
could result in bugs if not used properly. Moreover, it would only
partially solve the issue, since on little endian vs big endian
architectures, the provisioned memory areas (originating from the same
shm stats file) could be read differently by the host.

Instead we fix the aligments issues, and this alone helps to ensure
struct memory consistency on 64 vs 32bits platforms. It was tested
on both i386 and i586.

last_change and last_sess counters are now stored as unsigned int, as
it helped to fix the alignment issues and they were found to be used
as 32bits integers anyway.

Thanks to Willy for problem analysis and the patch proposal.

No backport needed.

2 weeks agoRevert "MINOR: compiler: add FIXED_SIZE(size, type, name) macro"
Aurelien DARRAGON [Fri, 24 Oct 2025 07:10:08 +0000 (09:10 +0200)] 
Revert "MINOR: compiler: add FIXED_SIZE(size, type, name) macro"

This reverts commit 466a603b59ed77e9787398ecf1baf77c46ae57b1.
Due to the last 2 commits, this macro is now unused, and will probably
never be used, so let's get rid of that for now.

2 weeks agoRevert "MEDIUM: freq-ctr: use explicit-size types for freq-ctr struct"
Aurelien DARRAGON [Fri, 24 Oct 2025 07:09:59 +0000 (09:09 +0200)] 
Revert "MEDIUM: freq-ctr: use explicit-size types for freq-ctr struct"

This reverts commit 4693ee0ff7a5fa4a12ff69b1a33adca142e781ac.
As discussed in GH #3168, this works but it is not the proper way to fix
the issue. See following commits.

2 weeks agoRevert "BUG/MAJOR: stats-file: ensure shm_stats_file_object struct mapping consistency"
Aurelien DARRAGON [Fri, 24 Oct 2025 07:08:56 +0000 (09:08 +0200)] 
Revert "BUG/MAJOR: stats-file: ensure shm_stats_file_object struct mapping consistency"

This reverts commit d30b88a6cc47d662e92b524ad5818be312401d0e.
As discussed in GH #3168, this works but it is not the proper way to fix
the issue. See following commits.

2 weeks agoBUG/MEDIUM: applet: Improve again spinning loops detection with the new API
Christopher Faulet [Thu, 16 Oct 2025 09:22:22 +0000 (11:22 +0200)] 
BUG/MEDIUM: applet: Improve again spinning loops detection with the new API

A first attempt to fix this issue was already pushed (54b7539d6 "BUG/MEDIUM:
apppet: Improve spinning loop detection with the new API"). But it not was
fully accurrate. Indeed, we must check if something was received or sent by
the applet before incrementing the call rate. But we must also take care the
applet is allowed to receive or send data. That is what is performed in this
patch.

This patch must be backported as far as 3.0 with the patch above.

2 weeks agoBUG/MINOR: quic: rename and duplicate stream settings
Amaury Denoyelle [Wed, 10 Sep 2025 09:21:26 +0000 (11:21 +0200)] 
BUG/MINOR: quic: rename and duplicate stream settings

Several settings can be set to control stream multiplexing and
associated receive window. Previously, all of these settings were
configured using prefix "tune.quic.frontend.", despite being applied
blindly on both sides.

Fix this by duplicating these settings specific to frontend and backend
side. Options are also renamed to use the standardize prefix
"tune.quic.[be|fe].stream." notation.

Also, each option is individually renamed to better reflect its purpose
and hide technical details relative to QUIC transport parameter naming :
* max-data-size -> stream.rxbuf
* max-streams-bidi -> stream.max-concurrent
* stream-data-ratio -> stream.data-ratio

No need to backport.

2 weeks agoBUG/MINOR: quic: split option for congestion max window size
Amaury Denoyelle [Wed, 10 Sep 2025 08:48:12 +0000 (10:48 +0200)] 
BUG/MINOR: quic: split option for congestion max window size

2 weeks agoBUG/MINOR: quic: split max-idle-timeout option for FE/BE usage
Amaury Denoyelle [Wed, 10 Sep 2025 07:53:48 +0000 (09:53 +0200)] 
BUG/MINOR: quic: split max-idle-timeout option for FE/BE usage

Streamline max-idle-timeout option. Rename it to use the newer cohesive
naming scheme 'tune.quic.fe|be.'.

Two different fields were already defined in global struct. These fields
are moved into quic_tune along with other QUIC settings. However, no
parser was defined for backend option, this commit fixes this.

No need to backport this.

2 weeks agoMINOR: quic: rename frontend sock-per-conn setting
Amaury Denoyelle [Tue, 5 Aug 2025 12:02:44 +0000 (14:02 +0200)] 
MINOR: quic: rename frontend sock-per-conn setting

On frontend side, a quic_conn can have a dedicated FD or use the
listener one. These different modes can be activated via a global QUIC
tune setting.

This patch adjusts the option. First, it is renamed to the more
meaningful name 'tune.quic.fe.sock-per-conn'. Also, arguments are now
either 'default-on' or 'force-off'. The objective is to better highlight
reliationship with 'quic-socket' bind option.

The older option is deprecated and will be removed in 3.5.

2 weeks agoMINOR: quic: rename retry-threshold setting
Amaury Denoyelle [Tue, 5 Aug 2025 11:35:33 +0000 (13:35 +0200)] 
MINOR: quic: rename retry-threshold setting

A QUIC global tune setting is defined to be able to force Retry emission
prior to handshake. By definition, this ability is only supported by
QUIC servers, hence it is a frontend option only.

Rename the option to use "fe" prefix. The old option name is deprecated
and will be removed in 3.5

2 weeks agoMINOR: quic: rename max Tx mem setting
Amaury Denoyelle [Tue, 5 Aug 2025 09:12:17 +0000 (11:12 +0200)] 
MINOR: quic: rename max Tx mem setting

QUIC global memory can be limited across the entire process via a global
tune setting. Previously, this setting used to misleading "frontend"
prefix. As this is applied as a sum between all QUIC connections, both
from frontend and backend sides, remove the prefix. The new option name
is "tune.quic.mem.tx-max".

The older option name is deprecated and will be removed in 3.5.

2 weeks agoMINOR: quic: split Tx options for FE/BE usage
Amaury Denoyelle [Thu, 31 Jul 2025 16:20:30 +0000 (18:20 +0200)] 
MINOR: quic: split Tx options for FE/BE usage

This patch is similar to the previous one, except that it is focused on
Tx QUIC settings. It is now possible to toggle GSO and pacing on
frontend and backend sides independently.

As with previous patch, option are renamed to use "fe/be" unified
prefixes. This is part of the current serie of commits which unify QUI
settings. Older options are deprecated and will be removed on 3.5
release.

2 weeks agoMINOR: quic: split congestion controler options for FE/BE usage
Amaury Denoyelle [Thu, 31 Jul 2025 15:15:51 +0000 (17:15 +0200)] 
MINOR: quic: split congestion controler options for FE/BE usage

Various settings can be configured related to QUIC congestion controler.
This patch duplicates them to be able to set independent values on
frontend and backend sides.

As with previous patch, option are renamed to use "fe/be" unified
prefixes. This is part of the current serie of commits which unify QUIC
settings. Older options are deprecated and will be removed on 3.5
release.

2 weeks agoMINOR: quic: duplicate glitches FE option on BE side
Amaury Denoyelle [Thu, 31 Jul 2025 14:48:57 +0000 (16:48 +0200)] 
MINOR: quic: duplicate glitches FE option on BE side

Previously, QUIC glitches support was only implemented for frontend
side. Extend this so that the option can be specified separately both on
frontend and backend sides. Function _qcc_report_glitch() now retrieves
the relevant max value based on connection side.

In addition to this, option has been renamed to use "fe/be" prefixes.
This is part of the current serie of commits which unify QUIC settings.
Older options are deprecated and will be removed on 3.5 release.

2 weeks agoMINOR: quic: rename "no-quic" to "tune.quic.listen"
Amaury Denoyelle [Wed, 30 Jul 2025 15:34:52 +0000 (17:34 +0200)] 
MINOR: quic: rename "no-quic" to "tune.quic.listen"

Rename the option to quickly enable/disable every QUIC listeners. It now
takes an argument on/off. The documentation is extended to reflect the
fact that QUIC backend are not impacted by this option.

The older keyword is simply removed. Deprecation is considered
unnecessary as this setting is only useful during debugging.

2 weeks agoMINOR: quic: prepare support for options on FE/BE side
Amaury Denoyelle [Thu, 31 Jul 2025 15:14:40 +0000 (17:14 +0200)] 
MINOR: quic: prepare support for options on FE/BE side

A major reorganization of QUIC settings is going to be performed. One of
its objective is to clearly define options which can be separately
configured on frontend and backend proxy sides.

To implement this, quic_tune structure is extended to support fe and be
options. A set of macros/functions is also defined : it allows to
retrieve an option defined on both sides with unified code, based on
proxy side of a quic_conn/connection instance.

2 weeks agoMINOR: quic: remove unused conn-tx-buffers limit keyword
Amaury Denoyelle [Tue, 5 Aug 2025 08:40:09 +0000 (10:40 +0200)] 
MINOR: quic: remove unused conn-tx-buffers limit keyword

Remove parsing code for tune.quic.frontend.conn-tx-buffers.limit. This
option was deprecated for some time and in fact was noop and not
mentionned anymore in the documentation.

2 weeks agoBUG/MEDIUM: mt_lists: Avoid el->prev = el->next = el
Olivier Houchard [Thu, 23 Oct 2025 12:41:23 +0000 (14:41 +0200)] 
BUG/MEDIUM: mt_lists: Avoid el->prev = el->next = el

Avoid setting both el->prev and el->next on the same line.
The goal is to set both el->prev and el->next to el, but a naive
compiler, such as when we're using -O0, will set el->next first, then
will set el->prev to the value of el->next, but if we're unlucky,
el->next will have been set to something else by another thread.
So explicitely set both to what we want.

This should be backported up to 2.8.

2 weeks agoMINOR: acme: display the complete challenge_ready command in the logs
William Lallemand [Thu, 23 Oct 2025 09:01:13 +0000 (11:01 +0200)] 
MINOR: acme: display the complete challenge_ready command in the logs

When using a wildcard DNS domain in the ACME configuration, for example
*.example.com, one might think that it needs to use the challenge_ready
command with this domain. But that's not the case, the challenge_ready
command takes the domain asked by the ACME server, which is stripped of
the wildcard.

In order to be clearer, the log message shows exactly the command the
user should sent, which is clearer.

2 weeks agoMINOR: acme: add the dns-01-record field to the sink
William Lallemand [Wed, 22 Oct 2025 16:31:51 +0000 (18:31 +0200)] 
MINOR: acme: add the dns-01-record field to the sink

The dns-01-record field in the dpapi sink, output the authentication
token which is needed in the TXT record in order to validate the DNS-01
challenge.

2 weeks agoBUG/MEDIUM: stick-tables: Don't loop if there's nothing left
Olivier Houchard [Thu, 23 Oct 2025 08:48:38 +0000 (10:48 +0200)] 
BUG/MEDIUM: stick-tables: Don't loop if there's nothing left

Before waking up the expiration task again at the end of it, make sure
the next date is set. If there's nothing left to do, then task_exp will
be TASK_ETERNITY and we then don't want to be waken up again.

2 weeks agoBUG/MEDIUM: build: limit excessive and counter-productive gcc-15 vectorization
Willy Tarreau [Wed, 22 Oct 2025 16:55:29 +0000 (18:55 +0200)] 
BUG/MEDIUM: build: limit excessive and counter-productive gcc-15 vectorization

In https://bugs.gentoo.org/964719, Dan Goodliffe reported that using
CFLAGS="-O3 -march=westmere" creates a binary that segfaults on startup
with gcc-15. This could be reproduced here, is isolated to gcc-15 and
-O3, and is caused by gcc emitting "movdqa" instructions to read unaligned
longs taken from chars that were carefully isolated within ifdefs checking
for support for unaligned integers on the platform...

Some experiments showed that changing all casts all over the code using
either typedef-enforced align(1) or using the packed union trick does
the job, it needs a more in-depth validation since it's obvious that
it doesn't produce the same code at all (at least on more modern
machines).

However, the offending optimization option could be isolated, it's
"-fvect-cost-model=dynamic" which causes this, while -O2 uses
"-fvect-cost-model=very-cheap". Turning it back to very-cheap solves the
issue, reduces the code, and yields an extra 5% performance increase on
the http-request rate (181k vs 172k on a single core)! This could at
least partially explain why it has been observed several times over
the last few years that -O3 yields bigger and slower code than -O2.

It was also verified that the option doesn't change the emitted code
at -O0..-O2,-Os,-Oz, but only at -O3.

This patch detects the presence of this option and turns it on to
address the problem that some distros are facing after an upgrade to
gcc-15. As such it should be backported to recent LTS and stable
branches. Here, 3.1 was used, so it seems legit to at least target
the last two LTS branches (i.e. go as far as 3.0).

Thanks to Dan Goodliffe for sharing a working reproducer, Sam James
for starting the investigations and Christian Ruppert for bringing
the issue to us.

2 weeks agoBUG/MAJOR: stats-file: ensure shm_stats_file_object struct mapping consistency
Aurelien DARRAGON [Wed, 22 Oct 2025 14:04:23 +0000 (16:04 +0200)] 
BUG/MAJOR: stats-file: ensure shm_stats_file_object struct mapping consistency

As reported by @tianon on GH #3168, running haproxy on 32bits i386
platform would trigger the following BUG_ON() statement:

 FATAL: bug condition "sizeof(struct shm_stats_file_object) != 544" matched at src/stats-file.c:825
shm_stats_file_object struct size changed, is is part of the exported API: ensure all precautions were taken (ie: shm_stats_file version change) before adjusting this

In fact, some efforts were already taken to ensure shm_stats_file_object
struct size remains consistent on 64 vs 32 bits platforms, since
shm_stats_file_object is part of the public API and directly exposed in
the stats file.

However, some parts were overlooked: some structs that are embedded in
shm_stats_file_object struct itself weren't using fixed-width integers,
and would sometime be unaligned. The result of this is that it was
up to the compiler (platform-dependent) to choose how to deal with such
ambiguities, which could cause the struct mapping/size to be inconsistent
from one platform to another.

Hopefully this was caught by the BUG_ON() statement and with the precious
help of @tianon

To fix this, we now use fixed-width integers everywhere for members
(and submembers) of shm_stats_file_object struct, and we use explicit
padding where missing to avoid automatic padding when we don't expect
one. As for the previous commit, we leverage FIXED_SIZE() and
FIXED_SIZE_ARRAY() macro to set the expected width for each integer
without causing build issues on platform that don't support larger
integers.

No backport needed, this feature was introduced during 3.3-dev.

2 weeks agoMEDIUM: freq-ctr: use explicit-size types for freq-ctr struct
Aurelien DARRAGON [Wed, 22 Oct 2025 07:34:17 +0000 (09:34 +0200)] 
MEDIUM: freq-ctr: use explicit-size types for freq-ctr struct

freq-ctr struct is used by the shm_stats_file API, and more precisely,
it is used in the shm_stats_file_object struct for counters.

shm_stats_file_object struct requires to be plateform-independent, thus
we switch to using explicit size types (AKA fixed width integer types)
for freq-ctr, in the attempt to make freq-ctr size and memory mapping
consistent from one platform to another.

We cannot simply use fixed-width integer because some of them are
involved in atomic operations, and forcing a given width could
cause build issues on some platforms where atomic ops are not
implemented for large integers. Instead we leverage the FIXED_SIZE
macro to keep handling the integers as before, but forcing them to
be stored using expected number of bytes (unused bytes will simply
be ignored).

No change of behavior should be expected.

2 weeks agoMINOR: compiler: add FIXED_SIZE(size, type, name) macro
Aurelien DARRAGON [Wed, 22 Oct 2025 17:23:02 +0000 (19:23 +0200)] 
MINOR: compiler: add FIXED_SIZE(size, type, name) macro

FIXED_SIZE() macro can be used to instruct the compiler that the struct
member named <name>, handled as <type>, must be stored using <size> bytes
and that even if the type used is actualler smaller than the expected size

FIXED_SIZE_ARRAY(), similar to FIXED_SIZE() but for arrays: it takes an
extra argument which is the number of members.

They may be used for portability concerns to ensure a structure mapping
remains consistent between platforms.

2 weeks agoMINOR: stats-file: fix typo in shm-stats-file object struct size detection
Aurelien DARRAGON [Wed, 22 Oct 2025 07:16:07 +0000 (09:16 +0200)] 
MINOR: stats-file: fix typo in shm-stats-file object struct size detection

As reported by @TimWolla on GH #3168, there was a typo in shm stats file
BUG_ON to report that the size of shm_stats_file_object changed.

No backport needed.

2 weeks agoMINOR: quic: remove received CRYPTO temporary tree storage
Amaury Denoyelle [Mon, 20 Oct 2025 12:29:55 +0000 (14:29 +0200)] 
MINOR: quic: remove received CRYPTO temporary tree storage

The previous commit switch from ncbuf to ncbmbuf as storage for received
CRYPTO frames. The latter ensures that buffering of such frames cannot
fail anymore due to gaps size.

Previously, extra mechanism were implemented on QUIC frames parsing
function to overcome the limitation of ncbuf on gaps size. Before
insertion, CRYPTO frames were stored in a temporary tree to order their
insertion. As this is not necessary anymore, this commit removes the
temporary tree insertion.

This commit is closely associated to the previous bug fix. As it
provides a neat optimization and code simplication, it can be backported
with it, but not in the next immediate release to spot potential
regression.

2 weeks agoBUG/MAJOR: quic: use ncbmbuf for CRYPTO handling
Amaury Denoyelle [Thu, 16 Oct 2025 14:43:16 +0000 (16:43 +0200)] 
BUG/MAJOR: quic: use ncbmbuf for CRYPTO handling

In QUIC, TLS handshake messages such as ClientHello are encapsulated in
CRYPTO frames. Each QUIC implementation can split the content in several
frames of random sizes. In fact, this feature is now used by several
clients, based on chrome so-called "Chaos protection" mechanism :

https://quiche.googlesource.com/quiche/+/cb6b51054274cb2c939264faf34a1776e0a5bab7

To support this, haproxy uses a ncbuf storage to store received CRYPTO
frames before passing it to the SSL library. However, this storage
suffers from a limitation as gaps between two filled blocks cannot be
smaller than 8 bytes. Thus, depending on the size of received CRYPTO
frames and their order, ncbuf may not be sufficient. Over time, several
mechanisms were implemented in haproxy QUIC frames parsing to overcome
the ncbuf limitation.

However, reports recently highlight that with some clients haproxy is
not able to deal with CRYPTO frames reception. In particular, this is
the case with the latest ngtcp2 release, which implements a similar
chaos protection mechanism via the following patch. It also seems that
this impacts haproxy interaction with firefox.

commit 89c29fd8611d5e6d2f6b1f475c5e3494c376028c
Author: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
Date:   Mon Aug 4 22:48:06 2025 +0900

    Crumble Client Initial CRYPTO (aka chaos protection)

To fix haproxy CRYPTO frames buffering once and for all, an alternative
non-contiguous buffer named ncbmbuf has been recently implemented. This
type does not suffer from gaps size limitation, albeit at the cost of a
small reduction in the size available for data storage.

Thus, the purpose of this current patch is to replace ncbuf with the
newer ncbmbuf for QUIC CRYPTO frames parsing. Now, ncbmb_add() is used
to buffer received frames which is guaranteed to suceed. The only
remaining case of error is if a received frame offset and length exceed
the ncbmbuf data storage, which would result in a CRYPTO_BUFFER_EXCEEDED
error code.

A notable behavior change when switching to ncbmbuf implementation is
that NCB_ADD_COMPARE mode cannot be used anymore during add. Instead,
crypto frame content received at a similar offset will be overwritten.

A final note regarding STREAM frames parsing. For now, it is considered
unnecessary to switch from ncbuf in this case. Indeed, QUIC clients does
not perform aggressive fragmentation for them. Keeping ncbuf ensure that
the data storage size is bigger than the equivalent ncbmbuf area.

This should fix github issue #3141.

This patch must be backported up to 2.6. It is first necessary to pick
the relevant commits for ncbmbuf implementation prior to it.

2 weeks agoMINOR: ncbmbuf: add tests as standalone mode
Amaury Denoyelle [Thu, 16 Oct 2025 14:41:42 +0000 (16:41 +0200)] 
MINOR: ncbmbuf: add tests as standalone mode

Write some tests for ncbmbuf buf. These tests should be run each time
ncbmbuf implementation is adjusted. Use the following command :

$ gcc -g -DSTANDALONE -I./include -o ncbmbuf src/ncbmbuf.c && ./ncbmbuf

As the previous patch, this commit must be backported prior to the fix
to come on QUIC CRYPTO frames parsing.

2 weeks agoMINOR: ncbmbuf: implement advance operation
Amaury Denoyelle [Thu, 16 Oct 2025 13:05:50 +0000 (15:05 +0200)] 
MINOR: ncbmbuf: implement advance operation

Implement ncbmb_advance() function for the ncbmbuf type. This allows to
remove bytes in front of the buffer, regardless of the existing gaps.
This is implemented by resetting the corresponding bits of the bitmap.

As the previous patch, this commit must be backported prior to the fix
to come on QUIC CRYPTO frames parsing.

2 weeks agoMINOR: ncbmbuf: implement ncbmb_data()
Amaury Denoyelle [Wed, 15 Oct 2025 09:56:16 +0000 (11:56 +0200)] 
MINOR: ncbmbuf: implement ncbmb_data()

Implement ncbmb_data() function for the ncbmbuf type. Its purpose is
similar to its ncbuf counterpart : it returns the size in bytes of data
starting at a specific offset until the next gap.

As the previous patch, this commit must be backported prior to the fix
to come on QUIC CRYPTO frames parsing.

2 weeks agoMINOR: ncbmbuf: implement iterator bitmap utilities functions
Amaury Denoyelle [Thu, 16 Oct 2025 15:34:10 +0000 (17:34 +0200)] 
MINOR: ncbmbuf: implement iterator bitmap utilities functions

Extend private API for ncbmbuf type by defining an iterator type for the
buffer bitmap handling. The purpose is to provide a simple method to
iterate over the bitmap one byte at a time, with a proper bitmask set to
hide irrelevant bits.

This internal type is unused for now, but will become useful when
implementing ncb_data() and ncb_advance() functions.

As the previous patch, this commit must be backported prior to the fix
to come on QUIC CRYPTO frames parsing.

2 weeks agoMINOR: ncbmbuf: implement add
Amaury Denoyelle [Tue, 14 Oct 2025 14:17:14 +0000 (16:17 +0200)] 
MINOR: ncbmbuf: implement add

This patch implements add operation for ncbmbuf type.

This function is simpler than its ncbuf counterpart. Indeed, for now
only NCB_ADD_OVERWRT mode is supported. This compromise has been chosen
as ncbmbuf will be first used for QUIC CRYPTO frames handling, which
does not mandate to compare existing filled blocks during insertion.

As the previous patch, this commit must be backported prior to the fix
to come on QUIC CRYPTO frames parsing.

2 weeks agoMINOR: ncbmbuf: define new ncbmbuf type
Amaury Denoyelle [Tue, 14 Oct 2025 09:29:40 +0000 (11:29 +0200)] 
MINOR: ncbmbuf: define new ncbmbuf type

Define ncbmbuf which is an alternative non-contiguous buffer
implementation. "bm" abbreviation stands for bitmap, which reflects how
gaps and filled blocks are encoded. The main purpose of this
implementation is to get rid of the ncbuf limitation regarding the
minimal size for gaps between two blocks of data.

This commit adds the new module ncbmbuf. Along with it, some utility
functions such as ncbmb_make(), ncbmb_init() and ncbmb_is_empty() are
defined. Public API of ncbmbuf will be extended in the following
patches.

This patch is not considered a bug fix. However, it will be required to
fix issue encountered on QUIC CRYPTO frames parsing. Thus, it will be
necessary to backport the current patch prior to the fix to come.

2 weeks agoMINOR: ncbuf: extract common types
Amaury Denoyelle [Tue, 14 Oct 2025 09:35:21 +0000 (11:35 +0200)] 
MINOR: ncbuf: extract common types

ncbuf is a module which provide a non-contiguous buffer type
implementation. This patch extracts some basic types related to it into
a new file ncbuf_common.h.

This patch will be useful to provide a new non-contiguous buffer
alternative implementation based on a bitmap.

This patch is not a bug fix. However, it is necessary for ncbmbuf
implementation which will be required to fix a QUIC issue on CRYPTO
frames parsing. This, it will be necessary to backport the current patch
prior to the fix to come.

2 weeks agoBUG/MAJOR: pools: fix default pool alignment
Willy Tarreau [Wed, 22 Oct 2025 07:01:54 +0000 (09:01 +0200)] 
BUG/MAJOR: pools: fix default pool alignment

The doc in commit 977feb5617 ("DOC: api: update the pools API with the
alignment and typed declarations") says that alignment of zero means
the type's alignment. And this is followed by the DECLARE_TYPED_POOL()
macro. Yet this is not what is done in create_pool_from_reg() which
only raises the alignment to a void* if lower, while it should start
from the type's. The effect is haproxy refusing to start on some 32-bit
platforms since that commit, displaying an error such as:

   "BUG in the code: at src/mux_h2.c:454, requested creation of pool
    'h2s' aligned to 4 while type requires alignment of 8! Please
    report to developers. Aborting."

Let's just apply the default type's alignment.

Thanks to @tianon for reporting this in GH issue #3168. No backport is
needed since aligned pools are 3.3-only.

2 weeks agoBUG/MEDIUM: h3: properly encode response after interim one in same buf
Amaury Denoyelle [Tue, 21 Oct 2025 13:06:39 +0000 (15:06 +0200)] 
BUG/MEDIUM: h3: properly encode response after interim one in same buf

Recently, proper support for interim responses forwarding to HTTP/3
client has been implemented. However, there was still an issue if two
responses are both encoded in the same snd_buf() iteration.

The issue is caused due to H3 HEADERS frame encoding method : 5 bytes
are reserved in front of the buffer to encode both H3 frame type and
varint length field. After proper headers encoding, output buffer head
is adjusted so that length can be encoded using the minimal varint size.

However, if the buffer is not empty due to a previous response already
encoded but not yet emitted, messing with the buffer head will corrupt
the entire H3 message. This only happens when encoding of both responses
is done in the same snd_buf() iteration, or at least without emission to
quic_conn layer in between.

The result of this bug is that the HTTP/3 client will be unable to parse
the response, most of the time reporting a formatting error. This can
be reproduced using the following netcat as HTTP/1 server to haproxy :

$ while sleep 0.2; do \
    printf "HTTP/1.1 100 continue\r\n\r\nHTTP/1.1 200 ok\r\nContent-length: 5\r\nConnection: close\r\n\r\nblah\n" | nc -lp8002
  done

To fix this, only adjust buffer head if content is empty. If this is not
the case, frame length is simply encoded as a 4-bytes varint size so
that messages are contiguous in the buffer.

This must be backported up to 2.6.

2 weeks agoBUG/MEDIUM: h1-htx: Don't set HTX_FL_EOM flag on 1xx informational messages
Christopher Faulet [Tue, 21 Oct 2025 12:22:25 +0000 (14:22 +0200)] 
BUG/MEDIUM: h1-htx: Don't set HTX_FL_EOM flag on 1xx informational messages

1xx informational messages are part of the HTTP response. It is not expected
to have a HX_FL_EOM flag set after parsing such messages when received from
a server. It is espacially important whne an informational messages is
processed on client side while the final response was not recieved yet, to
not erroneously detect the end of the message.

The HTTP multiplexers seem to ignore the HTX_FL_EOM flag for information
messages, but it remains an error from the HTX specification point of
view. So it must be fixed.

While it should theorically be backported as far as 3.0, it is a good idea
to not do so for now because no bug was reported and regressions may happen.

2 weeks agoMEDIUM: stick-tables: Stop as soon as stktable_trash_oldest succeeds.
Olivier Houchard [Wed, 15 Oct 2025 14:01:21 +0000 (16:01 +0200)] 
MEDIUM: stick-tables: Stop as soon as stktable_trash_oldest succeeds.

stktable_trash_oldest() goes through all the shards, trying to free a
number of entries. Going through each shard is expensive, as we have to
take the shard lock, so stop as soon as we free'd at least one entry, as
it is only called when we want to make room for one entry.

2 weeks agoMEDIUM: stick-tables: Stop if stktable_trash_oldest() fails.
Olivier Houchard [Tue, 14 Oct 2025 16:51:32 +0000 (18:51 +0200)] 
MEDIUM: stick-tables: Stop if stktable_trash_oldest() fails.

In stksess_new(), if the table is full, we call stktable_trash_oldest()
to remove a few entries so that we have some room for a new one.
It is unlikely, but possible, that stktable_trash_oldest() will fail. If
so, just give up and do not add the new entry, instead of adding it
anyway.
Give up if stktable_trash_oldest() fails to free any entry

2 weeks agoMEDIUM: stick-tables: Remove the table lock
Olivier Houchard [Thu, 9 Oct 2025 16:28:08 +0000 (18:28 +0200)] 
MEDIUM: stick-tables: Remove the table lock

Remove the table lock, it was only protecting the per-table expiration
date, and that task is gone.

2 weeks agoMEDIUM: stick-tables: Use a per-shard expiration task
Olivier Houchard [Mon, 29 Sep 2025 13:37:11 +0000 (15:37 +0200)] 
MEDIUM: stick-tables: Use a per-shard expiration task

Instead of having per-table expiration tasks, just use one per shard.
The task will now go through all the tables to expire entries. When a
table gets an expiration earlier than the one previously known, it will
be put in a mt-list, and the task will be responsible to put it into an
eb32, ordered based on the next expiration.
Each per-shard task will run on a different thread, so it should lead to
a better load distribution than the per-table tasks.

2 weeks agoMINOR: initcalls: Add a new initcall stage, STG_INIT_2
Olivier Houchard [Thu, 16 Oct 2025 13:45:52 +0000 (15:45 +0200)] 
MINOR: initcalls: Add a new initcall stage, STG_INIT_2

Add a new initcall stage, STG_INIT_2, for stuff to be called after
step_init_2() is called, so after we know for sure that global.nbthread
will be set.
Modify stick-tables stkt_late_init() to run at STG_INIT_2 instead of
STG_INIT, in anticipation for it to be enhanced and have a need for
global.nbthread.

2 weeks agoBUG/MEDIUM: cli: also free the trash chunk on the error path
Willy Tarreau [Mon, 20 Oct 2025 12:50:27 +0000 (14:50 +0200)] 
BUG/MEDIUM: cli: also free the trash chunk on the error path

Since commit 20ec1de214 ("MAJOR: cli: Refacor parsing and execution of
pipelined commands"), command not returning any response (e.g. "quit")
don't pass through the free_trash_chunk() call, possibly leaking the
cmdline buffer. A typical way to reproduce it is to loop on "quit" on
the CLI, though it very likely affects other specific commands.

Let's make sure in the release handler that we always release that
chunk in any case. This must be backported to 3.2.

2 weeks agoBUG/MINOR: quic-be: unchecked connections during handshakes
Frederic Lecaille [Mon, 20 Oct 2025 12:27:12 +0000 (14:27 +0200)] 
BUG/MINOR: quic-be: unchecked connections during handshakes

This bug impacts only the backends.

The ->conn (pointer to struct connection) member validity of the ssl_sock_ctx
struct was not checked before being dereferenced, leading to possible crashes
in qc_ssl_do_hanshake() during handshake.

This was reported by GH #3163 issue.

No need to backport because the QUIC backend support arrived with 3.3

2 weeks agoBUG/MEDIUM: mt_list: Make sure not to unlock the element twice
Olivier Houchard [Sun, 19 Oct 2025 21:17:55 +0000 (23:17 +0200)] 
BUG/MEDIUM: mt_list: Make sure not to unlock the element twice

In mt_list_delete(), if the element was not in a list, then n and p will
point to it, and so setting n->prev and n->next will be enough to unlock it.
Don't do it twice, as once it's been done the first time, another thread may
be working with it, and may have added it to a list already, and doing it
a second time can lead to list inconsistencies.

This should be backported up to 2.8.

2 weeks ago[RELEASE] Released version 3.3-dev10 v3.3-dev10
Willy Tarreau [Sat, 18 Oct 2025 09:24:05 +0000 (11:24 +0200)] 
[RELEASE] Released version 3.3-dev10

Released version 3.3-dev10 with the following main changes :
    - BUG/MEDIUM: connections: Only avoid creating a mux if we have one
    - BUG/MINOR: sink: retry attempt for sft server may never occur
    - CLEANUP: mjson: remove MJSON_ENABLE_RPC code
    - CLEANUP: mjson: remove MJSON_ENABLE_PRINT code
    - CLEANUP: mjson: remove MJSON_ENABLE_NEXT code
    - CLEANUP: mjson: remove MJSON_ENABLE_BASE64 code
    - CLEANUP: mjson: remove unused defines and math.h
    - BUG/MINOR: http-ana: Reset analyse_exp date after 'wait-for-body' action
    - CLEANUP: mjson: remove unused defines from mjson.h
    - BUG/MINOR: acme: avoid overflow when diff > notAfter
    - DEV: patchbot: use git reset+checkout instead of pull
    - MINOR: proxy: explicitly permit abortonclose on frontends and clarify the doc
    - REGTESTS: fix h2_desync_attacks to wait for the response
    - REGTESTS: http-messaging: fix the websocket and upgrade tests not to close early
    - MINOR: proxy: only check abortonclose through a dedicated function
    - MAJOR: proxy: enable abortonclose by default on HTTP proxies
    - MINOR: proxy: introduce proxy_abrt_close_def() to pass the desired default
    - MAJOR: proxy: enable abortonclose by default on TLS listeners
    - MINOR: h3/qmux: Set QC_SF_UNKNOWN_PL_LENGTH flag on QCS when headers are sent
    - MINOR: stconn: Add two fields in sedesc to replace the HTX extra value
    - MINOR: h1-htx: Increment body len when parsing a payload with no xfer length
    - MINOR: mux-h1: Set known input payload length during demux
    - MINOR: mux-fcgi: Set known input payload length during demux
    - MINOR: mux-h2: Use <body_len> H2S field for payload without content-length
    - MINOR: mux-h2: Set known input payload length of the sedesc
    - MINOR: h3: Set known input payload length of the sedesc
    - MINOR: stconn: Move data from kip to kop when data are sent to the consumer
    - MINOR: filters: Reset knwon input payload length if a data filter is used
    - MINOR: hlua/http-fetch: Use <kip> instead of HTX extra field to get body size
    - MINOR: cache: Use the <kip> value to check too big objects
    - MINOR: compression: Use the <kip> value to check body size
    - MEDIUM: mux-h1: Stop to use HTX extra value when formatting message
    - MEDIUM: htx: Remove the HTX extra field
    - MEDIUM: acme: don't insert acme account key in ckchs_tree
    - BUG/MINOR: acme: memory leak from the config parser
    - CI: cirrus-ci: bump FreeBSD image to 14-3
    - BUG/MEDIUM: ssl: take care of second client hello
    - BUG/MINOR: ssl: always clear the remains of the first hello for the second one
    - BUG/MEDIUM: stconn: Properly forward kip to the opposite SE descriptor
    - MEDIUM: applet: Forward <kip> to applets
    - DEBUG: mux-h1: Dump <kip> and <kop> values with sedesc info
    - BUG/MINOR: ssl: leak in ssl-f-use
    - BUG/MINOR: ssl: leak crtlist_name in ssl-f-use
    - BUILD: makefile: disable tail calls optimizations with memory profiling
    - BUG/MEDIUM: apppet: Improve spinning loop detection with the new API
    - BUG/MINOR: ssl: Free global_ssl structure contents during deinit
    - BUG/MINOR: ssl: Free key_base from global_ssl structure during deinit
    - MEDIUM: jwt: Remove certificate support in jwt_verify converter
    - MINOR: jwt: Add new jwt_verify_cert converter
    - MINOR: jwt: Do not look into ckch_store for jwt_verify converter
    - MINOR: jwt: Add new "jwt" certificate option
    - MINOR: jwt: Add specific error code for known but unavailable certificate
    - DOC: jwt: Add doc about "jwt_verify_cert" converter
    - MINOR: ssl: Dump options in "show ssl cert"
    - MINOR: jwt: Add new "add/del/show ssl jwt" CLI commands
    - REGTEST: jwt: Test new CLI commands
    - BUG/MINOR: ssl: Potential NULL deref in trace macro
    - MINOR: regex: use a thread-local match pointer for pcre2
    - BUG/MEDIUM: pools: fix bad freeing of aligned pools in UAF mode
    - MEDIUM: pools: detect() when munmap() fails in UAF mode
    - TESTS: quic: useless param for b_quic_dec_int()
    - BUG/MEDIUM: pools: fix crash on filtered "show pools" output
    - BUG/MINOR: pools: don't report "limited to the first X entries" by default
    - BUG/MAJOR: lb-chash: fix key calculation when using default hash-key id
    - BUG/MEDIUM: stick-tables: Don't forget to dec count on failure.
    - BUG/MINOR: quic: check applet_putchk() for 'show quic' first line
    - TESTS: quic: fix uninit of quic_cc_path const member
    - BUILD: ssl: can't build when using -DLISTEN_DEFAULT_CIPHERS
    - BUG/MAJOR: quic: uninitialized quic_conn_closed struct members
    - BUG/MAJOR: quic: do not reset QUIC backends fds in closing state
    - BUG/MINOR: quic: SSL counters not handled
    - DOC: clarify the experimental status for certain features
    - MINOR: config: remove experimental status on tune.disable-fast-forward
    - MINOR: tree-wide: add missing TAINTED flags for some experimental directives
    - MEDIUM: config: warn when expose-experimental-directives is used for no reason
    - BUG/MEDIUM: threads/config: drop absent threads from thread groups
    - REGTESTS: remove experimental from quic/retry.vtc

3 weeks agoREGTESTS: remove experimental from quic/retry.vtc
Willy Tarreau [Fri, 17 Oct 2025 18:55:43 +0000 (20:55 +0200)] 
REGTESTS: remove experimental from quic/retry.vtc

Recent commit 8b7a82cd30 ("MEDIUM: config: warn when
expose-experimental-directives is used for no reason") triggered on
this test exactly for the reason it was made for. The tests were just
done without quic on it. Let's drop the unneeded option.

3 weeks agoBUG/MEDIUM: threads/config: drop absent threads from thread groups
Willy Tarreau [Fri, 17 Oct 2025 18:36:00 +0000 (20:36 +0200)] 
BUG/MEDIUM: threads/config: drop absent threads from thread groups

Thread groups can be assigned arbitrary thread ranges, but if the
mentioned threads do not exist, this causes crashes in listener_accept()
or some connections to be ignored. The reason is that the calculated
mask is derived from the thread group's enabled threads count. Examples:

  global
     nbthread 2
     thread-groups 2
     thread-group 1 1-64
     thread-group 2 65-128

  frontend f-crash
     bind :8001 thread 1/all

  frontend f-freeze
     bind :8002 thread 2/all

This commit removes missing threads, emits a warning when the thread
group just has less threads than requested, and an error when it is
left with no threads at all.

This must be backported to 3.1 since the issue is present there already.

3 weeks agoMEDIUM: config: warn when expose-experimental-directives is used for no reason
Willy Tarreau [Fri, 17 Oct 2025 16:15:12 +0000 (18:15 +0200)] 
MEDIUM: config: warn when expose-experimental-directives is used for no reason

If users start to enable expose-experimental-directives for the purpose
of testing one specific feature, there are chances that the option remains
forever and hides the experimental status of other options.

Let's emit a warning if the option appears and is not used. This will
remind users that they can now drop it, and help keep configs safe for
future upgrades.

3 weeks agoMINOR: tree-wide: add missing TAINTED flags for some experimental directives
Willy Tarreau [Fri, 17 Oct 2025 15:57:40 +0000 (17:57 +0200)] 
MINOR: tree-wide: add missing TAINTED flags for some experimental directives

We normally taint the process when using experimental directives, but
a handful of places were missed so we don't always know that they are
in use. Let's fix these places (hint for future directives, just look
for places checking for "experimental_directives_allowed", and add
"mark_tainted(TAINTED_CONFIG_EXP_KW_DECLARED);").

3 weeks agoMINOR: config: remove experimental status on tune.disable-fast-forward
Willy Tarreau [Fri, 17 Oct 2025 16:55:03 +0000 (18:55 +0200)] 
MINOR: config: remove experimental status on tune.disable-fast-forward

The option was turned to off by default in 2.8 with commit 2f7c82bfd
("BUG/MINOR: haproxy: Fix option to disable the fast-forward"), however
at the same time it should have dropped its experimental status since
the feature is enabled by default. The only goal of the option is to
debug something, like many other tune.xxx options. The option should
still normally not be used without being invited to do so by developers
looking for something specific though.

This could be backported if desired to simplify debugging, though this
has never been needed for now.

3 weeks agoDOC: clarify the experimental status for certain features
Willy Tarreau [Fri, 17 Oct 2025 16:39:03 +0000 (18:39 +0200)] 
DOC: clarify the experimental status for certain features

Certain features require "expose-experimental-directives" to be set in
the global section. Let's clarify that experimental featuers are only
maintained in best effort mode, may break during the stable cycle, and
are generally not maintained beyond the release of the next LTS branch
since it is extremely challenging, and early adopters are expected to
upgrade to benefit from improvements anyway.

3 weeks agoBUG/MINOR: quic: SSL counters not handled
Frederic Lecaille [Fri, 17 Oct 2025 10:07:10 +0000 (12:07 +0200)] 
BUG/MINOR: quic: SSL counters not handled

The SSL counters were not handled at all for QUIC connections. This patch
implement ssl_sock_update_counters() extracting the code from ssl_sock.c
and call this function where applicable both in TLS/TCP and QUIC parts.

Must be backported as far as 2.8.

3 weeks agoBUG/MAJOR: quic: do not reset QUIC backends fds in closing state
Frederic Lecaille [Fri, 17 Oct 2025 09:04:36 +0000 (11:04 +0200)] 
BUG/MAJOR: quic: do not reset QUIC backends fds in closing state

This bug impacts only the backends.

When entering the closing state, a quic_closed_conn is used to replace the quic_conn.
In this state, the ->fd value was reset to -1 value calling qc_init_fd(). This value
is used by qc_may_use_saddr() which supposes it cannot be -1 for a backend, leading
->li to be dereferencd, which is legal only for a listener.

This bug impacts only the backend but with possible crash when qc_may_use_saddr()
is called: qc_test_fd() is false leading qc->li to be dereferenced. This is legal
only for a listener.

This patch prevents such fd value resettings for backends.

No need to backport because the QUIC backends support arrived with 3.3.

3 weeks agoBUG/MAJOR: quic: uninitialized quic_conn_closed struct members
Frederic Lecaille [Fri, 17 Oct 2025 08:47:52 +0000 (10:47 +0200)] 
BUG/MAJOR: quic: uninitialized quic_conn_closed struct members

A quic_conn_closed struct is initialized to replace the quic_conn when the
connection enters the closing to reduce the connection memory footprint.
->max_udp_payload quic_conn_close was not initialized leading to possible
BUG_ON()s in qc_rcv_buf() when comparing the RX buf size to this payload.

->cntrs counters were alon not initialized with the only consequence
to generate wrong values for these counters.

Must be backported as far as 2.9.

3 weeks agoBUILD: ssl: can't build when using -DLISTEN_DEFAULT_CIPHERS
William Lallemand [Fri, 17 Oct 2025 07:35:41 +0000 (09:35 +0200)] 
BUILD: ssl: can't build when using -DLISTEN_DEFAULT_CIPHERS

Emeric reported that he can't build haproxy anymore since 9bc6a034
("BUG/MINOR: ssl: Free global_ssl structure contents during deinit").

    src/ssl_sock.c:7020:40: error: comparison with string literal results in unspecified behavior [-Werror=address]
     7020 |  if (global_ssl.listen_default_ciphers != LISTEN_DEFAULT_CIPHERS)
          |                                        ^~
    src/ssl_sock.c:7023:41: error: comparison with string literal results in unspecified behavior [-Werror=address]
     7023 |  if (global_ssl.connect_default_ciphers != CONNECT_DEFAULT_CIPHERS)
          |                                         ^~
    src/ssl_sock.c: At top level:

Indeed the mentionned patch is checking the pointer in order to free
something freeable, but that can't work because these constant are
strings literal which can be passed from the compiler and not pointers.

Also the test is not useful, because these strings are strdup() in
__ssl_sock_init, so they can be free directly.

Must be backported in every stable branches with 9bc6a034.

3 weeks agoTESTS: quic: fix uninit of quic_cc_path const member
Amaury Denoyelle [Fri, 17 Oct 2025 07:22:44 +0000 (09:22 +0200)] 
TESTS: quic: fix uninit of quic_cc_path const member

Fix quic_tx unittest module by adding an explicit define for <mtu> const
member of quic_cc_path.

This should fix coverity report from github issue #3162.

This can be backported up to 3.2.

3 weeks agoBUG/MINOR: quic: check applet_putchk() for 'show quic' first line
Amaury Denoyelle [Mon, 13 Oct 2025 16:16:22 +0000 (18:16 +0200)] 
BUG/MINOR: quic: check applet_putchk() for 'show quic' first line

Ensure applet_putchk() return value is checked when outputing via the
CLI 'show quic' header line.

This is only to align with other usages of the same function, as trash
output buffer should always be large enough for it. As such, the command
is simply aborted if this is not the case.

This should fix coverity report from github issue #3139.

This could be backported up to 2.8.

3 weeks agoBUG/MEDIUM: stick-tables: Don't forget to dec count on failure.
Olivier Houchard [Tue, 14 Oct 2025 16:11:31 +0000 (18:11 +0200)] 
BUG/MEDIUM: stick-tables: Don't forget to dec count on failure.

In stksess_new(), if we failed to allocate memory for the new stksess,
don't forget to decrement the table entry count, as nobody else will
do it for us.
An artificially high count could lead to at least purging entries while
there is no need to.

This should be backported up to 2.8.

WIP decrement current on allocation failure

3 weeks 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

3 weeks agoBUG/MINOR: pools: don't report "limited to the first X entries" by default
Willy Tarreau [Thu, 16 Oct 2025 06:38:35 +0000 (08:38 +0200)] 
BUG/MINOR: pools: don't report "limited to the first X entries" by default

With the fix in commit 982805e6a3 ("BUG/MINOR: pools: Fix the dump of
pools info to deal with buffers limitations"), the max count is now
compared to the number of dumped pools instead of the configured
numbered, and keeping >= is no longer valid because maxcnt is set by
default to the same value when not set, so this means that since this
patch we're always displaying "limited to the first X entries" where X
is the number of dumped entries even in the absence of any limitation.
Let's just fix the comparison to only show this when the limit is lower.

This must be backported to 3.2 where the patch above already is.

3 weeks agoBUG/MEDIUM: pools: fix crash on filtered "show pools" output
Willy Tarreau [Thu, 16 Oct 2025 06:27:44 +0000 (08:27 +0200)] 
BUG/MEDIUM: pools: fix crash on filtered "show pools" output

The truncation of pools output that was adressed in commit 982805e6a3
("BUG/MINOR: pools: Fix the dump of pools info to deal with buffers
limitations") required to split the pools filling from dumping. However
there is a problem when a limit is passed that is lower than the number
of pools or if a pool name is specified or if pool caches are disabled,
because in this case the number of filled slots will be lower than the
initially allocated one, and empty entries will be visited either by the
sort functions when filling the entries if "byxxx" is specified, or by
the dump function after the last entry, but none of these functions was
expecting to be passed a NULL entry.

Let's just re-adjust nbpools to match the number of filled entries at
the end. Anyway the totals are calculated on the number of dumped
entries.

This must be backported to 3.2 since the fix above was backported there
as well.

3 weeks agoTESTS: quic: useless param for b_quic_dec_int()
Frederic Lecaille [Wed, 15 Oct 2025 07:58:03 +0000 (09:58 +0200)] 
TESTS: quic: useless param for b_quic_dec_int()

The third parameter passed to b_quic_dec_int() is unitialized. This is not a bug.
But this disturbs coverity for an unknown reason as revealed by GH issue #3154.

This patch takes the opportunity to use NULL as passed value to avoid using such
an uneeded third parameter.

Should be backported to 3.2 where this unit test was introduced.

3 weeks agoMEDIUM: pools: detect() when munmap() fails in UAF mode
Willy Tarreau [Mon, 13 Oct 2025 17:22:31 +0000 (19:22 +0200)] 
MEDIUM: pools: detect() when munmap() fails in UAF mode

Better check that munmap() always works, otherwise it means we might
have miscalculated an address, and if it fails silently, it will eat
all the memory extremely quickly. Let's add a BUG_ON() on munmap's
return.

3 weeks agoBUG/MEDIUM: pools: fix bad freeing of aligned pools in UAF mode
Willy Tarreau [Mon, 13 Oct 2025 17:15:55 +0000 (19:15 +0200)] 
BUG/MEDIUM: pools: fix bad freeing of aligned pools in UAF mode

As reported by Christopher, in UAF mode memory release of aligned
objects as introduced in commit ef915e672a ("MEDIUM: pools: respect
pool alignment in allocations") does not work. The padding calculation
in the freeing code is no longer correct since it now depends on the
alignment, so munmap() fails on EINVAL. Fortunately we don't care much
about it since we know it's the low bits of the passed address, which
is much simpler to compute, since all mmaps are page-aligned.

There's no need to backport this, as this was introduced in 3.3.

3 weeks agoMINOR: regex: use a thread-local match pointer for pcre2
Willy Tarreau [Mon, 13 Oct 2025 14:47:50 +0000 (16:47 +0200)] 
MINOR: regex: use a thread-local match pointer for pcre2

The pcre2 matching requires an array of matches for grouping, that is
allocated when executing the rule by pre-processing it, and that is
immediately freed after use. This is quite inefficient and results in
annoying patterns in "show profiling" that attribute the allocations
to libpcre2 and the releases to haproxy.

A good suggestion from Dragan is to pre-allocate these per thread,
since the entry is not specific to a regex. In addition we're already
limited to MAX_MATCH matches so we don't even have the problem of
having to grow it while parsing nor processing.

The current patch adds a per-thread pair of init/deinit functions to
allocate a thread-local entry for that, and gets rid of the dynamic
allocations. It will result in cleaner memory management patterns and
slightly higher performance (+2.5%) when using pcre2.

3 weeks agoBUG/MINOR: ssl: Potential NULL deref in trace macro
Remi Tricot-Le Breton [Fri, 10 Oct 2025 12:16:31 +0000 (14:16 +0200)] 
BUG/MINOR: ssl: Potential NULL deref in trace macro

'ctx' might be NULL when we exit 'ssl_sock_handshake', it can't be
dereferenced without check in the trace macro.

This was found by Coverity andraised in GitHub #3113.
This patch should be backported up to 3.2

3 weeks agoREGTEST: jwt: Test new CLI commands
Remi Tricot-Le Breton [Thu, 2 Oct 2025 13:32:48 +0000 (15:32 +0200)] 
REGTEST: jwt: Test new CLI commands

Test the "add/del ssl jwt" commands and check the new return value in
case of unavailable certificate used in a jwt_verify_cert converter.

3 weeks agoMINOR: jwt: Add new "add/del/show ssl jwt" CLI commands
Remi Tricot-Le Breton [Thu, 2 Oct 2025 13:32:47 +0000 (15:32 +0200)] 
MINOR: jwt: Add new "add/del/show ssl jwt" CLI commands

The new "add/del ssl jwt <file>" commands allow to change the "jwt" flag
of an already loaded certificate. It allows to delete certificates used
for JWT validation, which was not yet possible.
The "show ssl jwt" command iterates over all the ckch_stores and dumps
the ones that have the option set.

3 weeks agoMINOR: ssl: Dump options in "show ssl cert"
Remi Tricot-Le Breton [Thu, 2 Oct 2025 13:32:46 +0000 (15:32 +0200)] 
MINOR: ssl: Dump options in "show ssl cert"

Dump the values of the 'ocsp-update' and 'jwt' flags in the output of
'show ssl cert' CLI command.

3 weeks agoDOC: jwt: Add doc about "jwt_verify_cert" converter
Remi Tricot-Le Breton [Thu, 2 Oct 2025 13:32:45 +0000 (15:32 +0200)] 
DOC: jwt: Add doc about "jwt_verify_cert" converter

Add information about the new "jwt_verify_cert" converter and update the
existing "jwt_converter" doc to remove mentions of certificates from it.
Add information about the new "jwt" certificate option.

3 weeks agoMINOR: jwt: Add specific error code for known but unavailable certificate
Remi Tricot-Le Breton [Thu, 2 Oct 2025 13:32:44 +0000 (15:32 +0200)] 
MINOR: jwt: Add specific error code for known but unavailable certificate

A certificate that does not have the 'jwt' flag enabled cannot be used
for JWT validation. We now raise a specific return value so that such a
case can be identified.

3 weeks agoMINOR: jwt: Add new "jwt" certificate option
Remi Tricot-Le Breton [Thu, 2 Oct 2025 13:32:43 +0000 (15:32 +0200)] 
MINOR: jwt: Add new "jwt" certificate option

This option can be used to enable the use of a given certificate for JWT
verification. It defaults to 'off' so certificates that are declared in
a crt-store and will be used for JWT verification must have a
"jwt on" option in the configuration.

3 weeks agoMINOR: jwt: Do not look into ckch_store for jwt_verify converter
Remi Tricot-Le Breton [Thu, 2 Oct 2025 13:32:42 +0000 (15:32 +0200)] 
MINOR: jwt: Do not look into ckch_store for jwt_verify converter

We must not try to load full-on certificates for 'jwt_verify' converter
anymore. 'jwt_verify_cert' is the only one that accepts a certificate.

3 weeks agoMINOR: jwt: Add new jwt_verify_cert converter
Remi Tricot-Le Breton [Thu, 2 Oct 2025 13:32:41 +0000 (15:32 +0200)] 
MINOR: jwt: Add new jwt_verify_cert converter

This converter will be in charge of performing the same operation as the
'jwt_verify' one except that it takes a full-on pem certificate path
instead of a public key path as parameter.
The certificate path can be either provided directly as a string or via
a variable. This allows to use certificates that are not known during
init to perform token validation.

3 weeks agoMEDIUM: jwt: Remove certificate support in jwt_verify converter
Remi Tricot-Le Breton [Thu, 2 Oct 2025 13:32:40 +0000 (15:32 +0200)] 
MEDIUM: jwt: Remove certificate support in jwt_verify converter

The jwt_verify converter will not take full-on certificates anymore
in favor of a new soon to come jwt_verify_cert. We might end up with a
new jwt_verify_hmac in the future as well which would allow to deprecate
the jwt_verify converter and remove the need for a specific internal
tree for public keys.
The logic to always look into the internal jwt tree by default and
resolve to locking the ckch tree as little as possible will also be
removed. This allows to get rid of the duplicated reference to
EVP_PKEYs, the one in the jwt tree entry and the one in the ckch_store.

4 weeks 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.

4 weeks 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.

4 weeks 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.

4 weeks 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.

4 weeks agoBUG/MINOR: ssl: leak crtlist_name in ssl-f-use
William Lallemand [Thu, 9 Oct 2025 13:12:25 +0000 (15:12 +0200)] 
BUG/MINOR: ssl: leak crtlist_name in ssl-f-use

This patch fixes a leak of the temporary variable "crtlist_name" which
is used in the ssl-f-use parser.

Must be backported in 3.2.

4 weeks agoBUG/MINOR: ssl: leak in ssl-f-use
William Lallemand [Thu, 9 Oct 2025 12:57:37 +0000 (14:57 +0200)] 
BUG/MINOR: ssl: leak in ssl-f-use

Fix the leak of the filename in the struct cfg_crt_node which is a
temporary structure used for ssl-f-use initialization.

Must be backported to 3.2.

4 weeks agoDEBUG: mux-h1: Dump <kip> and <kop> values with sedesc info
Christopher Faulet [Fri, 10 Oct 2025 09:14:23 +0000 (11:14 +0200)] 
DEBUG: mux-h1: Dump <kip> and <kop> values with sedesc info

It could be handy to debug issues, especially because these values was
recently introduced.

4 weeks agoMEDIUM: applet: Forward <kip> to applets
Christopher Faulet [Fri, 10 Oct 2025 09:11:43 +0000 (11:11 +0200)] 
MEDIUM: applet: Forward <kip> to applets

For now, no applets are using the <kop> value when consuming data. At least,
as far as I know. But it remains a good idea to keep the applet API
compatible. So now, the <kip> of the opposite side is properly forwarded to
applets.

4 weeks agoBUG/MEDIUM: stconn: Properly forward kip to the opposite SE descriptor
Christopher Faulet [Fri, 10 Oct 2025 09:01:19 +0000 (11:01 +0200)] 
BUG/MEDIUM: stconn: Properly forward kip to the opposite SE descriptor

By refactoring the HTX to remove the extra field, a bug was introduced in
the stream-connector part. The <kip> (known input payload) value of a sedesc
was moved to <kop> (knwon output payload) using the same sedesc. Of course,
this is totally wrong. <kip> value of a sedesc must be forwarded to the
opposite side.

In addition, the operation is performed in sc_conn_send(). In this function,
we manipulate the stream-connectors. So se_fwd_kip() function was changed to
use the stream-connectors directely.

Now, the function sc_ep_fwd_kip() is now called with the both
stream-connectors to properly forward <kip> from on side to the opposite
side.

The bug is 3.3-specific. No backport needed.

4 weeks 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.

4 weeks 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.

4 weeks agoCI: cirrus-ci: bump FreeBSD image to 14-3
William Lallemand [Thu, 9 Oct 2025 12:06:48 +0000 (14:06 +0200)] 
CI: cirrus-ci: bump FreeBSD image to 14-3

FreeBSD CI seems to be broken for a while, try to upgrade the image to
the latest 14.3 version.

4 weeks agoBUG/MINOR: acme: memory leak from the config parser
William Lallemand [Thu, 9 Oct 2025 09:39:17 +0000 (11:39 +0200)] 
BUG/MINOR: acme: memory leak from the config parser

This patch fixes some memory leaks in the configuration parser:

- deinit_acme() was never called
- add ha_free() before every strdup() for section overwrite
- lacked some free() in deinit_acme()

4 weeks agoMEDIUM: acme: don't insert acme account key in ckchs_tree
William Lallemand [Thu, 9 Oct 2025 08:58:22 +0000 (10:58 +0200)] 
MEDIUM: acme: don't insert acme account key in ckchs_tree

Don't insert the acme account key in the ckchs_tree anymore. ckch_store
are not made to only include a private key. CLI operations are not
possible with them either. That doesn't make much sense to keep it that
way until we rework the ckch_store.

4 weeks agoMEDIUM: htx: Remove the HTX extra field
Christopher Faulet [Thu, 18 Sep 2025 07:33:49 +0000 (09:33 +0200)] 
MEDIUM: htx: Remove the HTX extra field

Thanks for previous changes, it is now possible to remove the <extra> field
from the HTX structure. HTX_FL_ALTERED_PAYLOAD flag is also removed because
it is now unsued.

4 weeks agoMEDIUM: mux-h1: Stop to use HTX extra value when formatting message
Christopher Faulet [Thu, 18 Sep 2025 07:22:37 +0000 (09:22 +0200)] 
MEDIUM: mux-h1: Stop to use HTX extra value when formatting message

We now rely on the <kop> value to format the message payload before
sending it. It is no longer necessary to use the HTX extra field.

4 weeks agoMINOR: compression: Use the <kip> value to check body size
Christopher Faulet [Thu, 18 Sep 2025 07:19:23 +0000 (09:19 +0200)] 
MINOR: compression: Use the <kip> value to check body size

When an minimum compression size is defined, we can now use the <kip>
value to skip the compression instead of the HTX extra field.

4 weeks agoMINOR: cache: Use the <kip> value to check too big objects
Christopher Faulet [Thu, 18 Sep 2025 07:04:02 +0000 (09:04 +0200)] 
MINOR: cache: Use the <kip> value to check too big objects

When an object should be cache, to check if it is too big or not, the
<kip> value is now used instead of the HTX extra field.

4 weeks agoMINOR: hlua/http-fetch: Use <kip> instead of HTX extra field to get body size
Christopher Faulet [Thu, 18 Sep 2025 07:00:42 +0000 (09:00 +0200)] 
MINOR: hlua/http-fetch: Use <kip> instead of HTX extra field to get body size

The known input payload length now contains the information. There is no
reason to still rely on the HTX extra field.

4 weeks agoMINOR: filters: Reset knwon input payload length if a data filter is used
Christopher Faulet [Thu, 18 Sep 2025 06:58:03 +0000 (08:58 +0200)] 
MINOR: filters: Reset knwon input payload length if a data filter is used

It a data filter is registered on a channel, the corresponding <kip>
field must be reset because the payload may be altered.

4 weeks agoMINOR: stconn: Move data from kip to kop when data are sent to the consumer
Christopher Faulet [Thu, 18 Sep 2025 06:54:31 +0000 (08:54 +0200)] 
MINOR: stconn: Move data from kip to kop when data are sent to the consumer

When data are sent to the consumer, the known output payload length is
updated using the known input payload length value and this last one is then
reset. se_fwd_kip() function is used for this purpose.