]> git.ipfire.org Git - thirdparty/haproxy.git/log
thirdparty/haproxy.git
47 hours agoMINOR: ssl: Add a way to globally disable ktls. 20250820-ktls
Olivier Houchard [Wed, 13 Aug 2025 16:34:10 +0000 (16:34 +0000)] 
MINOR: ssl: Add a way to globally disable ktls.

Add a new global option, "noktls", as well as a command line option,
"-dT", to totally disable ktls usage, even if it is activated on servers
or binds in the configuration.
That makes it easier to quickly figure out if a problem is related to
ktls or not.

47 hours agoMEDIUM: ssl: Handle non-Application data record with AWS-LC
Olivier Houchard [Wed, 9 Jul 2025 17:05:01 +0000 (19:05 +0200)] 
MEDIUM: ssl: Handle non-Application data record with AWS-LC

Handle receiving and sending TLS records that are not application data
records.
When receiving, we ignore new session tickets records, we handle close
notify as a read0, and we consider any other records as a connection
error.
For sending, we're just sending close notify, so that the TLS connection
is properly closed.

47 hours agoMEDIUM: ssl: Add support for ktls on TLS 1.3 with AWS-LC
Olivier Houchard [Thu, 26 Jun 2025 11:06:18 +0000 (13:06 +0200)] 
MEDIUM: ssl: Add support for ktls on TLS 1.3 with AWS-LC

AWS-LC added a new API in AWS-LC 1.54 that allows the user to retrieve
the keys for TLS 1.3 connections with SSL_get_read_traffic_secret(), so
use it to be able to use ktls with TLS 1.3 too.

47 hours agoMEDIUM: ssl: Add ktls support for AWS-LC.
Olivier Houchard [Thu, 19 Jun 2025 16:44:22 +0000 (18:44 +0200)] 
MEDIUM: ssl: Add ktls support for AWS-LC.

Add ktls support for AWS-LC. As it does  know anything
about ktls, it means extracting keys from the ssl lib, and provide them
to the kernel. At which point we can use regular recvmsg()/sendmsg()
calls.
This patch only provides support for TLS 1.2, AWS-LC provides a
different way to extract keys for TLS 1.3.
Note that this may work with BoringSSL too, but it has not been tested.

47 hours agoMEDIUM: ssl: Add splicing with SSL.
Olivier Houchard [Wed, 13 Aug 2025 16:52:13 +0000 (16:52 +0000)] 
MEDIUM: ssl: Add splicing with SSL.

Implement the splicing methods to the SSL xprt (which will just call the
raw_sock methods if kTLS is enabled on the socket), and properly report
that a connection supports splicing if kTLS is configured on that
connection.
For OpenSSL, if the upper layer indicated that it wanted to start using
splicing by adding the CO_FL_WANT_SPLICING flag, make sure we don't read
any more data from the socket, and just drain what may be in the
internal OpenSSL buffers, before allowing splicing

47 hours agoMEDIUM: splice: Don't consider EINVAL to be a fatal error
Olivier Houchard [Wed, 9 Jul 2025 17:05:23 +0000 (19:05 +0200)] 
MEDIUM: splice: Don't consider EINVAL to be a fatal error

Don't consider that EINVAL is a fatal error, when calling splice().
When doing splicing from a kTLS socket, splice() will set errno to
EINVAL if the next record to be read is not an application data record.
This is not a fatal error, it just means we have to use recvmsg() to
read it, and potentially we can then resume using splicing.
It is unfortunate that EINVAL was used for that case, but we should
never get any other case of receiving EINVAL from splice(), so it should
be safe to treat it as non-fatal.

47 hours agoMEDIUM: ssl: Add kTLS support for OpenSSL.
Olivier Houchard [Thu, 3 Jul 2025 16:14:43 +0000 (18:14 +0200)] 
MEDIUM: ssl: Add kTLS support for OpenSSL.

Modify the SSL code to enable kTLS with OpenSSL.
It mostly requires our internal BIO to be able to handle the various
kTLS-specific controls in ha_ssl_ctrl(), as well as being able to use
recvmsg() and sendmsg() from ha_ssl_read() and ha_ssl_write().

47 hours agoMINOR: build: Add a new define, USE_KTLS.
Olivier Houchard [Fri, 4 Jul 2025 14:27:38 +0000 (16:27 +0200)] 
MINOR: build: Add a new define, USE_KTLS.

Add a new define, USE_KTLS, that will be set for Linux.
It will, however, only compile with a kernel >= 0, so you should compile
with USE_KTLS=0 if you use an older kernel.

47 hours agoMINOR: ssl: Define HAVE_VANILLA_OPENSSL if openssl is used.
Olivier Houchard [Thu, 3 Jul 2025 16:12:19 +0000 (18:12 +0200)] 
MINOR: ssl: Define HAVE_VANILLA_OPENSSL if openssl is used.

If we're using OpenSSL as our crypto library, so add a define,
HAVE_VANILLA_OPENSSL, to make it easier to differentiate between the
various crypto libs.

47 hours agoMINOR: cfgparse: Add a new "ktls" option to bind and server.
Olivier Houchard [Thu, 3 Jul 2025 15:27:36 +0000 (17:27 +0200)] 
MINOR: cfgparse: Add a new "ktls" option to bind and server.

Add a new "ktls" option to bind and server. Valid values are "on" and
"off".
It currently does nothing, but when kTLS will be implemented, it will
enable or disable kTLS for the corresponding sockets.
It is marked as experimental for now.

47 hours agoMEDIUM: mux_h1/mux_pt: Use XPRT_CAN_SPLICE to decide if we should splice
Olivier Houchard [Wed, 13 Aug 2025 13:39:46 +0000 (13:39 +0000)] 
MEDIUM: mux_h1/mux_pt: Use XPRT_CAN_SPLICE to decide if we should splice

In both mux_h1 and mux_pt, use the new XPRT_CAN_SPLICE capability to
decide if we should attempt to use splicing or not.
If we receive XPRT_CONN_CAN_MAYBE_SPLICE, add a new flag on the
connection, CO_FL_WANT_SPLICING, to let the xprt know that we'd love to
be able to do splicing, so that it may get ready for that.
This should have no effect right now, and is required work for adding
kTLS support.

47 hours agoMEDIUM: xprt: Add a "get_capability" method.
Olivier Houchard [Wed, 13 Aug 2025 13:39:26 +0000 (13:39 +0000)] 
MEDIUM: xprt: Add a "get_capability" method.

Add a new method to xprts, get_capability, that can be used to query if
an xprt supports something or not.
The first capability implemented is XPRT_CAN_SPLICE, to know if the xprt
will be able to use splicing for the provided connection.
The possible answers are XPRT_CONN_CAN_NOT_SPLICE, which indicates
splicing will never be possible for that connection,
XPRT_CONN_COULD_SPLICE, which indicates that splicing is not usable
right now, but may be in the future, and XPRT_CONN_CAN_SPLICE, that
means we can splice right away.

47 hours agoMINOR: ssl: Add a "flags" field to ssl_sock_ctx.
Olivier Houchard [Wed, 20 Aug 2025 13:30:48 +0000 (13:30 +0000)] 
MINOR: ssl: Add a "flags" field to ssl_sock_ctx.

Instead of adding more separate fields in ssl_sock_ctx, add a "flags"
one.
Convert the "can_send_early_data" to the flag SSL_SOCK_F_EARLY_ENABLED.
More flags will be added for kTLS support.

47 hours agoMINOR: xprt: Add recvmsg() and sendmsg() parameters to rcv_buf() and snd_buf().
Olivier Houchard [Tue, 17 Jun 2025 14:43:20 +0000 (16:43 +0200)] 
MINOR: xprt: Add recvmsg() and sendmsg() parameters to rcv_buf() and snd_buf().

