]> git.ipfire.org Git - thirdparty/haproxy.git/log
thirdparty/haproxy.git
3 weeks agoBUG/MEDIUM: mux-h2: Report RST/error to app-layer stream during 0-copy fwding
Christopher Faulet [Tue, 9 Sep 2025 13:52:34 +0000 (15:52 +0200)] 
BUG/MEDIUM: mux-h2: Report RST/error to app-layer stream during 0-copy fwding

In h2_nego_ff(), it is important to report reset and error to app-layer
stream and to send the RST-STREAM frame accordingly. It is not clear if it
is an issue or not. But it is clearly a difference with the classical
forwarding via h2_snd_buf. And it is mandatory for the next fix.

This patch should be backported to 3.2. But is is probably a good idea to
not backport it on older versions, except if a bug is reported in this area.

3 weeks agoBUG/MINOR: mux-h2: Remove H2_CF_DEM_DFULL flags when the demux buffer is reset
Christopher Faulet [Tue, 9 Sep 2025 13:46:30 +0000 (15:46 +0200)] 
BUG/MINOR: mux-h2: Remove H2_CF_DEM_DFULL flags when the demux buffer is reset

This only happens when a connection error is detected or when the H2
connection is in ERR/ERR2 state. The demux buffer is explicitly reset. In
that case, it is important to remove the flag reporting this buffer as full.

It is probably worth to backport this patch to 3.2. But it is not mandatory
on older versions because it does not fix any known issue.

3 weeks agoBUG/MEDIUM: mux-h2: Restart reading when mbuf ring is no longer full
Christopher Faulet [Tue, 9 Sep 2025 13:40:01 +0000 (15:40 +0200)] 
BUG/MEDIUM: mux-h2: Restart reading when mbuf ring is no longer full

When the mbuf ring buffer is full, the flag H2_CF_DEM_MROOM is set on the H2
connection to block any demux. It is important to properly handle ACK
frames. However, we must take care to restart reading when some data were
removed from the mbuf. Otherwise, we may block the demux for no reason. It
is especially an issue if the demux buffer is full. In that case, the H2
connection is blocked, waiting for the timeout.

This patch should be backported to 3.2. But is is probably a good idea to
not backport it on older versions, except if a bug is reported in this area.

3 weeks agoBUG/MEDIUM: mux-h2; Don't block reveives in H2_CS_ERROR and H2_CS_ERROR2 states
Christopher Faulet [Tue, 9 Sep 2025 13:30:59 +0000 (15:30 +0200)] 
BUG/MEDIUM: mux-h2; Don't block reveives in H2_CS_ERROR and H2_CS_ERROR2 states

The H2 connection is switched to ERR when a GOAWAY must be sent and in ERR2
when it is sent. In these states, no more data can be emitted by the
mux. But there is no reason to not try to process incoming data or to not
try to receive data. It is espcially important to be able to get the
shutdown from the TCP connection when a SSL connection was previously
detected. Otherwise, it is possible to block a H2 connection until its
timeout expiration to be able to close it.

This patch should be backported to 3.2. But is is probably a good idea to
not backport it on older versions, except if a bug is reported in this
area.

3 weeks agoBUG/MEDIUM: mux-h2: Reset MUX blocking flags when a send error is caught
Christopher Faulet [Tue, 9 Sep 2025 05:55:01 +0000 (07:55 +0200)] 
BUG/MEDIUM: mux-h2: Reset MUX blocking flags when a send error is caught

When an send error is detected on the underlying connection, a pending error
is reported to the H2 connection by setting H2_CF_ERR_PENDING flag. When
this happen the tail of the mux ring buffer is reset. However some blocking
flags remain set and have no chance to be removed later because of the
pending error. Especially the flag H2_CF_DEM_MROOM which block data
demultiplexing. Thus, it is possible to block a H2 connection with unparsed
incoming data.

Worse, if a read event is received, it could lead to a wakeup loop between
the H2 connection and the underlying SSL connection. The H2 connection is
unable to convert the pending error to a fatal error because the
demultiplexing is blocked. In the mean time, it tries to receive more data
because of the not-consumed read event. On the underlying connection side,
the error detected earlier blocks the read, but the H2 connection is woken
up to handle the error.

To fix the issue, blocking flags must be removed when a send error is caught,
H2_CF_MUX_MFULL and H2_CF_DEM_MROOM flags. But, it is not necessary to only
release the tail of the mbuf ring. When a send error is detected, all outgoing
data can be flushed. So, now, in h2_send(), h2_release_mbuf() function is called
on pending error. The mbuf ring is fully released and H2_CF_MUX_MFULL and
H2_CF_DEM_MROOM flags are removed.

Many thanks to Krzysztof Kozłowski for its help to spot this issue.

This patch could be backported at least as far as 2.8. But it is a bit
sensitive. So, it is probably a good idea to backport it to 3.2 for now and
wait for bug report on older versions.

4 weeks agoBUG/MINOR: quic: properly support GSO on backend side
Amaury Denoyelle [Tue, 5 Aug 2025 08:26:29 +0000 (10:26 +0200)] 
BUG/MINOR: quic: properly support GSO on backend side

Previously, GSO emission was explicitely disabled on backend side. This
is not true since the following patch, thus GSO can be used, for example
when transfering large POST requests to a HTTP/3 backend.

  commit e064e5d46171d32097a84b8f84ccc510a5c211db
  MINOR: quic: duplicate GSO unsupp status from listener to conn

However, GSO on the backend side may cause crash when handling EIO. In
this case, GSO must be completely disabled. Previously, this was
performed by flagging listener instance. In backend side, this would
cause a crash as listener is NULL.

This patch fixes it by supporting GSO disable flag for servers. Thus, in
qc_send_ppkts(), EIO can be converted either to a listener or server
flag depending on the quic_conn proxy side. On backend side, server
instance is retrieved via <qc.conn.target>. This is enough to guarantee
that server is not deleted.

This does not need to be backported.

4 weeks agoMINOR: pools: Don't dump anymore info about pools when purge is forced
Christopher Faulet [Mon, 8 Sep 2025 13:44:06 +0000 (15:44 +0200)] 
MINOR: pools: Don't dump anymore info about pools when purge is forced

Historically, when the purge of pools was forced by sending a SIGQUIT to
haproxy, information about the pools were first dumped. It is now totally
pointless because these info can be retrieved via the CLI. It is even less
relevant now because the purge is forced typically when there are memroy
issues and to dump pools information, data must be allocated.

dump_pools_info() function was simplified because it is now called only from
an applet. No reason to still try to dump info on stderr.

4 weeks agoBUG/MINOR: pools: Fix the dump of pools info to deal with buffers limitations
Christopher Faulet [Mon, 8 Sep 2025 13:19:04 +0000 (15:19 +0200)] 
BUG/MINOR: pools: Fix the dump of pools info to deal with buffers limitations

The "show pools" CLI command was not designed to dump information exceeding
the size of a buffer. But there is now much more pools than few years ago
and when detailed information are dumped, we exceeds the buffer limit and
the output is truncated.

To fix the issue, the command must be refactored to be able to stream the
result. To do so, the array containing pools info is now part of the command
context and it is dynamically allocated. A dedicated function was created to
fill all info. In addition, the index of the next pool to dump is saved in
the command context too to properly handle resumption cases. Finally global
information about pools are also stored in the command context for
convenience.

This patch should fix the issue #3067. It must be backported to 3.2. On
older release, the buffer limit is never reached.

4 weeks agoREGTESTS: ssl: Fix the script about automatic SNI selection
Christopher Faulet [Mon, 8 Sep 2025 13:12:56 +0000 (15:12 +0200)] 
REGTESTS: ssl: Fix the script about automatic SNI selection

First, the barrier to delay the client execution was moved before the client
definition. Otherwise, the connection is established too early and with
short timeouts it could be closed before the requests are sent.

The main purpose of the barrier was to workaround slow health-checks. This
is also the reason why the script was flagged as slow. But it can be
significantly speed-up by setting a slow "inter" value. It is now set to
100ms and the script is no longer slow.

4 weeks agoMINOR: quic: restore QUIC_HP_SAMPLE_LEN constant
Amaury Denoyelle [Mon, 8 Sep 2025 12:42:26 +0000 (14:42 +0200)] 
MINOR: quic: restore QUIC_HP_SAMPLE_LEN constant