In rcv_buf() and snd_buf(), use sendmsg/recvmsg instead of send and
recv, and add two new optional parameters to provide msg_control and
msg_controllen.
Those are unused for now, but will be used later for kTLS.

2 days agoBUG/MEDIUM: mworker: more verbose error upon loading failure
William Lallemand [Tue, 19 Aug 2025 14:53:21 +0000 (16:53 +0200)] 
BUG/MEDIUM: mworker: more verbose error upon loading failure

When a worker crashes during its configuration parsing and without
emitting any messages, the master will emit the message "Failed to load
worker!". However that doesn't give us neither the PID of the worker,
nor the status code.

This patch fixes the problem by emitting a more verbose error.

Must be backported as far as 3.1.

2 days agoBUG/MEDIUM: quic-be: do not initialize ->conn too early
Frederic Lecaille [Wed, 20 Aug 2025 13:36:18 +0000 (15:36 +0200)] 
BUG/MEDIUM: quic-be: do not initialize ->conn too early

This bug arrived with this commit:

   BUG/MEDIUM: quic: do not release BE quic-conn prior to upper conn

which added a BUG_ON(qc->conn) statement at the beginning of quic_conn_release().
It is triggered if the connection is not released before releasing the quic_conn.
But this is always the case for a backend quic_conn when its allocation from
qc_new_conn() fails.

Such crashes could be reproduced with -dMfail option. To reach them, the
memory allocations must fail. So, this is relatively rare, except on systems
with limited memory.

To fix this, simply set ->conn quic_conn struct member to a not null value
(the one passed as parameter) after the quic_conn allocation has succeeded.

No backport needed.

2 days agoBUG/MEDIUM: quic: crash after quic_conn allocation failures
Frederic Lecaille [Wed, 20 Aug 2025 12:48:23 +0000 (14:48 +0200)] 
BUG/MEDIUM: quic: crash after quic_conn allocation failures

This regression arrived with this commit:

MINOR: quic-be: QUIC connection allocation adaptation (qc_new_conn())

where qc_new_conn() was modified. The ->cids allocation was moved without
checking if a quic_conn_release() call could lead to crashes due to uninitialized
quic_conn members. Indeed, if qc_new_conn() fails, then quic_conn_release() is
called. This bug could impact both QUIC servers and clients.

Such crashes could be reproduced with -dMfail option. To reach them, the
memory allocations must fail. So, this is relatively rare, except on systems
with limited memory.

This patch ensures all the quic_conn members which could lead to crash
from quic_conn_release() are initialized before any remaining memory allocations
required for the quic_conn.

The <conn_id> variable allocated by the client is no more attached to
the connection during its allocation, but after the ->cids trees is allocated.

No backport needed.

2 days agoBUG/MEDIUM: cli: Report inbuf is no longer full when a line is consumed
Christopher Faulet [Wed, 20 Aug 2025 13:50:37 +0000 (15:50 +0200)] 
BUG/MEDIUM: cli: Report inbuf is no longer full when a line is consumed