The below patch fixes padding emission for small packets, which is
required to ensure that header protection removal can be performed by
the recipient.

  commit d7dea408c64c327cab6aebf4ccad93405b675565
  BUG/MINOR: quic: too short PADDING frame for too short packets

In addition to the proper fix, constant QUIC_HP_SAMPLE_LEN was removed
and replaced by QUIC_TLS_TAG_LEN. However, it still makes sense to have
a dedicated constant which represent the size of the sample used for
header protection. Thus, this patch restores it.

Special instructions for backport : above patch mentions that no
backport is needed. However, this is incorrect, as bug is introduced by
another patch scheduled for backport up to 2.6. Thus, it is first
mandatory to schedule d7dea408c64c327cab6aebf4ccad93405b675565 after it.
Then, this patch can also be used for the sake of code clarity.

4 weeks agoTESTS: quic: add unit-tests for QUIC TX part
Amaury Denoyelle [Thu, 4 Sep 2025 12:53:03 +0000 (14:53 +0200)] 
TESTS: quic: add unit-tests for QUIC TX part

Define a new "quic_tx" unit-test which is used to test QUIC TX module.
For the moment, a single test is performed on qc_do_build_pkt(). It
checks that PADDING is correctly added for HP sampling in case of a
small packet.

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

Fix trace in qc_may_build_pkt().

This can be backported up to 3.0.

4 weeks agoMINOR: stats-file: use explicit unsigned integer bitshift for user slots
Aurelien DARRAGON [Mon, 8 Sep 2025 09:25:39 +0000 (11:25 +0200)] 
MINOR: stats-file: use explicit unsigned integer bitshift for user slots

As reported in GH #3104, there remained a place where (1 << shift was
used to set or remove bits from uint64_t users bitfield. It is incorrect
and could lead to bugs for values > 32 bits.

Instead, let's use 1ULL to ensure the operation remains 64bits consistent.

No backport needed.

4 weeks agoBUG/MEDIUM: proxy: fix crash with stop_proxy() called during init
Aurelien DARRAGON [Mon, 8 Sep 2025 09:01:02 +0000 (11:01 +0200)] 
BUG/MEDIUM: proxy: fix crash with stop_proxy() called during init

Willy reported that the following config would segfault right after the
"removing incomplete section 'peer' is emitted:

  peers peers
bind :2300
   server n10 127.0.0.1:2310

  listen dummy
  bind localhost:9999

This is caused by the fact that stop_proxy(), which tries to read shared
counters, is called during early init while shared counters are not yet
initialized. To fix the crash, let's check if we're still during starting
phase, in which case we assume the counters are not initialized and we
assume 0 value instead.

No backport needed unless 16eb0fab31 ("MAJOR: counters: dispatch counters
over thread groups") is.

4 weeks agoMINOR: quic: SSL session reuse for QUIC
Frederic Lecaille [Mon, 8 Sep 2025 09:46:26 +0000 (11:46 +0200)] 
MINOR: quic: SSL session reuse for QUIC

Mimic the same behavior as the one for SSL/TCP connetion to implement the
SSL session reuse.

Extract the code which try to reuse the SSL session for SSL/TCP connections
to implement ssl_sock_srv_try_reuse_sess().
Call this function from QUIC ->init() xprt callback (qc_conn_init()) as this
done for SSL/TCP connections.

4 weeks agoBUG/MEDIUM: ssl: Properly initialize msg_controllen.
Olivier Houchard [Sat, 6 Sep 2025 12:18:18 +0000 (14:18 +0200)] 
BUG/MEDIUM: ssl: Properly initialize msg_controllen.

When kTLS is compiled in, make sure msg_controllen is initialized to 0.
If we're not actually kTLS, then it won't be set, but we'll check that
it is non-zero later to check if we ancillary data.
This does not need to be backported.
This should fix CID 1620865, as reported in github issue #3106.

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

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

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

This workaround should be backported to 3.0.

4 weeks agoBUG/MINOR: quic: too short PADDING frame for too short packets
Frederic Lecaille [Fri, 5 Sep 2025 13:41:27 +0000 (15:41 +0200)] 
BUG/MINOR: quic: too short PADDING frame for too short packets

This bug arrvived with this commit:

    MINOR: quic: centralize padding for HP sampling on packet building

What was missed is the fact that at the centralization point for the
PADDING frame to add for too short packet, <len> payload length  already includes
<*pn_len> the packet number field length value.

So when computing the length of the PADDING frame, the packet field length must
not be considered and added to the payload length (<len>).

This bug leaded too short PADDING frame to too short packets. This was the case,
most of times with Application level packets with a 1-byte packet number field
followed by a 1-byte PING frame. A 1-byte PADDING frame was added in this case
in place of a correct 2-bytes PADDINF frame. The header packet protection of
such packet could not be removed by the clients as for instance for ngtcp2 with
such traces:

    I00001828 0x5a135c81e803f092c74bac64a85513b657 pkt could not decrypt packet number

As the header protection could no be removed, the header keyupdate bit could also
not be read by packet analyzers such as pyshark used during the keyupdate tests.

No need to backport.

4 weeks agoMINOR: quic: add useful trace about padding params values
Frederic Lecaille [Thu, 4 Sep 2025 07:18:08 +0000 (09:18 +0200)] 
MINOR: quic: add useful trace about padding params values

When adding a PADDING frame for too short packets, add a trace about variable
values whose this PADDING frame length depends on.

4 weeks agoREGTESTS: ssl: Add a script to test the automatic SNI selection
Christopher Faulet [Fri, 5 Sep 2025 13:45:02 +0000 (15:45 +0200)] 
REGTESTS: ssl: Add a script to test the automatic SNI selection

The script reg-tests/ssl/ssl_sni_auto.vtc tests the automatic SNI selection
for regular server connections and for health-check ones. It rely on a
3.3-dev8 feature (in fact, it was pushed just after the dev8).

4 weeks agoOPTIM: tcpcheck: Reorder tcpchek_connect structure fields to fill holes
Christopher Faulet [Thu, 4 Sep 2025 10:19:46 +0000 (12:19 +0200)] 
OPTIM: tcpcheck: Reorder tcpchek_connect structure fields to fill holes

Thanks to this patch, two 4-bytes holes are now filled in the
tcpchek_connect structure.

4 weeks agoMEDIUM: httpcheck/ssl: Base the SNI value on the HTTP host header by default
Christopher Faulet [Thu, 4 Sep 2025 10:13:54 +0000 (12:13 +0200)] 
MEDIUM: httpcheck/ssl: Base the SNI value on the HTTP host header by default

Similarly to the automic SNI selection for regulat SSL traffic, the SNI of
health-checks HTTPS connection is now automatically set by default by using
the host header value. "check-sni-auto" and "no-check-sni-auto" server
settings were added to change this behavior.

Only implicit HTTPS health-checks can take advantage of this feature. In
this case, the host header value from the "option httpchk" directive is used
to extract the SNI. It is disabled if http-check rules are used. So, the SNI
must still be explicitly specified via a "http-check connect" rule.

This patch with should paritally fix the issue #3081.

4 weeks agoMEDIUM: server/ssl: Base the SNI value to the HTTP host header by default
Christopher Faulet [Thu, 4 Sep 2025 08:12:19 +0000 (10:12 +0200)] 
MEDIUM: server/ssl: Base the SNI value to the HTTP host header by default

For HTTPS outgoing connections, the SNI is now automatically set using the
Host header value if no other value is already set (via the "sni" server
keyword). It is now the default behavior. It could be disabled with the
"no-sni-auto" server keyword. And eventually "sni-auto" server keyword may
be used to reset any previous "no-sni-auto" setting. This option can be
inherited from "default-server" settings. Finally, if no connection name is
set via "pool-conn-name" setting, the selected value is used.

The automatic selection of the SNI is enabled by default for all outgoing
connections. But it is concretely used for HTTPS connections only. The
expression used is "req.hdr(host),host_only".

This patch should paritally fix the issue #3081. It only covers the server
part. Another patch will add the feature for HTTP health-checks.

4 weeks agoBUG/MINOR: tcpcheck: Don't use sni as pool-conn-name for non-SSL connections
Christopher Faulet [Wed, 3 Sep 2025 14:50:47 +0000 (16:50 +0200)] 
BUG/MINOR: tcpcheck: Don't use sni as pool-conn-name for non-SSL connections

When we try to ruse connection to perform an healtcheck, the SNI, from the
tcpcheck connection or the healthcheck itself, must not be used as
connection name for non-SSL connections.

This patch must be backported to 3.2.

4 weeks agoOPTIM: tcpcheck: Don't set SNI and ALPN for non-ssl connections
Christopher Faulet [Wed, 3 Sep 2025 14:48:11 +0000 (16:48 +0200)] 
OPTIM: tcpcheck: Don't set SNI and ALPN for non-ssl connections

There is no reason to set the SNI and ALPN for non-ssl connections. It is
not really an issue because ssl_sock_set_servername() and
ssl_sock_set_alpn() functions will do nothing. But it is cleaner this way
and this could avoid bugs in future.

No backport needed, because there is no bug.

4 weeks agoOPTIM: proto_rhttp: Don't set SNI for non-ssl connections
Christopher Faulet [Wed, 3 Sep 2025 14:47:00 +0000 (16:47 +0200)] 
OPTIM: proto_rhttp: Don't set SNI for non-ssl connections

There is no reason to set the SNI for non-ssl connections. It is not really
an issue because ssl_sock_set_servername() function will do nothing. But
there is no reason to uselessly evaluate an expression.

No backport needed, because there is no bug.

4 weeks agoOPTIM: backend: Don't set SNI for non-ssl connections
Christopher Faulet [Wed, 3 Sep 2025 14:44:15 +0000 (16:44 +0200)] 
OPTIM: backend: Don't set SNI for non-ssl connections

There is no reason to set the SNI for non-ssl connections. It is not really
an issue because ssl_sock_set_servername() function will do nothing. But
there is no reason to uselessly evaluate an expression.

No backport needed, because there is no bug.

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

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

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

This patch should be backported to all stable versions.

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

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

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

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

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

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

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

4 weeks agoBUG/MINOR: acl: Fix error message about several '-m' parameters
Christopher Faulet [Fri, 5 Sep 2025 09:27:40 +0000 (11:27 +0200)] 
BUG/MINOR: acl: Fix error message about several '-m' parameters

There is a typo in the commit * c51ddd5c3 ("MINOR: acl: Only allow one '-m'
matching method") . '*m' was reported in the error message instead of '-m'.

In addition, it is now mentionned that only the last one should be keep if
an old config triggers the error.

No backport needed, except if the commit above is backported.

4 weeks ago[RELEASE] Released version 3.3-dev8 v3.3-dev8
Willy Tarreau [Fri, 5 Sep 2025 07:54:34 +0000 (09:54 +0200)] 
[RELEASE] Released version 3.3-dev8

Released version 3.3-dev8 with the following main changes :
    - BUG/MEDIUM: mux-h2: fix crash on idle-ping due to unwanted ABORT_NOW
    - BUG/MINOR: quic-be: missing Initial packet number space discarding
    - BUG/MEDIUM: quic-be: crash after backend CID allocation failures
    - BUG/MEDIUM: ssl: apply ssl-f-use on every "ssl" bind
    - BUG/MAJOR: stream: Remove READ/WRITE events on channels after analysers eval
    - MINOR: dns: dns_connect_nameserver: fix fd leak at error path
    - BUG/MEDIUM: quic: reset padding when building GSO datagrams
    - BUG/MINOR: quic: do not emit probe data if CONNECTION_CLOSE requested
    - BUG/MAJOR: quic: fix INITIAL padding with probing packet only
    - BUG/MINOR: quic: don't coalesce probing and ACK packet of same type
    - MINOR: quic: centralize padding for HP sampling on packet building
    - MINOR: http_ana: fix typo in http_res_get_intercept_rule
    - BUG/MEDIUM: http_ana: handle yield for "stats http-request" evaluation
    - MINOR: applet: Rely on applet flag to detect the new api
    - MINOR: applet: Add function to test applet flags from the appctx
    - MINOR: applet: Add a flag to know an applet is using HTX buffers
    - MINOR: applet: Make some applet functions HTX aware
    - MEDIUM: applet: Set .rcv_buf and .snd_buf functions on default ones if not set
    - BUG/MEDIUM: mux-spop: Reject connection attempts from a non-spop frontend
    - REGTESTS: jwt: create dynamically "cert.ecdsa.pem"
    - BUG/MEDIUM: spoe: Improve error detection in SPOE applet on client abort
    - MINOR: haproxy: abort config parsing on fatal errors for post parsing hooks
    - MEDIUM: server: split srv_init() in srv_preinit() + srv_postinit()
    - MINOR: proxy: handle shared listener counters preparation from proxy_postcheck()
    - DOC: configuration: reword 'generate-certificates'
    - BUG/MEDIUM: quic-be: avoid crashes when releasing Initial pktns
    - BUG/MINOR: quic: reorder fragmented RX CRYPTO frames by their offsets
    - MINOR: ssl: diagnostic warning when both 'default-crt' and 'strict-sni' are used
    - MEDIUM: ssl: convert diag to warning for strict-sni + default-crt
    - DOC: configuration: clarify 'default-crt' and implicit default certificates
    - MINOR: quic: remove ->offset qf_crypto struct field
    - BUG/MINOR: mux-quic: trace with non initialized qcc
    - BUG/MINOR: acl: set arg_list->kw to aclkw->kw string literal if aclkw is found
    - BUG/MEDIUM: mworker: fix startup and reload on macOS
    - BUG/MINOR: connection: rearrange union list members
    - BUG/MINOR: connection: remove extra session_unown_conn() on reverse
    - MINOR: cli: display failure reason on wait command
    - BUG/MINOR: server: decrement session idle_conns on del server
    - BUG/MINOR: mux-quic: do not access conn after idle list insert
    - MINOR: session: document explicitely that session_add_conn() is safe
    - MINOR: session: uninline functions related to BE conns management
    - MINOR: session: refactor alloc/lookup of sess_conns elements
    - MEDIUM: session: protect sess conns list by idle_conns_lock
    - MINOR: server: shard by thread sess_conns member
    - MEDIUM: server: close new idle conns if server in maintenance
    - MEDIUM: session: close new idle conns if server in maintenance
    - MINOR: server: cleanup idle conns for server in maint already stopped
    - MINOR: muxes: enforce thread-safety for private idle conns
    - MEDIUM: conn/muxes/ssl: reinsert BE priv conn into sess on IO completion
    - MEDIUM: conn/muxes/ssl: remove BE priv idle conn from sess on IO
    - MEDIUM: mux-quic: enforce thread-safety of backend idle conns
    - MAJOR: server: implement purging of private idle connections
    - MEDIUM: session: account on server idle conns attached to session
    - MAJOR: server: do not remove idle conns in del server
    - BUILD: mworker: fix ignoring return value of â\80\98readâ\80\99
    - DOC: unreliable sockpair@ on macOS
    - MINOR: muxes: adjust takeover with buf_wait interaction
    - OPTIM: backend: set release on takeover for strict maxconn
    - DOC: configuration: confuse "strict-mode" with "zero-warning"
    - MINOR: doc: add missing statistics column
    - MINOR: doc: add missing statistics column
    - MINOR: stats: display new curr_sess_idle_conns server counter
    - MINOR: proxy: extend "show servers conn" output
    - MEDIUM: proxy: Reject some header names for 'http-send-name-header' directive
    - BUG/BUILD: stats: fix build due to missing stat enum definition
    - DOC: proxy-protocol: Make example for PP2_SUBTYPE_SSL_SIG_ALG accurate
    - CLEANUP: quic: remove a useless CRYPTO frame variable assignment
    - BUG/MEDIUM: quic: CRYPTO frame freeing without eb_delete()
    - BUG/MAJOR: mux-quic: fix crash on reload during emission
    - MINOR: conn/muxes/ssl: add ASSUME_NONNULL() prior to _srv_add_idle
    - REG-TESTS: map_redirect: Don't use hdr_dom in ACLs with "-m end" matching method
    - MINOR: acl: Only allow one '-m' matching method
    - MINOR: acl; Warn when matching method based on a suffix is overwritten
    - BUG/MEDIUM: server: Duplicate healthcheck's alpn inherited from default server
    - BUG/MINOR: server: Duplicate healthcheck's sni inherited from default server
    - BUG/MINOR: acl: Properly detect overwritten matching method
    - BUG/MINOR: halog: Add OOM checks for calloc() in filter_count_srv_status() and filter_count_url()
    - BUG/MINOR: log: Add OOM checks for calloc() and malloc() in logformat parser and dup_logger()
    - BUG/MINOR: acl: Add OOM check for calloc() in smp_fetch_acl_parse()
    - BUG/MINOR: cfgparse: Add OOM check for calloc() in cfg_parse_listen()
    - BUG/MINOR: compression: Add OOM check for calloc() in parse_compression_options()
    - BUG/MINOR: tools: Add OOM check for malloc() in indent_msg()
    - BUG/MINOR: quic: ignore AGAIN ncbuf err when parsing CRYPTO frames
    - MINOR: quic/flags: complete missing flags
    - BUG/MINOR: quic: fix room check if padding requested
    - BUG/MINOR: quic: fix padding issue on INITIAL retransmit
    - BUG/MINOR: quic: pad Initial pkt with CONNECTION_CLOSE on client
    - MEDIUM: quic: strengthen BUG_ON() for unpad Initial packet on client
    - DOC: configuration: rework the jwt_verify keyword documentation
    - BUG/MINOR: haproxy: be sure not to quit too early on soft stop
    - BUILD: acl: silence a possible null deref warning in parse_acl_expr()
    - MINOR: quic: Add more information about RX packets
    - CI: fix syntax of Quic Interop pipelines
    - MEDIUM: cfgparse: warn when using user/group when built statically
    - BUG/MEDIUM: stick-tables: don't leave the expire loop with elements deleted
    - BUG/MINOR: stick-tables: never leave used entries without expiration
    - BUG/MEDIUM: peers: don't fail twice to grab the update lock
    - MINOR: stick-tables: limit the number of visited nodes during expiration
    - OPTIM: stick-tables: exit expiry faster when the update lock is held
    - MINOR: counters: retrieve detailed errmsg upon failure with counters_{fe,be}_shared_prepare()
    - MINOR: stats-file: introduce shm-stats-file directive
    - MEDIUM: stats-file: processes share the same clock source from shm-stats-file
    - MINOR: stats-file: add process slot management for shm stats file
    - MEDIUM: stats-file/counters: store and preload stats counters as shm file objects
    - DOC: config: document "shm-stats-file" directive
    - OPTIM: stats-file: don't unnecessarily die hard on shm_stats_file_reuse_object()
    - MINOR: compiler: add ALWAYS_PAD() macro
    - BUILD: stats-file: fix aligment issues
    - MINOR: stats-file: reserve some bytes in exported structs
    - MEDIUM: stats-file: add some BUG_ON() guards to ensure exported structs are not changed by accident
    - BUG/MINOR: check: ensure check-reuse is compatible with SSL
    - BUG/MINOR: check: fix dst address when reusing a connection
    - REGTESTS: explicitly use "balance roundrobin" where RR is needed
    - MAJOR: backend: switch the default balancing algo to "random"
    - BUG/MEDIUM: conn: fix UAF on connection after reversal on edge
    - BUG/MINOR: connection: streamline conn detach from lists
    - BUG/MEDIUM: quic-be: too early SSL_SESSION initialization
    - BUG/MINOR: log: fix potential memory leak upon error in add_to_logformat_list()
    - MEDIUM: init: always warn when running as root without being asked to
    - MINOR: sample: Add base2 converter
    - MINOR: version: add -vq, -vqb, and -vqs flags for concise version output
    - BUILD: trace: silence a bogus build warning at -Og
    - MINOR: trace: accept trace spec right after "-dt" on the command line
    - BUILD: makefile: bump the default minimum linux version to 4.17

4 weeks agoBUILD: makefile: bump the default minimum linux version to 4.17
Willy Tarreau [Fri, 5 Sep 2025 07:44:56 +0000 (09:44 +0200)] 
BUILD: makefile: bump the default minimum linux version to 4.17

As explained during the 3.3-dev7 announcement below:
  https://www.mail-archive.com/haproxy@formilux.org/msg46073.html

no regularly maintained distro supports a kernel older than 4.18 anymore,
and KTLS is supported since 4.17. So it's about the right moment to bump
the default minimum kernel version supported by glibc and musl to
automatically cover new features. The linux-glibc-legacy target still
supports 2.6.28 and above.

4 weeks agoMINOR: trace: accept trace spec right after "-dt" on the command line
Willy Tarreau [Fri, 5 Sep 2025 07:30:07 +0000 (09:30 +0200)] 
MINOR: trace: accept trace spec right after "-dt" on the command line

I continue to mistakenly set the traces using "-dtXXX" and to have to
refer to the doc to figure that it requires a separate argument and
differs from some other options. Worse, "-dthelp" doesn't say anything
and silently ignores the argument.

Let's make the parser take whatever follows "-dt" as the argument if
present, otherwise take the next one (as it currently does). Doing
this even allows to simplify the code, and is easier to figure the
syntax since "-dthelp" now works.

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

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

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

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

It could be backported to 3.0.

4 weeks agoMINOR: version: add -vq, -vqb, and -vqs flags for concise version output
Nikita Kurashkin [Tue, 2 Sep 2025 09:34:51 +0000 (11:34 +0200)] 
MINOR: version: add -vq, -vqb, and -vqs flags for concise version output

This patch introduces three new command line flags to display HAProxy version
info more flexibly:

- `-vqs` outputs the short version string without commit info (e.g., "3.3.1").
- `-vqb` outputs only the branch (major.minor) part of the version (e.g., "3.3").
- `-vq` outputs the full version string with suffixes (e.g., "3.3.1-dev5-1bb975-71").

This allows easier parsing of version info in automation while keeping existing -v and -vv behaviors.

The command line argument parsing now calls `display_version_plain()` with a
display_mode parameter to select the desired output format. The function handles
stripping of commit or patch info as needed, depending on the mode.

Signed-off-by: Nikita Kurashkin <nkurashkin@stsoft.ru>
4 weeks agoMINOR: sample: Add base2 converter
Maximilian Moehl [Thu, 4 Sep 2025 07:19:39 +0000 (09:19 +0200)] 
MINOR: sample: Add base2 converter

This commit adds the base2 converter to turn binary input into it's
string representation. Each input byte is converted into a series of
eight characters which are either 0s and 1s by bit-wise comparison.

4 weeks agoMEDIUM: init: always warn when running as root without being asked to
Willy Tarreau [Thu, 4 Sep 2025 07:22:38 +0000 (09:22 +0200)] 
MEDIUM: init: always warn when running as root without being asked to

Like many exposed network deamons, haproxy does normally not need to run
as root and strongly recommends against this, unless strictly necessary.
On some operating systems, capabilities even totally alleviate this need.

Lately, maybe due to a raise of containerization or automated config
generation or a bit of both, we've observed a resurgence of this bad
practice, possibly due to the fact that users are just not aware of the
conditions they're using their daemon.

Let's add a warning at boot when starting as root without having requested
it using "uid" or "user". And take this opportunity for warning the user
about the existence of capabilities when supported, and encouraging the
use of a chroot.

This is achieved by leaving global.uid set to -1 by default, allowing us
to detect if it was explicitly set or not.

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

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

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

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

4 weeks agoBUG/MEDIUM: quic-be: too early SSL_SESSION initialization
Frederic Lecaille [Thu, 4 Sep 2025 18:25:14 +0000 (20:25 +0200)] 
BUG/MEDIUM: quic-be: too early SSL_SESSION initialization

When an SNI is set on a QUIC server line, ssl_sock_set_servername() is called
from connect_server() (backend.c). This leads some BUG_ON() to be triggered
because the CO_FL_WAIT_L6_CONN | CO_FL_SSL_WAIT_HS were not set. This must
be done into the ->init() xprt callback. This patch move the flags settings
from ->start() to ->init() callback.

Indeed, connect_server() calls these functions in this order:

   ->init(),
   ssl_sock_set_servername() # => crash if CO_FL_WAIT_L6_CONN | CO_FL_SSL_WAIT_HS not set
   ->start()

Furthermore ssl_sock_set_servername() has a side effect to reset the SSL_SESSION
object (attached to SSL object) calling SSL_set_session(), leading to crashes as follows:

 [Thread debugging using libthread_db enabled]
 Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
 Core was generated by `./haproxy -f quic_srv.cfg'.
 Program terminated with signal SIGSEGV, Segmentation fault.
 #0  tls_process_server_hello (s=0x560c259733b0, pkt=0x7fffac239f20)
     at ssl/statem/statem_clnt.c:1624
 1624            if (s->session->session_id_length > 0) {
 [Current thread is 1 (Thread 0x7fc364e53dc0 (LWP 35514))]
 (gdb) bt
 #0  tls_process_server_hello (s=0x560c259733b0, pkt=0x7fffac239f20)
     at ssl/statem/statem_clnt.c:1624
 #1  0x00007fc36540fba4 in ossl_statem_client_process_message (s=0x560c259733b0,
     pkt=0x7fffac239f20) at ssl/statem/statem_clnt.c:1042
 #2  0x00007fc36540d028 in read_state_machine (s=0x560c259733b0) at ssl/statem/statem.c:646
 #3  0x00007fc36540ca70 in state_machine (s=0x560c259733b0, server=0)
     at ssl/statem/statem.c:439
 #4  0x00007fc36540c576 in ossl_statem_connect (s=0x560c259733b0) at ssl/statem/statem.c:250
 #5  0x00007fc3653f1698 in SSL_do_handshake (s=0x560c259733b0) at ssl/ssl_lib.c:3835
 #6  0x0000560c22620327 in qc_ssl_do_hanshake (qc=qc@entry=0x560c25961f60,
     ctx=ctx@entry=0x560c25963020) at src/quic_ssl.c:863
 #7  0x0000560c226210be in qc_ssl_provide_quic_data (len=90, data=<optimized out>,
     ctx=0x560c25963020, level=ssl_encryption_initial, ncbuf=0x560c2588bb18)
     at src/quic_ssl.c:1071
 #8  qc_ssl_provide_all_quic_data (qc=qc@entry=0x560c25961f60, ctx=0x560c25963020)
     at src/quic_ssl.c:1123
 #9  0x0000560c2260ca5f in quic_conn_io_cb (t=0x560c25962f80, context=0x560c25961f60,
     state=<optimized out>) at src/quic_conn.c:791
 #10 0x0000560c228255ed in run_tasks_from_lists (budgets=<optimized out>) at src/task.c:648
 #11 0x0000560c22825f7a in process_runnable_tasks () at src/task.c:889
 #12 0x0000560c22793dc7 in run_poll_loop () at src/haproxy.c:2836
 #13 0x0000560c22794481 in run_thread_poll_loop (data=<optimized out>) at src/haproxy.c:3056
 #14 0x0000560c2259082d in main (argc=<optimized out>, argv=<optimized out>)
     at src/haproxy.c:3667

<s> is the SSL object, and <s->session> is the SSL_SESSION object.

For the client, this is the first call do SSL_do_handshake() which initializes this
SSL_SESSION object from ->init() xpt callback. Then it is reset by
ssl_sock_set_servername(), then tls_process_server_hello() TLS stack is called with
NULL value for s->session when receiving the ServerHello TLS message.

To fix this, simply move the first call to SSL_do_handshake to ->start xprt call
back (qc_xprt_start()).

No need to backport.

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

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

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

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

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

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

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

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

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

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

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

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

This patch must be backported up to 3.0 release.

4 weeks agoMAJOR: backend: switch the default balancing algo to "random"
Willy Tarreau [Thu, 4 Sep 2025 06:23:30 +0000 (08:23 +0200)] 
MAJOR: backend: switch the default balancing algo to "random"

For many years, an unset load balancing algorithm would use "roundrobin".
It was shown several times that "random" with at least 2 draws (the
default) generally provides better performance and fairness in that
it will automatically adapt to the server's load and capacity. This
was further described with numbers in this discussion:

  https://www.mail-archive.com/haproxy@formilux.org/msg46011.html
  https://github.com/orgs/haproxy/discussions/3042

BTW there were no objection and only support for the change.

The goal of this patch is to change the default algo when none is
specified, from "roundrobin" to "random". This way, users who don't
care and don't set the load balancing algorithm will benefit from a
better one in most cases, while those who have good reasons to prefer
roundrobin (for session affinity or for reproducible sequences like used
in regtests) can continue to specify it.

The vast majority of users should not notice a difference.

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

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

4 weeks agoBUG/MINOR: check: fix dst address when reusing a connection
Amaury Denoyelle [Wed, 3 Sep 2025 13:00:12 +0000 (15:00 +0200)] 
BUG/MINOR: check: fix dst address when reusing a connection

The keyword check-reuse-pool allows to reuse an idle connection to
perform a health check instead of opening a new one. It is implemented
similarly to HTTP transfer reuse : a hash is calculated with a subset of
properties to lookup a connection with the same characteristics.

One of these properties is the destination address. Initially it was
always set to NULL prior to reuse check, as this is necessary to match
connections on a reverse-HTTP server. However, this prevents reuse on
other servers with a proper address configured. Indeed, in this case
destination address is always used as key for connections inserted in
idle pool.

This patch fixes this by properly setting destination address for check
reuse. By default, it reuses the address from the server. The only
exception is if the server is using reverse-HTTP, in which case address
remains NULL.

A new test is also performed prior to try check reuse to ensure this is
not performed on a transparent server. Indeed, in this case server
address would be unset. Anyway, check cannot reuse a connection in this
case so this is OK. Note that this does not prevent to continue check
with a newly connection with a NULL address : this should be handled
more properly in another patch.

This must be backported up to 3.2.

4 weeks agoBUG/MINOR: check: ensure check-reuse is compatible with SSL
Amaury Denoyelle [Wed, 3 Sep 2025 12:28:58 +0000 (14:28 +0200)] 
BUG/MINOR: check: ensure check-reuse is compatible with SSL

SSL may be activated implicitely if a server relies on SSL, even without
check-ssl keyword. This is performed by init_srv_check() function. The
main operation is to change xprt layer for check to SSL.

Prior to this patch, <use_ssl> check member was also set, despite not
strictly necessary. This has a negative side-effect of rendering
check-reuse-pool ineffective. Indeed, reuse on check is only performed
if no specific check configuration has been specified (see
tcpcheck_use_nondefault_connect()).

This patch fixes check reuse with SSL : <use_ssl> is not set in case SSL
is inherited implicitely from server configuration. Thus, <use_ssl> is
now only set if an explicit check-ssl keyword is set, which disables
connection reuse for check.

This must be backported up to 3.2.

4 weeks agoMEDIUM: stats-file: add some BUG_ON() guards to ensure exported structs are not chang...
Aurelien DARRAGON [Wed, 3 Sep 2025 14:23:33 +0000 (16:23 +0200)] 
MEDIUM: stats-file: add some BUG_ON() guards to ensure exported structs are not changed by accident

Add two BUG_ON() in shm_stats_file_prepare() which will trigger if
exported structures (shm_stats_file_hdr and shm_stats_file_object) change
in size, because it means that they will become incompatible with older
versions and thus precautions should be taken by the developer to ensure
compatibility with olders versions, or at least detect incompatible
versions by changing the version number to prevent bugs resulting
from inconsistent mapping between versions. The BUG_ON() may be
safely adjusted then.

Please note that it doesn't protect against accidental struct member
re-ordering if the resulting struct size is equal..

4 weeks agoMINOR: stats-file: reserve some bytes in exported structs
Aurelien DARRAGON [Wed, 3 Sep 2025 14:07:30 +0000 (16:07 +0200)] 
MINOR: stats-file: reserve some bytes in exported structs

We may need additional struct members in shm_stats_file_object and
shm_stats_file_hdr, yet since these structs are exported they should
not change in size nor ordering else it would require a version change
to break compability on purpose since mapping would differ.

Here we reserve 64 additional bytes in shm_stats_file_object, and
128 bytes in shm_stats_file_hdr for future usage.

4 weeks agoBUILD: stats-file: fix aligment issues
Aurelien DARRAGON [Wed, 3 Sep 2025 13:23:16 +0000 (15:23 +0200)] 
BUILD: stats-file: fix aligment issues

Document some byte holes and fix some potential aligment issues
between 32 and 64 bits architectures to ensure the shm_stats_file memory
mapping is consistent between operating systems.

4 weeks agoMINOR: compiler: add ALWAYS_PAD() macro
Aurelien DARRAGON [Wed, 3 Sep 2025 13:23:00 +0000 (15:23 +0200)] 
MINOR: compiler: add ALWAYS_PAD() macro

same as THREAD_PAD() but doesn't depend on haproxy being compiled with
thread support. It may be useful for memory (or files) that may be
shared between multiple processed.

4 weeks agoOPTIM: stats-file: don't unnecessarily die hard on shm_stats_file_reuse_object()
Aurelien DARRAGON [Fri, 29 Aug 2025 13:34:10 +0000 (13:34 +0000)] 
OPTIM: stats-file: don't unnecessarily die hard on shm_stats_file_reuse_object()

shm_stats_file_reuse_object() has a non negligible cost, especially if
the shm file contains a lot of objects because the functions scans the
whole shm file to find available slots.

During startup, if no existing objects could be mapped in the shm
file shm_stats_file_add_object() for each object (server, fe, be or
listener) with a GUID set. On large config it means
shm_stats_file_add_object() could be called a lot of times in a row.

With current implementation, each shm_stats_file_add_object() call
leverages shm_stats_file_reuse_object(), so the more objects are defined
in the config, the slower the startup will be.

To try to optimize startup time a bit with large configs, we don't
sytematically call shm_stats_file_reuse_object(), especially when we
know that the previous attempt to reuse objects failed. In this case
we add a small tempo between failed attempts to reuse objects because
we assume the new attempt will probably fail anyway. (For slots to
become available, either an old process has to clean its entries,
or they have to time out which implies that the clock needs to be updated)

4 weeks agoDOC: config: document "shm-stats-file" directive
Aurelien DARRAGON [Fri, 8 Aug 2025 13:07:49 +0000 (15:07 +0200)] 
DOC: config: document "shm-stats-file" directive

Add some documentation for "shm-stats-file" and
"shm-stats-file-max-objects" experimental directives related to the use
of shared memory for storing stats counters (see previous commits for
implementation details)

4 weeks agoMEDIUM: stats-file/counters: store and preload stats counters as shm file objects
Aurelien DARRAGON [Wed, 27 Aug 2025 15:23:42 +0000 (17:23 +0200)] 
MEDIUM: stats-file/counters: store and preload stats counters as shm file objects

This is the last patch of the shm stats file series, in this patch we
implement the logic to store and fetch shm stats objects and associate
them to existing shared counters on the current process.

Shm objects are stored in the same memory location as the shm stats file
header. In fact they are stored right after it. All objects (struct
shm_stats_file_object) have the same size (no matter their type), which
allows for easy object traversal without having to check the object's
type, and could permit the use of external tools to scan the SHM in the
future. Each object stores a guid (of GUID_MAX_LEN+1 size) and tgid
which allows to match corresponding shared counters indexes. Also,
as stated before, each object stores the list of users making use of
it. Objects are never released (the map can only grow), but unused
objects (when no more users or active users are found in objects->users),
the object is automatically recycled. Also, each object stores its
type which defines how the object generic data member should be handled.

Upon startup (or reload), haproxy first tries to scan existing shm to
find objects that could be associated to frontends, backends, listeners
or servers in the current config based on GUID. For associations that
couldn't be made, haproxy will automatically create missing objects in
the SHM during late startup. When haproxy matches with an existing object,
it means the counter from an older process is preserved in the new
process, so multiple processes temporarily share the same counter for as
long as required for older processes to eventually exit.

4 weeks agoMINOR: stats-file: add process slot management for shm stats file
Aurelien DARRAGON [Wed, 27 Aug 2025 14:36:12 +0000 (16:36 +0200)] 
MINOR: stats-file: add process slot management for shm stats file

Now that all processes tied to the same shm stats file now share a
common clock source, we introduce the process slot notion in this
patch.

Each living process registers itself in a map at a free index: each slot
stores information about the process' PID and heartbeat. Each process is
responsible for updating its heartbeat, a slot is considered as "free" if
the heartbeat was never set or if the heartbeat is expired (60 seconds of
inactivity). The total number of slots is set to 64, this is on purpose
because it allows to easily store the "users" of a given shm object using
a 64 bits bitmask. Given that when haproxy is reloaded olders processes
are supposed to die eventually, it should be large enough (64 simultaneous
processes) to be safe. If we manage to reach this limit someday, more
slots could be added by splitting "users" bitmask on multiple 64bits
variable.

4 weeks agoMEDIUM: stats-file: processes share the same clock source from shm-stats-file
Aurelien DARRAGON [Wed, 27 Aug 2025 14:14:53 +0000 (16:14 +0200)] 
MEDIUM: stats-file: processes share the same clock source from shm-stats-file

The use of the "shm-stats-file" directive now implies that all processes
using the same file now share a common clock source, this is required
for consistency regarding time-related operations.

The clock source is stored in the shm stats file header.
When the directive is set, all processes share the same clock
(global_now_ms and global_now_ns both point to variables in the map),
this is required for time-based counters such as freq counters to work
consistently. Since all processes manipulate global clock with atomic
operations exclusively during runtime, and don't systematically relies
on it (thanks to local now_ms and now_ns), it is pretty much transparent.

4 weeks agoMINOR: stats-file: introduce shm-stats-file directive
Aurelien DARRAGON [Wed, 27 Aug 2025 13:51:08 +0000 (15:51 +0200)] 
MINOR: stats-file: introduce shm-stats-file directive

add initial support for the "shm-stats-file" directive and
associated "shm-stats-file-max-objects" directive. For now they are
flagged as experimental directives.

The shared memory file is automatically created by the first process.
The file is created using open() so it is up to the user to provide
relevant path (either on regular filesystem or ramfs for performance
reasons). The directive takes only one argument which is path of the
shared memory file. It is passed as-is to open().

The maximum number of objects per thread-group (hard limit) that can be
stored in the shm is defined by "shm-stats-file-max-objects" directive,

Upon initial creation, the main shm stats file header is provisioned with
the version which must remains the same to be compatible between processes
and defaults to 2k. which means approximately 1mb max per thread group
and should cover most setups. When the limit is reached (during startup)
an error is reported by haproxy which invites the user to increase the
"shm-stats-file-max-objects" if desired, but this means more memory will
be allocated. Actual memory usage is low at start, because only the mmap
(mapping) is provisionned with the maximum number of objects to avoid
relocating the memory area during runtime, but the actual shared memory
file is dynamically resized when objects are added (resized by following
half power of 2 curve when new objects are added, see upcoming commits)

For now only the file is created, further logic will be implemented in
upcoming commits.

4 weeks agoMINOR: counters: retrieve detailed errmsg upon failure with counters_{fe,be}_shared_p...
Aurelien DARRAGON [Wed, 27 Aug 2025 12:51:48 +0000 (14:51 +0200)] 
MINOR: counters: retrieve detailed errmsg upon failure with counters_{fe,be}_shared_prepare()

counters_{fe,be}_shared_prepare now take an extra <errmsg> parameter
that contains additional hints about the error in case of failure.

It must be freed accordingly since it is allocated using memprintf

4 weeks agoOPTIM: stick-tables: exit expiry faster when the update lock is held
Willy Tarreau [Wed, 3 Sep 2025 09:54:15 +0000 (11:54 +0200)] 
OPTIM: stick-tables: exit expiry faster when the update lock is held

It helps keep the contention level low: when we hold the update lock
that we know other parts may be relying on (peers, track-sc etc),
we decrease the remaining visit counters 4 times as fast to further
reduce the contention. At this point no more warnings are seen during
intense synchronization (2x64 cores, 1.5M req/s with a track-sc each,
5M entries in use).

4 weeks agoMINOR: stick-tables: limit the number of visited nodes during expiration
Willy Tarreau [Wed, 3 Sep 2025 08:45:30 +0000 (10:45 +0200)] 
MINOR: stick-tables: limit the number of visited nodes during expiration

As reported by Felipe in GH issue #3084, on large systems it's not
sufficient to leave the expiration process after a certain number of
expired entries, because if they accumulate too fast, it's possible
to still spend some time visiting many (e.g. those still in use),
which takes time.

Thus here we're taking a stricter approach consisting in counting the
number of visited entries, which allows to leave early if we can't do
the expected work in a reasonable amount of time.

In order to avoid always stopping on first shards and never visiting
last ones, we're always starting from a random shard number and looping
from that one. This way even if we always leave early, all shards will
be handled equally.

This should be backported to 3.2.

4 weeks agoBUG/MEDIUM: peers: don't fail twice to grab the update lock
Willy Tarreau [Wed, 3 Sep 2025 09:54:45 +0000 (11:54 +0200)] 
BUG/MEDIUM: peers: don't fail twice to grab the update lock

When the expire task is running fast (i.e. running almost alone), it's
super hard to grab the update lock and peers can easily trigger the
watchdog because the time it takes to grab this lock is multiplied by
the number of updates to perform. This is easier to trigger at the end
of an injection session where the expire task is omni-present. Let's
just record that we failed once and don't fail a second time in the
loop.

This should be backported to 3.2, but probably not further given that
this area changed significantly in 3.2.

4 weeks agoBUG/MINOR: stick-tables: never leave used entries without expiration
Willy Tarreau [Wed, 3 Sep 2025 12:03:40 +0000 (12:03 +0000)] 
BUG/MINOR: stick-tables: never leave used entries without expiration

When trying to kill/expire entries, if a ref-counted entry is found,
let's requeue it with its expiration timer instead of leaving it out,
because other ref-counters (e.g. peers) will not purge it otherwise,
leaving it orphan. This one seems trickier to trigger, though it seems
to happen sometimes when peers are late and a long resync is active
and competing with intense calls to process_table_expire() (i.e. when
no other acitvity is there).

This must be backported to 3.2. It's likely that older versions are
affected as well, but possibly differently since the expiration
mechanism changed between 3.1 and 3.2, so better not take unneeded
risks there.

4 weeks agoBUG/MEDIUM: stick-tables: don't leave the expire loop with elements deleted
Willy Tarreau [Wed, 3 Sep 2025 11:46:30 +0000 (11:46 +0000)] 
BUG/MEDIUM: stick-tables: don't leave the expire loop with elements deleted

In 3.2, the table expiration latency was improved by commit 994cc58576
("MEDIUM: stick-tables: Limit the number of entries we expire"), however
it introduced an issue by which it's possible to leave the loop after a
certain number of elements were expired, without requeuing the deleted
elements. The issue it causes is that other places with a non-null ref_cnt
will not necessarily delete it themselves, resulting in orphan elements in
the table. These ones will then pollute it and force recycling old ones
more often which in turn results in an increase of the contention.

Let's check for the expiration counter before deleting the element so
that it can be found upon next visit.

This fix must be backported to 3.2. It is directly related to GH
issue #3084. Thanks to Felipe and Ricardo for sharing precious info
and testing a candidate fix.

4 weeks agoMEDIUM: cfgparse: warn when using user/group when built statically
William Lallemand [Wed, 3 Sep 2025 12:45:00 +0000 (14:45 +0200)] 
MEDIUM: cfgparse: warn when using user/group when built statically

In issue #3013, an user observed a crash at startup of haproxy when
building statically and using the "user" global section.

This is a known problem of the glibc and the linker even warn about
this:

> warning: Using 'getgrnam' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
> warning: Using 'getpwnam' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking

Let's emit a warning when using user/group in this case.

4 weeks agoCI: fix syntax of Quic Interop pipelines
Ilia Shipitsin [Tue, 2 Sep 2025 19:52:53 +0000 (21:52 +0200)] 
CI: fix syntax of Quic Interop pipelines

previously, wrong syntax of passing build arguments was used, thus
previously images were built using default SSLLIB=QuicTLS-1.1.1

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

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

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

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

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

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

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

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

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

4 weeks agoDOC: configuration: rework the jwt_verify keyword documentation
William Lallemand [Tue, 26 Aug 2025 12:16:12 +0000 (14:16 +0200)] 
DOC: configuration: rework the jwt_verify keyword documentation

Split the documentation in multiple sections:

- Explanation about what it does and how
- <alg> parameter with array of parameters
- <key> parameter with details about certificates and public keys
- Return value

Others changes:

- certificates does not need to be known during configuration parsing
- differences between public key and certificate

4 weeks agoMEDIUM: quic: strengthen BUG_ON() for unpad Initial packet on client
Amaury Denoyelle [Tue, 2 Sep 2025 07:22:24 +0000 (09:22 +0200)] 
MEDIUM: quic: strengthen BUG_ON() for unpad Initial packet on client

To avoid anti-amplification limit, it is required that Initial packet
are padded to be at least 1.200 bytes long. On server side, this only
applies to ack-eliciting packets. However, for client side, this is
mandatory for every packets.

This patch adjusts qc_txb_store() BUG_ON statement used to catch too
small Initial packets. On QUIC client side, ack-eliciting flag is now
ignored, thus every packets are checked.

This is labelled as MEDIUM as this BUG_ON() is known to be easily
triggered, as QUIC datagrams encoding function are complex. However,
it's important that a QUIC endpoint respects it, else the peer will drop
the invalid packet and could immediately close the connection.

4 weeks agoBUG/MINOR: quic: pad Initial pkt with CONNECTION_CLOSE on client
Amaury Denoyelle [Tue, 2 Sep 2025 07:16:02 +0000 (09:16 +0200)] 
BUG/MINOR: quic: pad Initial pkt with CONNECTION_CLOSE on client

Currently, when connection is closing, only CONNECTION_CLOSE frame is
emitted via qc_prep_pkts()/qc_do_build_pkt(). Also, only the first
registered encryption level is considered while the others are
dismissed. This results in a single packet datagram.

This can cause issues for QUIC client support, as padding is required
for every Initial packet, contrary to server side where only
ack-eliciting packets are eligible. Thus a client must add padding to a
CONNECTION_CLOSE frame on Initial level.

This patch adjusts qc_prep_pkts() to ensure such packet will be
correctly padded on client side. It sets <final_packet> variable which
instructs that if padding is necessary it must be apply immediately on
the current encryption level instead of the last one.

It could appear as unnecessary to pad a CONNECTION_CLOSE packet, as the
peer will enter in draining state when processing it. However, RFC
mandates that a client Initial packet too small must be dropped by the
server, so there is a risk that the CONNECTION_CLOSE is simply discarded
prior to its processing if stored in a too small datagram.

No need to backport as this is a QUIC backend issue only.

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

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

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

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

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

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

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

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

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

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

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

This should be backported up to 2.6.

4 weeks agoMINOR: quic/flags: complete missing flags
Amaury Denoyelle [Tue, 2 Sep 2025 07:21:42 +0000 (09:21 +0200)] 
MINOR: quic/flags: complete missing flags

Add missing quic_conn flags definition for dev utility.

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

This fix follows this previous one:

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

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

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

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

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

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

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

Co-authored-by: Christian Norbert Menges <christian.norbert.menges@sap.com>
4 weeks agoBUG/MINOR: compression: Add OOM check for calloc() in parse_compression_options()
Alexander Stephan [Mon, 1 Sep 2025 09:57:51 +0000 (09:57 +0000)] 
BUG/MINOR: compression: Add OOM check for calloc() in parse_compression_options()

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

Co-authored-by: Christian Norbert Menges <christian.norbert.menges@sap.com>
4 weeks agoBUG/MINOR: cfgparse: Add OOM check for calloc() in cfg_parse_listen()
Alexander Stephan [Mon, 1 Sep 2025 09:51:19 +0000 (09:51 +0000)] 
BUG/MINOR: cfgparse: Add OOM check for calloc() in cfg_parse_listen()

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

Co-authored-by: Christian Norbert Menges <christian.norbert.menges@sap.com>
4 weeks agoBUG/MINOR: acl: Add OOM check for calloc() in smp_fetch_acl_parse()
Alexander Stephan [Mon, 1 Sep 2025 09:47:30 +0000 (09:47 +0000)] 
BUG/MINOR: acl: Add OOM check for calloc() in smp_fetch_acl_parse()

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

Co-authored-by: Christian Norbert Menges <christian.norbert.menges@sap.com>
4 weeks agoBUG/MINOR: log: Add OOM checks for calloc() and malloc() in logformat parser and...
Alexander Stephan [Mon, 1 Sep 2025 09:36:07 +0000 (09:36 +0000)] 
BUG/MINOR: log: Add OOM checks for calloc() and malloc() in logformat parser and dup_logger()

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

Co-authored-by: Christian Norbert Menges <christian.norbert.menges@sap.com>
4 weeks agoBUG/MINOR: halog: Add OOM checks for calloc() in filter_count_srv_status() and filter...
Alexander Stephan [Mon, 1 Sep 2025 09:32:04 +0000 (09:32 +0000)] 
BUG/MINOR: halog: Add OOM checks for calloc() in filter_count_srv_status() and filter_count_url()

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

Co-authored-by: Christian Norbert Menges <christian.norbert.menges@sap.com>
5 weeks agoBUG/MINOR: acl: Properly detect overwritten matching method
Christopher Faulet [Mon, 1 Sep 2025 19:36:22 +0000 (21:36 +0200)] 
BUG/MINOR: acl: Properly detect overwritten matching method

A bug was introduced by the commit 6ea50ba46 ("MINOR: acl; Warn when
matching method based on a suffix is overwritten"). The test on the match
function, when defined was not correct. It is now fixed.

No backport needed, except if the commit above is backported.

5 weeks agoBUG/MINOR: server: Duplicate healthcheck's sni inherited from default server
Christopher Faulet [Mon, 1 Sep 2025 13:13:07 +0000 (15:13 +0200)] 
BUG/MINOR: server: Duplicate healthcheck's sni inherited from default server

It is not really an issue, but the "check-sni" value inerited from a default
server is not duplicated while the paramter value is duplicated during the
parsing. So here there is a small leak if several "check-sni" parameters are
used on the same server line. The previous value is never released. But to
fix this issue, the value inherited from the default server must also be
duplicated. At the end it is safer this way and consistant with the parsing
of the "sni" parameter.

It is harmless so there is no reason to backport this patch.

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

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

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

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

5 weeks agoMINOR: acl; Warn when matching method based on a suffix is overwritten
Christopher Faulet [Fri, 29 Aug 2025 15:47:17 +0000 (17:47 +0200)] 
MINOR: acl; Warn when matching method based on a suffix is overwritten

From time to time, issues are reported about string matching based on suffix
(for instance path_beg). Each time, it appears these ACLs are used in
conjunction with a converter or followed by an explicit matching method
(-m).

Unfortunatly, it is not an issue but an expected behavior, while it is not
obvious. matching suffixes can be consider as aliases on the corresponding
'-m' matching method. Thus "path_beg" is equivalent to "path -m beg". When a
converter is used the original matching (string) is used and the suffix is
lost. When followed by an explicit matching method, it overwrites the
matching method based on the suffix.

It is expected but confusing. Thus now a warning is emitted because it is a
configuration issue for sure. Following sample fetch functions are concerned:

 * base
 * path
 * req.cook
 * req.hdr
 * res.hdr
 * url
 * urlp

The configuration manual was modified to make it less ambiguous.

5 weeks agoMINOR: acl: Only allow one '-m' matching method
Christopher Faulet [Fri, 29 Aug 2025 15:43:07 +0000 (17:43 +0200)] 
MINOR: acl: Only allow one '-m' matching method

Several '-m' explicit matching method was allowed, but only the last one was
really used. There is no reason to specify several matching method and it is
most probably an error or a lack of understanding of how matchings are
performed. So now, an error is triggered during the configuration parsing to
avoid any bad usage.

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

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

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

5 weeks agoMINOR: conn/muxes/ssl: add ASSUME_NONNULL() prior to _srv_add_idle
Amaury Denoyelle [Mon, 1 Sep 2025 11:32:24 +0000 (13:32 +0200)] 
MINOR: conn/muxes/ssl: add ASSUME_NONNULL() prior to _srv_add_idle

When manipulating idle backend connections for input/output processing,
special care is taken to ensure the connection cannot be accessed by
another thread, for example via a takeover. When processing is over,
connection is reinserted in its original list.

A connection can either be attached to a session (private ones) or a
server idle tree. In the latter case, <srv> is guaranteed to be non null
prior to _srv_add_idle() thanks to CO_FL_LIST_MASK comparison with conn
flags. This patch adds an ASSUME_NONNULL() to better reflect this.

This should fix coverity reports from github issue #3095.

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

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

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

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

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

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

This must be backported up to 3.0.

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

Since this commit:

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

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

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

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

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

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

This modification should have arrived with this commit:

MINOR: quic: remove ->offset qf_crypto struct field

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

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

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

5 weeks agoDOC: proxy-protocol: Make example for PP2_SUBTYPE_SSL_SIG_ALG accurate
Collison, Steven [Wed, 27 Aug 2025 17:26:25 +0000 (17:26 +0000)] 
DOC: proxy-protocol: Make example for PP2_SUBTYPE_SSL_SIG_ALG accurate

The docs call out that this field is the algorithm used to
sign the certificate. However, the example only had the hash portion of
the signature algorithm. This change updates the example to be accurate
based on a value written by HAProxy, which is based on an OID for
signature algorithms. I based example on a real TLV written by
HAProxy on my machine with all SSL TLVs enabled in config.

5 weeks agoBUG/BUILD: stats: fix build due to missing stat enum definition
Amaury Denoyelle [Fri, 29 Aug 2025 07:29:04 +0000 (09:29 +0200)] 
BUG/BUILD: stats: fix build due to missing stat enum definition

Recently, new server counter for private idle connections have been
added to statistics output. However, the patch was missing
ST_I_PX_PRIV_IDLE_CUR enum definition.

No need to backport.

5 weeks agoMEDIUM: proxy: Reject some header names for 'http-send-name-header' directive
Christopher Faulet [Thu, 28 Aug 2025 13:05:57 +0000 (15:05 +0200)] 
MEDIUM: proxy: Reject some header names for 'http-send-name-header' directive

From time to time, we saw the 'http-send-name-header' directive used to
overwrite the Host header to workaround limitations of a buggy application.
Most of time, this led to troubles. This was never officially supported and
each time we strongly discouraged anyone to do so. We already thought to
deprecate this directive, but it seems to be still used by few people. So
for now, we decided to strengthen the tests performed on it.

The header name is now checked during the configuration parsing to forbid
some risky names. 'Host', 'Content-Length', 'Transfer-Encoding' and
'Connection' header names are now rejected. But more headers could be added
in future.

5 weeks agoMINOR: proxy: extend "show servers conn" output
Amaury Denoyelle [Tue, 19 Aug 2025 13:23:21 +0000 (15:23 +0200)] 
MINOR: proxy: extend "show servers conn" output

CLI command "show servers conn" is used as a debugging tool to monitor
the number of connections per server. This patch extends its output by
adding the content of two server counters.

<served> is the first added column. It represents the number of active
streams on a server. <curr_sess_idle_conns> is the second added column.
This is a recently added value which account private idle connections
referencing a server.

5 weeks agoMINOR: stats: display new curr_sess_idle_conns server counter
Amaury Denoyelle [Thu, 28 Aug 2025 16:14:23 +0000 (18:14 +0200)] 
MINOR: stats: display new curr_sess_idle_conns server counter

Add a new stats column in proxy stats to display server counter for
private idle connections. This counter has been introduced recently.

The value is displayed on CSV output on the last column before modules.
It is also displayed on HTLM page alongside other idle server counters.

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

Complete documentation with missing description of newly added columns.

This must be backported up to 2.8.

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

Complete documentation with missing description of newly added columns.

This should be backported up to 2.4

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

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

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

Must be backported as far as 2.4.

5 weeks agoOPTIM: backend: set release on takeover for strict maxconn
Amaury Denoyelle [Fri, 8 Aug 2025 15:50:57 +0000 (17:50 +0200)] 
OPTIM: backend: set release on takeover for strict maxconn

When strict maxconn is enforced on a server, it may be necessary to kill
an idle connection to never exceed the limit. To be able to delete a
connection from any thread, takeover is first used to migrate it on the
current thread prior to its deletion.

As takeover is performed to delete a connection instead of reusing it,
<release> argument can be set to true. This removes unnecessary
allocations of resources prior to connection deletion. As such, this
patch is a small optimization for strict maxconn implementation.

Note that this patch depends on the previous one which removes any
assumption in takeover implementation that thread isolation is active if
<release> is true.

5 weeks agoMINOR: muxes: adjust takeover with buf_wait interaction
Amaury Denoyelle [Fri, 8 Aug 2025 15:50:18 +0000 (17:50 +0200)] 
MINOR: muxes: adjust takeover with buf_wait interaction

Takeover operation defines an argument <release>. It's a boolean which
if set indicate that freed connection resources during the takeover does
not have to be reallocated on the new thread. Typically, it is set to
false when takever is performed to reuse a connection. However, when
used to be able to delete a connection from a different thread,
<release> should be set to true.

Previously, <release> was only set in conjunction with "del server"
handler. This operation was performed under thread isolation, which
guarantee that not thread-safe operation such as removal from buf_wait
list could be performed on takeover if <release> was true. In the
contrary case, takeover operation would fail.

Recently, "del server" handler has been adjusted to remove idle
connection cleanup with takeover. As such, <release> is never set to
true in remaining takeover usage.

However, takeover is also used to enforce strict-maxconn on a server.
This is performed to delete a connection from any thread, which is the
primary reason of <release> to true. But for the moment as takeover
implementers considers that thread isolation is active if <release> is
set, this is not yet applicable for strict-maxconn usage.

Thus, the purpose of this patch is to adjust takeover implementation.
Remove assumption between <release> and thread-isolation mode. It's not
possible to remove a connection from a buf_wait list, an error will be
return in any case.