When the command line parsing was refactored (20ec1de21 "MAJOR: cli: Refacor
parsing and execution of pipelined commands"), a regression was introduced.
When input data are consumed, information about the applet's input buffer
are no longer updated accordingly to state it is no longer full. So it is
possible to freeze the CLI applet. And a spinning loop may be encountered if
a client shutdown is detected in this state.

The fix is obivous. When data are consumed from the applet's input buffer,
APPCTX_FL_INBLK_FULL flag is removed to notify the input buffer is no longer
full and more data can be sent to the CLI applet.

This patch should fix the issue #3064. It must be backported to 3.2.

2 days agoBUG/MINOR: spoe: Properly detect and skip empty NOTIFY frames
Christopher Faulet [Wed, 20 Aug 2025 13:38:42 +0000 (15:38 +0200)] 
BUG/MINOR: spoe: Properly detect and skip empty NOTIFY frames

Since the SPOE was refactored, the detection of empty NOTIFY frames is
broken. So it is possible to send a NOTIFY frames to an agent with no
message at all. The bug happens because the frame type is now added to the
buffer before the messages encoding. So the buffer is never really empty.

To fix the issue, the condition to detect empty frame was adapted.

This patch must be backported as far as 3.1.

3 days agoMEDIUM: dns: don't call connect to dest socket for AF_INET*
Valentine Krasnobaeva [Wed, 13 Aug 2025 13:48:47 +0000 (15:48 +0200)] 
MEDIUM: dns: don't call connect to dest socket for AF_INET*

When we perform connect call for a datagram socket, used to send DNS requests,
we set for it the default destination address to some given nameserver. Then we
simply use send(), as the destination address is already set. In some usecases
described in GitHub issues #3001 and #2654, this approach becames inefficient,
nameservers change its IP addresses dynamically, this triggers DNS resolution
errors.

To fix this, let's perform the bind() on the wildcard address for the datagram
AF_INET* client socket. Like this we will allocate a port for it. Then let's
use sendto() instead of send().

If the nameserver is local and is listening on the UNIX domain socket, we
continue to use the existed approach (connect() and then send()).

This fixes issues #3001 and #2654.
This may be backported in all stable versions.

8 days 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.

8 days agoBUG/MEDIUM: quic: listener connection stuck during handshakes (OpenSSL 3.5)
Frederic Lecaille [Thu, 14 Aug 2025 09:48:30 +0000 (11:48 +0200)] 
BUG/MEDIUM: quic: listener connection stuck during handshakes (OpenSSL 3.5)

This issue was reported in GH #3071 by @famfo where a wireshark capture
reveals that some handshake could not complete after having received
two Initial packets. This could happen when the packets were parsed
in two times, calling qc_ssl_provide_all_quic_data() two times.

This is due to crypto data stream counter which was incremented two times
from qc_ssl_provide_all_quic_data() (see cstream->rx.offset += data
statement around line 1223 in quic_ssl.c). One time by the callback
which "receives" the crypto data, and on time by qc_ssl_provide_all_quic_data().

Then when parsing the second crypto data frame, the parser detected
that the crypto were already provided.

To fix this, one could comment the code which increment the crypto data
stream counter by <data>. That said, when using the OpenSSL 3.5 QUIC API
one should not modified the crypto data stream outside of the OpenSSL 3.5
QUIC API.

So, this patch stop calling qc_ssl_provide_all_quic_data() and
qc_ssl_provide_quic_data() and only calls qc_ssl_do_hanshake() after
having received some crypto data. In addition to this, as these functions
are no more called when building haproxy against OpenSSL 3.5, this patch
disable their compilations (with #ifndef HAVE_OPENSSL_QUIC).

This patch depends on this previous one:

     MINOR: quic: implement qc_ssl_do_hanshake()

Thank you to @famto for this report.

Must be backported to 3.2.

8 days agoMINOR: quic: implement qc_ssl_do_hanshake()
Frederic Lecaille [Thu, 14 Aug 2025 09:25:00 +0000 (11:25 +0200)] 
MINOR: quic: implement qc_ssl_do_hanshake()

Extract the code in relation with the hanshake SSL API (SSL_do_hanshake()...)
from qc_ssl_provide_quic_data() to implement qc_ssl_do_handshake().

8 days agoCI: Update to actions/checkout@v5
Tim Duesterhus [Wed, 13 Aug 2025 17:13:31 +0000 (19:13 +0200)] 
CI: Update to actions/checkout@v5

No functional change, but we should keep this current.

see 5f4ddb54b05ae0355b1f64c22263a6bc381410df
see 5c923f1869881156bf3a25c9659655ae10f7dbd0

8 days agoMEDIUM: ring: always allocate properly aligned ring structures
Willy Tarreau [Wed, 13 Aug 2025 15:36:18 +0000 (17:36 +0200)] 
MEDIUM: ring: always allocate properly aligned ring structures

The rings were manually padded to place the various areas that compose
them into different cache lines, provided that the allocator returned
a cache-aligned address, which until now was not granted. By now
switching to the aligned API we can finally have this guarantee and
hope for more consistent ring performance between tests. Like previously
the few carefully crafted THREAD_PAD() could simply be replaced by
generic THREAD_ALIGN() that dictate the type's alignment.

This was the last user of THREAD_PAD() by the way.

8 days agoMINOR: server: align server struct to 64 bytes
Willy Tarreau [Wed, 13 Aug 2025 13:07:55 +0000 (15:07 +0200)] 
MINOR: server: align server struct to 64 bytes

Several times recently, it was noticed that some benchmarks would
highly vary depending on the position of certain fields in the server
struct, and this could even vary between runs.

The server struct does have separate areas depending on the user cases
and hot/cold aspect of the members stored there, but the areas are
artificially kept apart using fixed padding instead of real alignment,
which has the first sad effect of artificially inflating the struct,
and the second one of misaligning it.

Now that we have all the necessary tools to keep them aligned, let's
just do it. The struct has shrunk from 4160 to 4032 bytes on 64-bit
systems, 152 of which are still holes or padding.

8 days agoMEDIUM: server: introduce srv_alloc()/srv_free() to alloc/free a server
Willy Tarreau [Wed, 13 Aug 2025 09:52:59 +0000 (11:52 +0200)] 
MEDIUM: server: introduce srv_alloc()/srv_free() to alloc/free a server

It happens that we free servers at various places in the code, both
on error paths and at runtime thanks to the "server delete" feature. In
order to switch to an aligned struct, we'll need to change the calloc()
and free() calls. Let's first spot them and switch them to srv_alloc()
and srv_free() instead of using calloc() and either free() or ha_free().
An easy trap to fall into is that some of them are default-server
entries. The new srv_free() function also resets the pointer like
ha_free() does.

This was done by running the following coccinelle script all over the
code:

  @@
  struct server *srv;
  @@
  (
  - free(srv)
  + srv_free(&srv)
  |
  - ha_free(&srv)
  + srv_free(&srv)
  )
  @@
  struct server *srv;
  expression e1;
  expression e2;
  @@
  (
  - srv = malloc(e1)
  + srv = srv_alloc()
  |
  - srv = calloc(e1, e2)
  + srv = srv_alloc()
  )

This is marked medium because despite spotting all call places, we can
never rule out the possibility that some out-of-tree patches would
allocate their own servers and continue to use the old API... at their
own risk.

8 days agoMINOR: tools: also implement ha_aligned_alloc_typed()
Willy Tarreau [Wed, 13 Aug 2025 15:11:32 +0000 (17:11 +0200)] 
MINOR: tools: also implement ha_aligned_alloc_typed()

This one is a macro and will allocate a properly aligned and sized
object. This will help make sure that the alignment promised to the
compiler is respected.

When memstats is used, the type name is passed as a string into the
.extra field so that it can be displayed in "debug dev memstats". Two
tiny mistakes related to memstats macros were also fixed (calloc
instead of malloc for zalloc), and the doc was also added to document
how to use these calls.

9 days 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
9 days 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.

10 days agoOPTIM: server: start to use aligned allocs in server quic-interop
Willy Tarreau [Mon, 11 Aug 2025 15:43:51 +0000 (17:43 +0200)] 
OPTIM: server: start to use aligned allocs in server

This is currently for per-thread arrays like idle conns etc. We're
now cache-aligning the per-thread arrays so as to put an end to false
sharing. A comparative test between no alignment and alignment on a
simple config with round robin between 4 servers showed an average
rate of 1.75M/s vs 1.72M/s before for 100M requests. The gain seems
to be more commonly less than 1% however. This should mostly help
make measurements more reproducible across multiple runs.

10 days agoOPTIM: connection: align connection pools to 64
Willy Tarreau [Mon, 11 Aug 2025 15:36:39 +0000 (17:36 +0200)] 
OPTIM: connection: align connection pools to 64

The struct connection is used a lot by the muxes during many operations,
particularly at the beginning of the struct (flags, ctrl, xprt and mux).
We definitely want this one not to be falsely shared with another thread,
so let's align the pools to a cache line.

10 days agoOPTIM: queue: align the pendconn pools to 64
Willy Tarreau [Mon, 11 Aug 2025 15:33:55 +0000 (17:33 +0200)] 
OPTIM: queue: align the pendconn pools to 64

This is in order to limit false sharing, because this element is already
ultra-sensitive to sharing and we'd rather limit it as much as possible.

10 days agoOPTIM: buffers: align the buffer pool to 64
Willy Tarreau [Mon, 11 Aug 2025 15:31:08 +0000 (17:31 +0200)] 
OPTIM: buffers: align the buffer pool to 64

This struct is used by memcpy() and friends, particularly during the
early recv() and send(). By keeping it 64-byte aligned, we let the
underlying libs/kernel use optimal operations (e.g.  AVX512) for memory
copies while right now it's just random (buffers are found to be equally
aligned to 32 and 64 in practice).

10 days agoOPTIM: tasks: align task and tasklet pools to 64
Willy Tarreau [Mon, 11 Aug 2025 15:29:04 +0000 (17:29 +0200)] 
OPTIM: tasks: align task and tasklet pools to 64

These structs are intensively used and really must not experience false
sharing, so let's declare them aligned to 64. We don't try to align the
struct themselves, as we don't want the compiler to expand them either.

10 days agoMEDIUM: tree-wide: replace most DECLARE_POOL with DECLARE_TYPED_POOL
Willy Tarreau [Wed, 6 Aug 2025 14:43:27 +0000 (16:43 +0200)] 
MEDIUM: tree-wide: replace most DECLARE_POOL with DECLARE_TYPED_POOL

This will make the pools size and alignment automatically inherit
the type declaration. It was done like this:

   sed -i -e 's:DECLARE_POOL(\([^,]*,[^,]*,\s*\)sizeof(\([^)]*\))):DECLARE_TYPED_POOL(\1\2):g' $(git grep -lw DECLARE_POOL src addons)
   sed -i -e 's:DECLARE_STATIC_POOL(\([^,]*,[^,]*,\s*\)sizeof(\([^)]*\))):DECLARE_STATIC_TYPED_POOL(\1\2):g' $(git grep -lw DECLARE_STATIC_POOL src addons)

81 replacements were made. The only remaining ones are those which set
their own size without depending on a structure. The few ones with an
extra size were manually handled.

It also means that the requested alignments are now checked against the
type's. Given that none is specified for now, no issue is reported.

It was verified with "show pools detailed" that the definitions are
exactly the same, and that the binaries are similar.

10 days agoDOC: api: update the pools API with the alignment and typed declarations
Willy Tarreau [Mon, 11 Aug 2025 17:40:58 +0000 (19:40 +0200)] 
DOC: api: update the pools API with the alignment and typed declarations

This adds the DECLARE_*ALIGNED*() and DECLARE_*TYPED*() macros.

10 days agoMINOR: pools: always check that requested alignment matches the type's
Willy Tarreau [Mon, 11 Aug 2025 14:47:17 +0000 (16:47 +0200)] 
MINOR: pools: always check that requested alignment matches the type's

For pool registrations that are created from the type declaration, we
now have the ability to verify that the requested alignment matches
the type's one. Let's not miss this opportunity, as we've met bugs in
the past that were caused by such mismatches. The principle is simple:
if the type alignment is known, we check that the configured alignment
is at least as large as that one otherwise we refuse to start (since
the code may crash at any moment). Obviously it doesn't crash for now!

10 days agoMINOR: pools: permit to optionally specify extra size and alignment
Willy Tarreau [Mon, 11 Aug 2025 13:51:32 +0000 (15:51 +0200)] 
MINOR: pools: permit to optionally specify extra size and alignment

The common macros REGISTER_TYPED_POOL(), DECLARE_TYPED_POOL() and
DECLARE_STATIC_TYPED_POOL() will now take two optional arguments,
one being the extra size to be added to the structure, and a second
one being the desired alignment to enforce. This will permit to
specify alignments larger than the default ones promised to the
compiler.

10 days agoMINOR: pools: distinguish the requested alignment from the type-specific one
Willy Tarreau [Mon, 11 Aug 2025 13:24:33 +0000 (15:24 +0200)] 
MINOR: pools: distinguish the requested alignment from the type-specific one

We're letting users request an alignment but that can violate one imposed
by a type, especially if we start seeing REGISTER_TYPED_POOL() grow in
adoption, encouraging users to specify alignment on their types. On the
other hand, if we ask the user to always specify the alignment, no control
is possible and the error is easy. Let's have a second field in the pool
registration, for the type-specific one. We'll set it to zero when unknown,
and to the types's alignment when known. This way it will become possible
to compare them at startup time to detect conflicts. For now no macro
permits to set both separately so this is not visible.

10 days agoCLEANUP: fd: make use of ha_aligned_alloc() for the fdtab
Willy Tarreau [Mon, 11 Aug 2025 16:55:09 +0000 (18:55 +0200)] 
CLEANUP: fd: make use of ha_aligned_alloc() for the fdtab

We've forcefully aligned the fdtab in commit 97ea9c49f1 ("BUG/MEDIUM:
fd: always align fdtab[] to 64 bytes"), but now we don't need such hacks
anymore thanks to ha_aligned_alloc(). Let's use it and get rid of
fdtab_addr.

10 days agoMINOR: tools: implement ha_aligned_zalloc()
Willy Tarreau [Mon, 11 Aug 2025 16:46:28 +0000 (18:46 +0200)] 
MINOR: tools: implement ha_aligned_zalloc()

This one is exactly ha_aligned_alloc() followed by a memset(0), as
it will be convenient for a number of call places as a replacement
for calloc().

Note that ideally we should also have a calloc version that performs
basic multiply overflow checks, but these are essentially used with
numbers of threads times small structs so that's fine, and we already
do the same everywhere in malloc() calls.

10 days agoMEDIUM: ssl/cli: relax crt insertion in crt-list of type directory
William Lallemand [Mon, 11 Aug 2025 15:24:11 +0000 (17:24 +0200)] 
MEDIUM: ssl/cli: relax crt insertion in crt-list of type directory

In previous versions of haproxy, insertions of certificates in a
crt-list from the CLI would require to have the path of the directory,
in the path of the certificate. This would help avoiding that the
certificate wasn't loaded upon a reload because it is not at the right
place.

However, since version 3.0 and crt-store, the name stored in the tree
could be an alias and not a path, so that does not make sense anymore.
Even though path would be right, the check is not right anymore in this
case.

The tool or user inserting the certificate must now check itself that
the certificate was placed at the right spot on the filesystem.

Reported in issue #3053.

Could be backported as far as haproxy 3.0.

11 days agoDOC: management: clarify usage of -V with -c
William Lallemand [Mon, 11 Aug 2025 14:19:17 +0000 (16:19 +0200)] 
DOC: management: clarify usage of -V with -c

In ticket #3065 an user complained that no success message is printed
anymore when using -c. The message does not appear by default since
version 2.9. This patch clarify the documentation.

Must be backported as far as 2.8.

11 days 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.

11 days agoMEDIUM: acme: use lowercase for challenge names in configuration
William Lallemand [Mon, 11 Aug 2025 12:53:29 +0000 (14:53 +0200)] 
MEDIUM: acme: use lowercase for challenge names in configuration

Both the RFC and the IANA registry refers to challenge names in
lowercase. If we need to implement more challenges, it's better to
use the correct naming.

In order to keep the compatibility with the previous configurations, the
parsing does a strcasecmp() instead of a strcmp().

Also rename every occurence in the code and doc in lowercase.

This was discussed in issue #1864

13 days 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.

13 days 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.

2 weeks agoCI: vtest: add Ubuntu arm64 builds
Ilia Shipitsin [Fri, 8 Aug 2025 09:41:47 +0000 (11:41 +0200)] 
CI: vtest: add Ubuntu arm64 builds

Reference: https://github.com/actions/partner-runner-images

since GHA now supports arm64 as well, let add those builds. We will
start with ASAN builds, other will be added later if required

2 weeks agoCI: vtest: add os name to OT cache key
Ilia Shipitsin [Fri, 8 Aug 2025 09:41:46 +0000 (11:41 +0200)] 
CI: vtest: add os name to OT cache key

currently OpenTracing cache does not include os name. it does not
allow to distinguish, for example between ubuntu-24.04 and
ubuntu-24.04-arm.

2 weeks agoMINOR: sock: update broken accept4 detection for older hardwares.
David Carlier [Thu, 7 Aug 2025 18:43:39 +0000 (19:43 +0100)] 
MINOR: sock: update broken accept4 detection for older hardwares.

Some older ARM embedded settings set errno to EPERM instead of ENOSYS
for missing implementations (e.g. Freescale ARM 2.6.35)

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.

2 weeks agoBUILD: restore USE_SHM_OPEN build option
Aurelien DARRAGON [Thu, 5 Jun 2025 11:07:42 +0000 (13:07 +0200)] 
BUILD: restore USE_SHM_OPEN build option

Some optional features may still require the use of shm_open() in the
future. In this patch we restore the USE_SHM_OPEN build option that
was removed in 143be1b59 ("MEDIUM: errors: get rid of shm_open()") and
should guard the use of shm_open() in the code.

2 weeks agoMINOR: init: add REGISTER_POST_DEINIT_MASTER() hook
Aurelien DARRAGON [Thu, 26 Jun 2025 15:23:06 +0000 (17:23 +0200)] 
MINOR: init: add REGISTER_POST_DEINIT_MASTER() hook

Similar to REGISTER_POST_DEINIT() hook (which is invoked during deinit)
but for master process only, when haproxy was started in master-worker
mode. The goal is to be able to register cleanup functions that will
only run for the master process right before exiting.

2 weeks agoMINOR: clock: add clock_get_now_offset() helper
Aurelien DARRAGON [Thu, 7 Aug 2025 13:28:59 +0000 (15:28 +0200)] 
MINOR: clock: add clock_get_now_offset() helper

Same as clock_set_now_offset() but to retrieve the offset from external
location.

2 weeks agoMINOR: clock: add clock_set_now_offset() helper
Aurelien DARRAGON [Thu, 26 Jun 2025 17:21:36 +0000 (19:21 +0200)] 
MINOR: clock: add clock_set_now_offset() helper

Since now_offset is a static variable and is not exposed outside from
clock.c, let's add an helper so that it becomes possible to set its
value from another source file.

2 weeks agoMINOR: guid: add guid_count() function
Aurelien DARRAGON [Tue, 15 Apr 2025 10:40:17 +0000 (12:40 +0200)] 
MINOR: guid: add guid_count() function

returns the total amount of registered GUIDs in the guid_tree

2 weeks agoMINOR: guid: add guid_get() helper
Aurelien DARRAGON [Mon, 14 Apr 2025 13:05:23 +0000 (15:05 +0200)] 
MINOR: guid: add guid_get() helper

guid_get() is a convenient function to get the actual key string
associated to a given guid_node struct

2 weeks agoBUG/MINOR: proxy: avoid NULL-deref in post_section_px_cleanup()
Aurelien DARRAGON [Thu, 7 Aug 2025 11:04:26 +0000 (13:04 +0200)] 
BUG/MINOR: proxy: avoid NULL-deref in post_section_px_cleanup()

post_section_px_cleanup(), which was implemented in abcc73830
("MEDIUM: proxy: register a post-section cleanup function"), is called
for the current section no matter if the parsing was aborted due to
a fatal error. In this case, the curproxy pointer may point to NULL,
yet post_section_px_cleanup() assumes curproxy pointer is always valid,
which could lead to NULL-deref.

For instance, the config below will cause SEGFAULT:

  listen toto titi

To fix the issue, let's simply consider that the curproxy pointer may
be NULL in post_section_px_cleanup(), in which case we skip the cleanup
for the curproxy since there is nothing we can do.

No backport needed

2 weeks agoBUG/MINOR: cfgparse-listen: update err_code for fatal error on proxy directive
Aurelien DARRAGON [Thu, 7 Aug 2025 10:45:58 +0000 (12:45 +0200)] 
BUG/MINOR: cfgparse-listen: update err_code for fatal error on proxy directive

When improper arguments are provided on proxy directive (listen,
frontend or backend), such alert may be emitted:

  "please use the 'bind' keyword for listening addresses"

This was introduced in 6e62fb6405 ("MEDIUM: cfgparse: check section
maximum number of arguments"). However, despite the error being reported
as alert, the err_code isn't updated accordingly, which could make the
upper parser think there was no error, while it isn't the case.

In practise since the proxy directive is ignored following proxy related
directives should raise errors, so this didn't cause much harm, yet
better fix that.

It could be backported to all stable versions.

2 weeks agoBUG/MINOR: cfgparse: immediately stop after hard error in srv_init()
Aurelien DARRAGON [Wed, 30 Jul 2025 13:10:27 +0000 (15:10 +0200)] 
BUG/MINOR: cfgparse: immediately stop after hard error in srv_init()

Since 368d01361 (" MEDIUM: server: add and use srv_init() function"), in
case of srv_init() error, we simply increment cfgerr variable and keep
going.

It isn't enough, some treatment occuring later in check_config_validity()
assume that srv_init() succeeded for servers, and may cause undefined
behavior. To fix the issue, let's consider that if (srv_init() & ERR_CODE)
returns true, then we must stop checking the config immediately.

No backport needed unless 368d01361 is.

2 weeks agoMINOR: quic: prefer qc_is_back() usage over qc->target
Amaury Denoyelle [Wed, 6 Aug 2025 14:19:38 +0000 (16:19 +0200)] 
MINOR: quic: prefer qc_is_back() usage over qc->target

Previously quic_conn <target> member was used to determine if quic_conn
was used on the frontend (as server) or backend side (as client). A new
helper function can now be used to directly check flag
QUIC_FL_CONN_IS_BACK.

This reduces the dependency between quic_conn and their relative
listener/server instances.

2 weeks agoMINOR: quic: define QUIC_FL_CONN_IS_BACK flag
Amaury Denoyelle [Tue, 5 Aug 2025 08:18:42 +0000 (10:18 +0200)] 
MINOR: quic: define QUIC_FL_CONN_IS_BACK flag

Define a new quic_conn flag assign if the connection is used on the
backend side. This is similar to other haproxy components such as struct
connection and muxes element.

This flag is positionned via qc_new_conn(). Also update quic traces to
mark proxy side as 'F' or 'B' suffix.

2 weeks agoMINOR: quic: duplicate GSO unsupp status from listener to conn
Amaury Denoyelle [Wed, 6 Aug 2025 14:34:35 +0000 (16:34 +0200)] 
MINOR: quic: duplicate GSO unsupp status from listener to conn

QUIC emission can use GSO to emit multiple datagrams with a single
syscall invokation. However, this feature relies on several kernel
parameters which are checked on haproxy process startup.

Even if these checks report no issue, GSO may still be unable due to the
underlying network adapter underneath. Thus, if a EIO occured on
sendmsg() with GSO, listener is flagged to mark GSO as unsupported. This
allows every other QUIC connections to share the status and avoid using
GSO when using this listener.

Previously, listener flag was checked for every QUIC emission. This was
done using an atomic operation to prevent races. Improve this by
duplicating GSO unsupported status as the connection level. This is done
on qc_new_conn() and also on thread rebinding if a new listener instance
is used.

The main benefit from this patch is to reduce the dependency between
quic_conn and listener instances.

2 weeks ago[RELEASE] Released version 3.3-dev6 v3.3-dev6
Willy Tarreau [Wed, 6 Aug 2025 19:50:00 +0000 (21:50 +0200)] 
[RELEASE] Released version 3.3-dev6

Released version 3.3-dev6 with the following main changes :
    - MINOR: acme: implement traces
    - BUG/MINOR: hlua: take default-path into account with lua-load-per-thread
    - CLEANUP: counters: rename counters_be_shared_init to counters_be_shared_prepare
    - MINOR: clock: make global_now_ms a pointer
    - MINOR: clock: make global_now_ns a pointer as well
    - MINOR: mux-quic: release conn after shutdown on BE reuse failure
    - MINOR: session: strengthen connection attach to session
    - MINOR: session: remove redundant target argument from session_add_conn()
    - MINOR: session: strengthen idle conn limit check
    - MINOR: session: do not release conn in session_check_idle_conn()
    - MINOR: session: streamline session_check_idle_conn() usage
    - MINOR: muxes: refactor private connection detach
    - BUG/MEDIUM: mux-quic: ensure Early-data header is set
    - BUILD: acme: avoid declaring TRACE_SOURCE in acme-t.h
    - MINOR: acme: emit a log for DNS-01 challenge response
    - MINOR: acme: emit the DNS-01 challenge details on the dpapi sink
    - MEDIUM: acme: allow to wait and restart the task for DNS-01
    - MINOR: acme: update the log for DNS-01
    - BUG/MINOR: acme: possible integer underflow in acme_txt_record()
    - BUG/MEDIUM: hlua_fcn: ensure systematic watcher cleanup for server list iterator
    - MINOR: sample: Add le2dec (little endian to decimal) sample fetch
    - BUILD: fcgi: fix the struct name of fcgi_flt_ctx
    - BUILD: compat: provide relaxed versions of the MIN/MAX macros
    - BUILD: quic: use _MAX() to avoid build issues in pools declarations
    - BUILD: compat: always set _POSIX_VERSION to ease comparisons
    - MINOR: implement ha_aligned_alloc() to return aligned memory areas
    - MINOR: pools: support creating a pool from a pool registration
    - MINOR: pools: add a new flag to declare static registrations
    - MINOR: pools: force the name at creation time to be a const.
    - MEDIUM: pools: change the static pool creation to pass a registration
    - DEBUG: pools: store the pool registration file name and line number
    - DEBUG: pools: also retrieve file and line for direct callers of create_pool()
    - MEDIUM: pools: add an alignment property
    - MINOR: pools: add macros to register aligned pools
    - MINOR: pools: add macros to declare pools based on a struct type
    - MEDIUM: pools: respect pool alignment in allocations

2 weeks agoMEDIUM: pools: respect pool alignment in allocations
Willy Tarreau [Tue, 5 Aug 2025 16:12:18 +0000 (18:12 +0200)] 
MEDIUM: pools: respect pool alignment in allocations

Now pool_alloc_area() takes the alignment in argument and makes use
of ha_aligned_malloc() instead of malloc(). pool_alloc_area_uaf()
simply applies the alignment before returning the mapped area. The
pool_free() functionn calls ha_aligned_free() so as to permit to use
a specific API for aligned alloc/free like mingw requires.

Note that it's possible to see warnings about mismatching sized
during pool_free() since we know both the pool and the type. In
pool_free, adding just this is sufficient to detect potential
offenders:

WARN_ON(__alignof__(*__ptr) > pool->align);

2 weeks agoMINOR: pools: add macros to declare pools based on a struct type
Willy Tarreau [Wed, 6 Aug 2025 14:33:27 +0000 (16:33 +0200)] 
MINOR: pools: add macros to declare pools based on a struct type

DECLARE_TYPED_POOL() and friends take a name, a type and an extra
size (to be added to the size of the element), and will use this
to create the pool. This has the benefit of letting the compiler
automatically adapt sizeof() and alignof() based on the type
declaration.

2 weeks agoMINOR: pools: add macros to register aligned pools
Willy Tarreau [Tue, 5 Aug 2025 16:26:37 +0000 (18:26 +0200)] 
MINOR: pools: add macros to register aligned pools

This adds an alignment argument to create_pool_from_loc() and
completes the existing low-level macros with new ones that expose
the alignment and the new macros permit to specify it. For now
they're not used.

2 weeks agoMEDIUM: pools: add an alignment property
Willy Tarreau [Tue, 5 Aug 2025 16:03:09 +0000 (18:03 +0200)] 
MEDIUM: pools: add an alignment property

This will be used to declare aligned pools. For now it's not used,
but it's properly set from the various registrations that compose
a pool, and rounded up to the next power of 2, with a minimum of
sizeof(void*).

The alignment is returned in the "show pools" part that indicates
the entry size. E.g. "(56 bytes/8)" means 56 bytes, aligned by 8.

2 weeks agoDEBUG: pools: also retrieve file and line for direct callers of create_pool()
Willy Tarreau [Wed, 6 Aug 2025 07:50:42 +0000 (09:50 +0200)] 
DEBUG: pools: also retrieve file and line for direct callers of create_pool()

Just like previous patch, we want to retrieve the location of the caller.
For this we turn create_pool() into a macro that collects __FILE__ and
__LINE__ and passes them to the now renamed function create_pool_with_loc().

Now the remaining ~30 pools also have their location stored.

2 weeks agoDEBUG: pools: store the pool registration file name and line number
Willy Tarreau [Wed, 6 Aug 2025 07:43:39 +0000 (09:43 +0200)] 
DEBUG: pools: store the pool registration file name and line number

When pools are declared using DECLARE_POOL(), REGISTER_POOL etc, we
know where they are and it's trivial to retrieve the file name and line
number, so let's store them in the pool_registration, and display them
when known in "show pools detailed".

2 weeks agoMEDIUM: pools: change the static pool creation to pass a registration
Willy Tarreau [Tue, 5 Aug 2025 16:59:15 +0000 (18:59 +0200)] 
MEDIUM: pools: change the static pool creation to pass a registration

Now we're creating statically allocated registrations instead of
passing all the parameters and allocating them on the fly. Not only
this is simpler to extend (we're limited in number of INITCALL args),
but it also leaves all of these in the data segment where they are
easier to find when debugging.

2 weeks agoMINOR: pools: force the name at creation time to be a const.
Willy Tarreau [Tue, 5 Aug 2025 17:07:47 +0000 (19:07 +0200)] 
MINOR: pools: force the name at creation time to be a const.

This is already the case as all names are constant so that's fine. If
it would ever change, it's not very hard to just replace it in-situ
via an strdup() and set a flag to mention that it's dynamically
allocated. We just don't need this right now.

One immediately visible effect is in "show pools detailed" where the
names are no longer truncated.

2 weeks agoMINOR: pools: add a new flag to declare static registrations
Willy Tarreau [Tue, 5 Aug 2025 16:46:34 +0000 (18:46 +0200)] 
MINOR: pools: add a new flag to declare static registrations

We must not free these ones when destroying a pool, so let's dedicate
them a flag to mention that they are static. For now we don't have any
such.

2 weeks agoMINOR: pools: support creating a pool from a pool registration
Willy Tarreau [Tue, 5 Aug 2025 16:40:21 +0000 (18:40 +0200)] 
MINOR: pools: support creating a pool from a pool registration

We've recently introduced pool registrations to be able to enumerate
all pool creation requests with their respective parameters, but till
now they were only used for debugging ("show pools detailed"). Let's
go a step further and split create_pool() in two:
  - the first half only allocates and sets the pool registration
  - the second half creates the pool from the registration

This is what this patch does. This now opens the ability to pre-create
registrations and create pools directly from there.

2 weeks agoMINOR: implement ha_aligned_alloc() to return aligned memory areas
Willy Tarreau [Thu, 31 Jul 2025 13:26:58 +0000 (15:26 +0200)] 
MINOR: implement ha_aligned_alloc() to return aligned memory areas

We have two versions, _safe() which verifies and adjusts alignment,
and the regular one which trusts the caller. There's also a dedicated
ha_aligned_free() due to mingw.

The currently detected OSes are mingw, unixes older than POSIX 200112
which require memalign(), and those post 200112 which will use
posix_memalign(). Solaris 10 reports 200112 (probably through
_GNU_SOURCE since it does not do it by default), and Solaris 11 still
supports memalign() so for all Solaris we use memalign(). The memstats
wrappers are also implemented, and have the exported names. This was
the opportunity for providing a separate free call that lets the caller
specify the size (e.g. for use with pools).

For now this code is not used.

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.

2 weeks agoBUILD: quic: use _MAX() to avoid build issues in pools declarations
Willy Tarreau [Wed, 6 Aug 2025 17:10:11 +0000 (19:10 +0200)] 
BUILD: quic: use _MAX() to avoid build issues in pools declarations

With the upcoming pool declaration, we're filling a struct's fields,
while older versions were relying on initcalls which could be turned
to function declarations. Thus the compound expressions that were
usable there are not necessarily anymore, as witnessed here with
gcc-5.5 on solaris 10:

      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 make the macro use _MAX() instead of MAX() since it relies on pure
constants.

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.

2 weeks agoBUILD: fcgi: fix the struct name of fcgi_flt_ctx
Willy Tarreau [Wed, 6 Aug 2025 14:25:00 +0000 (16:25 +0200)] 
BUILD: fcgi: fix the struct name of fcgi_flt_ctx

The struct was mistakenly spelled flt_fcgi_ctx() in fcgi_flt_stop()
when it was introduced in 2.1 with commit 78fbb9f991 ("MEDIUM:
fcgi-app: Add FCGI application and filter"), causing build issues
when trying to get the alignment of the object in pool_free() for
debugging purposes. No backport is needed as it's just used to convey
a pointer.

2 weeks agoMINOR: sample: Add le2dec (little endian to decimal) sample fetch
Alexander Stephan [Fri, 14 Mar 2025 11:17:09 +0000 (11:17 +0000)] 
MINOR: sample: Add le2dec (little endian to decimal) sample fetch

This commit introduces a sample fetch, `le2dec`, to convert
little-endian binary input samples into their decimal representations.
The function converts the input into a string containing unsigned
integer numbers, with each number derived from a specified number of
input bytes. The numbers are separated using a user-defined separator.

This new sample is achieved by adding a parametrized sample_conv_2dec
function, unifying the logic for be2dec and le2dec converters.

Co-authored-by: Christian Norbert Menges <christian.norbert.menges@sap.com>
[wt: tracked as GH issue #2915]
Signed-off-by: Willy Tarreau <w@1wt.eu>
2 weeks agoBUG/MEDIUM: hlua_fcn: ensure systematic watcher cleanup for server list iterator
Aurelien DARRAGON [Fri, 1 Aug 2025 13:33:56 +0000 (15:33 +0200)] 
BUG/MEDIUM: hlua_fcn: ensure systematic watcher cleanup for server list iterator

In 358166a ("BUG/MINOR: hlua_fcn: restore server pairs iterator pointer
consistency"), I wrongly assumed that because the iterator was a temporary
object, no specific cleanup was needed for the watcher.

In fact watcher_detach() is not only relevant for the watcher itself, but
especially for its parent list to remove the current watcher from it.

As iterators are temporary objects, failing to remove their watchers from
the server watcher list causes the server watcher list to be corrupted.

On a normal iteration sequence, the last watcher_next() receives NULL
as target so it successfully detaches the last watcher from the list.
However the corner case here is with interrupted iterators: users are
free to break away from the iteration loop when a specific condition is
met for instance from the lua script, when this happens
hlua_listable_servers_pairs_iterator() doesn't get a chance to detach the
last iterator.

Also, Lua doesn't tell us that the loop was interrupted,
so to fix the issue we rely on the garbage collector to force a last
detach right before the object is freed. To achieve that, watcher_detach()
was slightly modified so that it becomes possible to call it without
knowing if the watcher is already detached or not, if watcher_detach() is
called on a detached watcher, the function does nothing. This way it saves
the caller from having to track the watcher state and makes the API a
little more convenient to use. This way we now systematically call
watcher_detach() for server iterators right before they are garbage
collected.

This was first reported in GH #3055. It can be observed when the server
list is browsed one than more time when it was already browsed from Lua
for a given proxy and the iteration was interrupted before the end. As the
watcher list is corrupted, the common symptom is watcher_attach() or
watcher_next() not ending due to the internal mt_list call looping
forever.

Thanks to GH users @sabretus and @sabretus for their precious help.

It should be backported everywhere 358166a was.

2 weeks agoBUG/MINOR: acme: possible integer underflow in acme_txt_record()
William Lallemand [Sun, 3 Aug 2025 11:51:44 +0000 (13:51 +0200)] 
BUG/MINOR: acme: possible integer underflow in acme_txt_record()

a2base64url() can return a negative value is olen is too short to
accept ilen. This is not supposed to happen since the sha256 should
always fit in a buffer. But this is confusing since a2base64()
returns a signed integer which is pt in output->data which is unsigned.

Fix the issue by setting ret to 0 instead of -1 upon error. And returns
a unsigned integer instead of a signed one.
This patch also checks the return value from the caller in order
to emit an error instead of setting trash.data which is already done
from the function.

2 weeks agoMINOR: acme: update the log for DNS-01
William Lallemand [Fri, 1 Aug 2025 16:08:43 +0000 (18:08 +0200)] 
MINOR: acme: update the log for DNS-01

Update the log for DNS-01 by mentionning the challenge_ready command
over the CLI.

2 weeks agoMEDIUM: acme: allow to wait and restart the task for DNS-01
William Lallemand [Fri, 1 Aug 2025 15:57:29 +0000 (17:57 +0200)] 
MEDIUM: acme: allow to wait and restart the task for DNS-01

DNS-01 needs a external process which would register a TXT record on a
DNS provider, using a REST API or something else.

To achieve this, the process should read the dpapi sink and wait for
events. With the DNS-01 challenge, HAProxy will put the task to sleep
before asking the ACME server to achieve the challenge. The task then
need to be woke up, using the command implemented by this patch.

This patch implements the "acme challenge_ready" command which should be
used by the agent once the challenge was configured in order to wake the
task up.

Example:
    echo "@1 acme challenge_ready foobar.pem.rsa domain kikyo" | socat /tmp/master.sock -

3 weeks agoMINOR: acme: emit the DNS-01 challenge details on the dpapi sink
William Lallemand [Fri, 1 Aug 2025 14:25:57 +0000 (16:25 +0200)] 
MINOR: acme: emit the DNS-01 challenge details on the dpapi sink

This commit adds a new message to the dpapi sink which is emitted during
the new authorization request.

One message is emitted by challenge to resolve. The certificate name as
well as the thumprint of the account key are on the first line of the
message. A dump of the JSON response for 1 challenge is dumped, en the
message ends with a \0.

The agent consuming these messages MUST NOT access the URLs, and SHOULD
only uses the thumbprint, dns and token to configure a challenge.

Example:

    $ ( echo "@@1 show events dpapi -w -0"; cat - ) | socat /tmp/master.sock -  | cat -e
    <0>2025-08-01T16:23:14.797733+02:00 acme deploy foobar.pem.rsa thumbprint Gv7pmGKiv_cjo3aZDWkUPz5ZMxctmd-U30P2GeqpnCo$
    {$
       "status": "pending",$
       "identifier": {$
          "type": "dns",$
          "value": "foobar.com"$
       },$
       "challenges": [$
          {$
             "type": "dns-01",$
             "url": "https://0.0.0.0:14000/chalZ/1o7sxLnwcVCcmeriH1fbHJhRgn4UBIZ8YCbcrzfREZc",$
             "token": "tvAcRXpNjbgX964ScRVpVL2NXPid1_V8cFwDbRWH_4Q",$
             "status": "pending"$
          },$
          {$
             "type": "dns-account-01",$
             "url": "https://0.0.0.0:14000/chalZ/z2_WzibwTPvE2zzIiP3BF0zNy3fgpU_8Nj-V085equ0",$
             "token": "UedIMFsI-6Y9Nq3oXgHcG72vtBFWBTqZx-1snG_0iLs",$
             "status": "pending"$
          },$
          {$
             "type": "tls-alpn-01",$
             "url": "https://0.0.0.0:14000/chalZ/AHnQcRvZlFw6e7F6rrc7GofUMq7S8aIoeDileByYfEI",$
             "token": "QhT4ejBEu6ZLl6pI1HsOQ3jD9piu__N0Hr8PaWaIPyo",$
             "status": "pending"$
          },$
          {$
             "type": "http-01",$
             "url": "https://0.0.0.0:14000/chalZ/Q_qTTPDW43-hsPW3C60NHpGDm_-5ZtZaRfOYDsK3kY8",$
             "token": "g5Y1WID1v-hZeuqhIa6pvdDyae7Q7mVdxG9CfRV2-t4",$
             "status": "pending"$
          }$
       ],$
       "expires": "2025-08-01T15:23:14Z"$
    }$
    ^@

3 weeks agoMINOR: acme: emit a log for DNS-01 challenge response
William Lallemand [Fri, 1 Aug 2025 14:04:12 +0000 (16:04 +0200)] 
MINOR: acme: emit a log for DNS-01 challenge response

This commit emits a log which output the TXT entry to create in case of
DNS-01. This is useful in cases you want to update your TXT entry
manually.

Example:

    acme: foobar.pem.rsa: DNS-01 requires to set the "acme-challenge.example.com" TXT record to "7L050ytWm6ityJqolX-PzBPR0LndHV8bkZx3Zsb-FMg"

3 weeks agoBUILD: acme: avoid declaring TRACE_SOURCE in acme-t.h
William Lallemand [Thu, 31 Jul 2025 14:03:28 +0000 (16:03 +0200)] 
BUILD: acme: avoid declaring TRACE_SOURCE in acme-t.h

Files ending with '-t.h' are supposed to be used for structure
definitions and could be included in the same file to check API
definitions.

This patch removes TRACE_SOURCE from acme-t.h to avoid conflicts with
other TRACE_SOURCE definitions.

3 weeks agoBUG/MEDIUM: mux-quic: ensure Early-data header is set
Amaury Denoyelle [Thu, 31 Jul 2025 09:51:24 +0000 (09:51 +0000)] 
BUG/MEDIUM: mux-quic: ensure Early-data header is set

QUIC MUX may be initialized prior to handshake completion, when 0-RTT is
used. In this case, connection is flagged with CO_FL_EARLY_SSL_HS, which
is notably used by wait-for-hs http rule.

Early data may be subject to replay attacks. For this reason, haproxy
adds the header 'Early-data: 1' to all requests handled as TLS early
data. Thus the server can reject it if it is deemed unsafe. This header
injection is implemented by http-ana. However, it was not functional
with QUIC due to missing CO_FL_EARLY_DATA connection flag.

Fix this by ensuring that QUIC MUX sets CO_FL_EARLY_DATA when needed.
This is performed during qcc_recv() for STREAM frame reception. It is
only set if QC_CF_WAIT_HS is set, meaning that the handshake is not yet
completed. After this, the request is considered safe and Early-data
header is not necessary anymore.

This should fix github issue #3054.

This must be backported up to 3.2 at least. If possible, it should be
backported to all stable releases as well. On these versions, the
current patch relies on the following refactoring commit :
  commit 0a53a008d032b69377869c8caaec38f81bdd5bd6
  MINOR: mux-quic: refactor wait-for-handshake support

3 weeks agoMINOR: muxes: refactor private connection detach
Amaury Denoyelle [Wed, 30 Jul 2025 14:13:42 +0000 (16:13 +0200)] 
MINOR: muxes: refactor private connection detach

Following the latest adjustment on session_add_conn() /
session_check_idle_conn(), detach muxes callbacks were rewritten for
private connection handling.

Nothing really fancy here : some more explicit comments and the removal
of a duplicate checks on idle conn status for muxes with true
multipexing support.

3 weeks agoMINOR: session: streamline session_check_idle_conn() usage
Amaury Denoyelle [Wed, 30 Jul 2025 09:56:05 +0000 (11:56 +0200)] 
MINOR: session: streamline session_check_idle_conn() usage

session_check_idle_conn() is called by muxes when a connection becomes
idle. It ensures that the session idle limit is not yet reached. Else,
the connection is removed from the session and it can be freed.

Prior to this patch, session_check_idle_conn() was compatible with a
NULL session argument. In this case, it would return true, considering
that no limit was reached and connection not removed.

However, this renders the function error-prone and subject to future
bugs. This patch streamlines it by ensuring it is never called with a
NULL argument. Thus it can now only returns true if connection is kept
in the session or false if it was removed, as first intended.

3 weeks agoMINOR: session: do not release conn in session_check_idle_conn()
Amaury Denoyelle [Thu, 24 Jul 2025 09:29:50 +0000 (11:29 +0200)] 
MINOR: session: do not release conn in session_check_idle_conn()

session_check_idle_conn() is called to flag a connection already
inserted in a session list as idle. If the session limit on the number
of idle connections (max-session-srv-conns) is exceeded, the connection
is removed from the session list.

In addition to the connection removal, session_check_idle_conn()
directly calls MUX destroy callback on the connection. This means the
connection is freed by the function itself and should not be used by the
caller anymore.

This is not practical when an alternative connection closure method
should be used, such as a graceful shutdown with QUIC. As such, remove
MUX destroy invokation : this is now the responsability of the caller to
either close or release immediately the connection.

3 weeks agoMINOR: session: strengthen idle conn limit check
Amaury Denoyelle [Wed, 30 Jul 2025 07:55:37 +0000 (09:55 +0200)] 
MINOR: session: strengthen idle conn limit check

Add a BUG_ON() on session_check_idle_conn() to ensure the connection is
not already flagged as CO_FL_SESS_IDLE.

This checks that this function is only called one time per connection
transition from active to idle. This is necessary to ensure that session
idle counter is only incremented one time per connection.

3 weeks agoMINOR: session: remove redundant target argument from session_add_conn()
Amaury Denoyelle [Thu, 24 Jul 2025 09:53:13 +0000 (11:53 +0200)] 
MINOR: session: remove redundant target argument from session_add_conn()

session_add_conn() uses three argument : connection and session
instances, plus a void pointer labelled as target. Typically, it
represents the server, but can also be a backend instance (for example
on dispatch).

In fact, this argument is redundant as <target> is already a member of
the connection. This commit simplifies session_add_conn() by removing
it. A BUG_ON() on target is extended to ensure it is never NULL.

3 weeks agoMINOR: session: strengthen connection attach to session
Amaury Denoyelle [Wed, 23 Jul 2025 08:03:51 +0000 (10:03 +0200)] 
MINOR: session: strengthen connection attach to session

This commit is the first one of a serie to refactor insertion of backend
private connection into the session list.

session_add_conn() is used to attach a connection into a session list.
Previously, this function would report an error if the connection
specified was already attached to another session. However, this case
currently never happens and thus can be considered as buggy.

Remove this check and replace it with a BUG_ON(). This allows to ensure
that session insertion remains consistent. The same check is also
transformed in session_check_idle_conn().

3 weeks agoMINOR: mux-quic: release conn after shutdown on BE reuse failure
Amaury Denoyelle [Wed, 30 Jul 2025 07:51:21 +0000 (09:51 +0200)] 
MINOR: mux-quic: release conn after shutdown on BE reuse failure

On stream detach on backend side, connection is inserted in the proper
server/session list to be able to reuse it later. If insertion fails and
the connection is idle, the connection can be removed immediately.

If this occurs on a QUIC connection, QUIC MUX implements graceful
shutdown to ensure the server is notified of the closure. However, the
connection instance is not freed. Change this to ensure that both
shutdown and release is performed.

3 weeks agoMINOR: clock: make global_now_ns a pointer as well
Aurelien DARRAGON [Thu, 26 Jun 2025 10:58:07 +0000 (12:58 +0200)] 
MINOR: clock: make global_now_ns a pointer as well

Similar to previous commit but for global_now_ns

3 weeks agoMINOR: clock: make global_now_ms a pointer
Aurelien DARRAGON [Fri, 30 May 2025 10:04:53 +0000 (12:04 +0200)] 
MINOR: clock: make global_now_ms a pointer

This is preparation work for shared counters between co-processes. As
co-processes will need to share a common date. global_now_ms will be used
for that as it will point to the shm when sharing is enabled.

Thus in this patch we turn global_now_ms into a pointer (and adjust the
places where it is written to and read from, hopefully atomic operations
through pointer are already used so the change is trivial)

For now global_now_ms points to process-local _global_now_ms which is a
fallback for when sharing through the shm is not enabled.

3 weeks agoCLEANUP: counters: rename counters_be_shared_init to counters_be_shared_prepare
Aurelien DARRAGON [Tue, 29 Jul 2025 12:16:05 +0000 (14:16 +0200)] 
CLEANUP: counters: rename counters_be_shared_init to counters_be_shared_prepare

75e480d10 ("MEDIUM: stats: avoid 1 indirection by storing the shared
stats directly in counters struct") took care of renaming
counters_fe_shared_init() but we forgot counters_be_shared_init().

Let's fix that for consistency

3 weeks agoBUG/MINOR: hlua: take default-path into account with lua-load-per-thread
Aurelien DARRAGON [Mon, 28 Jul 2025 18:14:53 +0000 (20:14 +0200)] 
BUG/MINOR: hlua: take default-path into account with lua-load-per-thread

As discussed in GH #3051, default-path is not taken into account when
loading files using lua-load-per-thread. In fact, the initial
hlua_load_state() (performed on first thread which parses the config)
is successful, but other threads run hlua_load_state() later based
on config hints which were saved by the first thread, and those config
hints only contain the file path provided on the lua-load-per-thread
config line, not the absolute one. Indeed, `default-path` directive
changes the current working directory only for the thread parsing the
configuration.

To fix the issue, when storing config hints under hlua_load_per_thread()
we now make sure to save the absolute file path for `lua-load-per-thread'
argument.

Thanks to GH user @zhanhb for having reported the issue

It may be backported to all stable versions.