]> git.ipfire.org Git - thirdparty/haproxy.git/log
thirdparty/haproxy.git
15 months agoBUG/MEDIUM: ssl: Fix crash when calling "update ssl ocsp-response" when an update...
Remi Tricot-Le Breton [Thu, 14 Mar 2024 14:38:32 +0000 (15:38 +0100)] 
BUG/MEDIUM: ssl: Fix crash when calling "update ssl ocsp-response" when an update is ongoing

The CLI command "update ssl ocsp-response" was forcefully removing an
OCSP response from the update tree regardless of whether it used to be
in it beforehand or not. But since the main OCSP upate task works by
removing the entry being currently updated from the update tree and then
reinserting it when the update process is over, it meant that in the CLI
command code we were modifying a structure that was already being used.

These concurrent accesses were not properly locked on the "regular"
update case because it was assumed that once an entry was removed from
the update tree, the update task was the only one able to work on it.

Rather than locking the whole update process, an "updating" flag was
added to the certificate_ocsp in order to prevent the "update ssl
ocsp-response" command from trying to update a response already being
updated.

An easy way to reproduce this crash was to perform two "simultaneous"
calls to "update ssl ocsp-response" on the same certificate. It would
then crash on an eb64_delete call in the main ocsp update task function.

This patch can be backported up to 2.8. Wait a little bit before
backporting.

15 months agoREGTESTS: ssl: Add OCSP related tests
Remi Tricot-Le Breton [Thu, 14 Mar 2024 14:38:31 +0000 (15:38 +0100)] 
REGTESTS: ssl: Add OCSP related tests

Add tests that combine the OCSP update mechanism and the various
preexisting commands that allow to manipulate certificates and
crt-lists.

15 months agoBUG/MAJOR: ocsp: Separate refcount per instance and per store
Remi Tricot-Le Breton [Thu, 14 Mar 2024 14:38:30 +0000 (15:38 +0100)] 
BUG/MAJOR: ocsp: Separate refcount per instance and per store

With the current way OCSP responses are stored, a single OCSP response
is stored (in a certificate_ocsp structure) when it is loaded during a
certificate parsing, and each SSL_CTX that references it increments its
refcount. The reference to the certificate_ocsp is kept in the SSL_CTX
linked to each ckch_inst, in an ex_data entry that gets freed when the
context is freed.
One of the downsides of this implementation is that if every ckch_inst
referencing a certificate_ocsp gets detroyed, then the OCSP response is
removed from the system. So if we were to remove all crt-list lines
containing a given certificate (that has an OCSP response), and if all
the corresponding SSL_CTXs were destroyed (no ongoing connection using
them), the OCSP response would be destroyed even if the certificate
remains in the system (as an unused certificate).
In such a case, we would want the OCSP response not to be "usable",
since it is not used by any ckch_inst, but still remain in the OCSP
response tree so that if the certificate gets reused (via an "add ssl
crt-list" command for instance), its OCSP response is still known as
well.
But we would also like such an entry not to be updated automatically
anymore once no instance uses it. An easy way to do it could have been
to keep a reference to the certificate_ocsp structure in the ckch_store
as well, on top of all the ones in the ckch_instances, and to remove the
ocsp response from the update tree once the refcount falls to 1, but it
would not work because of the way the ocsp response tree keys are
calculated. They are decorrelated from the ckch_store and are the actual
OCSP_CERTIDs, which is a combination of the issuer's name hash and key
hash, and the certificate's serial number. So two copies of the same
certificate but with different names would still point to the same ocsp
response tree entry.

The solution that answers to all the needs expressed aboved is actually
to have two reference counters in the certificate_ocsp structure, one
actual reference counter corresponding to the number of "live" pointers
on the certificate_ocsp structure, incremented for every SSL_CTX using
it, and one for the ckch stores.
If the ckch_store reference counter falls to 0, the corresponding
certificate must have been removed via CLI calls ('set ssl cert' for
instance).
If the actual refcount falls to 0, then no live SSL_CTX uses the
response anymore. It could happen if all the corresponding crt-list
lines were removed and there are no live SSL sessions using the
certificate anymore.
If any of the two refcounts becomes 0, we will always remove the
response from the auto update tree, because there's no point in spending
time updating an OCSP response that no new SSL connection will be able
to use. But the certificate_ocsp object won't be removed from the tree
unless both refcounts are 0.

Must be backported up to 2.8. Wait a little bit before backporting.

15 months agoBUG/MAJOR: connection: fix server used_conns with H2 + reuse safe
Amaury Denoyelle [Tue, 19 Mar 2024 09:34:45 +0000 (10:34 +0100)] 
BUG/MAJOR: connection: fix server used_conns with H2 + reuse safe

By default, backend connections are accounted by the server. This allows
to determine the number of idle connections to keep. A backend
connection can also be marked as private to prevent its reuse. It is
thus removed from server lists into the session list. As such, a private
connection is not accounted into server : conn_set_private() uses
srv_release_conn() to ensure this.

When using HTTP/2 on backend side with default http-reuse safe, the
above principle are mixed. Indeed, when a connection is first used, or
switches from idle to used, it is moved into the session list but it is
not flagged as private. This is done to prevent its sharing by different
clients to prevent head-of-line blocking issue. When all streams are
closed, the connection becomes idle again and is reinserted in the
server list. This has been introduced by the following patch :

  0d21deaded1a4bbd1e1700ab8386af1f1441ea73
  MEDIUM: backend: add reused conn to sess if mux marked as HOL blocking

When freeing a backend connection, special care is taken to ensure
server used counter is decremented. This is implemented into
conn_backend_deinit(). However, this function does this only if the
connection is not present in a session list. This is valid for private
connections. However, if a connection is non-private and present only
temporarily into a session list, the decrement operation won't be
executed despite the connection being accounted by the server.

This bug has several impacts. The server used counter won't be able to
reach its initial null value, even when all its connections are closed.
This can result in a wrong estimation of necessary idle connections,
which may cause unnecessary new connection usage. Also, this will
prevent definitely the server from being removed via "delete server" CLI
command.

This should be backported up to 2.4. Note that conn_backend_deinit() was
introduced in 2.9. For lesser versions, the change should be done
directly into conn_free().

15 months agoBUG/MEDIUM: http_ana: ignore NTLM for reuse aggressive/always and no H1
Amaury Denoyelle [Wed, 20 Mar 2024 08:25:03 +0000 (09:25 +0100)] 
BUG/MEDIUM: http_ana: ignore NTLM for reuse aggressive/always and no H1

Backend connections can be marked as private to prevent their sharing by
multiple clients. Now, this has become an exception as only two reasons
for data traffic can trigger this (checks are ignored here) :
* http-reuse never
* HTTP response with NTLM header

The first case is easy to manage as the connection is flagged as private
since its inception. However, the second case is dynamic as the
connection can be flagged anytime during its lifetime. When using a
backend protocol such as HTTP/2 with reuse mode aggressive or always, we
face a design issue as the connection would be marked as private,
despite potentially being shared by several clients at the same time.

This is conceptually invalid, but worst it can trigger crashes on MUX
stream detach callback depending on the order of release of the streams,
by calling session_check_idle_conn() with a NULL session. It could also
be possible to have several NTLM responses on a single connection for
different sessions. In this case, connection owner is still being
updated without attaching the connection to its correct session, which
ultimately would cause a crash on session_check_idle_conn with an
invalid session.

Here are two backtrace examples from GDB for such cases :

Thread 1 (Thread 0x7ff73e9fc700 (LWP 648859)):
 #0  session_check_idle_conn (conn=0x7ff72f597800, sess=0x0) at include/haproxy/session.h:209
 #1  h2_detach (sd=<optimized out>) at src/mux_h2.c:4520
 #2  0x000056151742be24 in sc_detach_endp (scp=scp@entry=0x7ff73e9f0f18) at src/stconn.c:376
 #3  0x000056151742c208 in sc_destroy (sc=<optimized out>) at src/stconn.c:444
 #4  0x0000561517370871 in stream_free (s=s@entry=0x7ff72a2dbd80) at src/stream.c:728
 #5  0x000056151737541f in process_stream (t=t@entry=0x7ff72d5e2620, context=0x7ff72a2dbd80, state=<optimized out>) at src/stream.c:2645
 #6  0x0000561517456cbb in run_tasks_from_lists (budgets=budgets@entry=0x7ff73e9f10d0) at src/task.c:632
 #7  0x00005615174576b9 in process_runnable_tasks () at src/task.c:876
 #8  0x000056151742275a in run_poll_loop () at src/haproxy.c:2996
 #9  0x0000561517422db1 in run_thread_poll_loop (data=<optimized out>) at src/haproxy.c:3195
 #10 0x00007ff789e081ca in start_thread () from /lib64/libpthread.so.0
 #11 0x00007ff789a39e73 in clone () from /lib64/libc.so.6

(gdb)
Thread 1 (Thread 0x7ff52e7fc700 (LWP 681458)):
 #0  0x0000556ebd6e7e69 in session_check_idle_conn (conn=0x7ff5787ff100, sess=0x7ff51d2539a0) at include/haproxy/session.h:209
 #1  h2_detach (sd=<optimized out>) at src/mux_h2.c:4520
 #2  0x0000556ebd7f3e24 in sc_detach_endp (scp=scp@entry=0x7ff52e7f0f18) at src/stconn.c:376
 #3  0x0000556ebd7f4208 in sc_destroy (sc=<optimized out>) at src/stconn.c:444
 #4  0x0000556ebd738871 in stream_free (s=s@entry=0x7ff520e28200) at src/stream.c:728
 #5  0x0000556ebd73d41f in process_stream (t=t@entry=0x7ff565783700, context=0x7ff520e28200, state=<optimized out>) at src/stream.c:2645
 #6  0x0000556ebd81ecbb in run_tasks_from_lists (budgets=budgets@entry=0x7ff52e7f10d0) at src/task.c:632
 #7  0x0000556ebd81f6b9 in process_runnable_tasks () at src/task.c:876
 #8  0x0000556ebd7ea75a in run_poll_loop () at src/haproxy.c:2996
 #9  0x0000556ebd7eadb1 in run_thread_poll_loop (data=<optimized out>) at src/haproxy.c:3195
 #10 0x00007ff5752081ca in start_thread () from /lib64/libpthread.so.0
 #11 0x00007ff574e39e73 in clone () from /lib64/libc.so.6
(gdb)

To solve this issue, simply ignore NTLM responses when using a
multiplexer with streams support and the connection is not already
attached to the session. The connection is not marked as private and
will continue to be shared freely accross clients. This is considered
conceptually valid as NTLM usage (rfc 4559) with HTTP is broken and was
designed only with HTTP/1.1 in mind. A side-effect of the change is that
SESS_FL_PREFER_LAST is also not set anymore on NTLM detection, which
allows following requests to be load-balanced accross several server
instances.

The original behavior is kept for HTTP/1 or if the connection is already
attached to the session. This last case happens when using HTTP/2 with
default http-reuse safe mode since the following patch :

  0d21deaded1a4bbd1e1700ab8386af1f1441ea73
  MEDIUM: backend: add reused conn to sess if mux marked as HOL blocking

This should be backported up to all stable releases. Up until 2.4, it
can be taken as-is. For lesser versions, above patch is not present. In
this case the condition should be restricted only to HTTP/1 usage :

  if (srv_conn && strcmp(srv_conn->mux->name, "H1") == 0) {

15 months agoBUG/MINOR: session: ensure conn owner is set after insert into session
Amaury Denoyelle [Wed, 20 Mar 2024 10:25:31 +0000 (11:25 +0100)] 
BUG/MINOR: session: ensure conn owner is set after insert into session

A crash could occured if a session_add_conn() would temporarily failed
when called via h2_detach(). In this case, connection owner is reset to
NULL. However, if this wasn't the last connection stream, the connection
won't be destroyed. When h2_detach() is recalled for another stream and
this time session_add_conn() succeeds, a crash will occur due to
session_check_idle_conn() invocation with a NULL connection owner.

To fix this, ensure connection owner is always set after
session_add_conn() success.

This bug is considered as minor as the only failure reason for
session_add_conn() is a pool allocation issue.

This should be backported up to all stable releases.

15 months agoBUG/MEDIUM: spoe: Return an invalid frame on recv if size is too small
Christopher Faulet [Mon, 18 Mar 2024 07:02:32 +0000 (08:02 +0100)] 
BUG/MEDIUM: spoe: Return an invalid frame on recv if size is too small

Frames with a too small size must be detected on receive and an error must
be triggered. It is especially important for frames of size 0. Otherwise,
because the frame length is used as return value, the frame is ignored (0 is
the return value to state the frame must be ignored). It is an issue because
in this case, outgoing data, the 4 bytes representing the frame size, are
never consumed. If the agent also closes the connection, this leads to a
wakeup loop because outgoing data are stuck and a shutdown is pending.

In addition, all pending outgoing data are systematcially skipped when the
applet is in SPOE_APPCTX_ST_END state.

The patch should fix the issue #2490. It must be backported to all stable
versions.

15 months agoCI: temporarily adjust kernel entropy to work with ASAN/clang
Ilia Shipitsin [Sun, 17 Mar 2024 16:01:39 +0000 (17:01 +0100)] 
CI: temporarily adjust kernel entropy to work with ASAN/clang

clang runtime (shipped with clang14) is not compatible with recent
Ubuntu kernels

more details: https://github.com/actions/runner-images/issues/9491

15 months agoCLEANUP: assorted typo fixes in the code and comments
Ilia Shipitsin [Sun, 17 Mar 2024 16:01:38 +0000 (17:01 +0100)] 
CLEANUP: assorted typo fixes in the code and comments

This is 40th iteration of typo fixes

15 months agoMINOR: spoe: Add SPOE filters in the exposed deprecated directives
Christopher Faulet [Fri, 15 Mar 2024 08:08:08 +0000 (09:08 +0100)] 
MINOR: spoe: Add SPOE filters in the exposed deprecated directives

It is the first deprecated directive exposed via the
'expose-deprecated-directives' global option. This way, it is possible to
silent the warning about the SPOE uses.

15 months agoMINOR: cfgparse: Add a global option to expose deprecated directives
Christopher Faulet [Fri, 15 Mar 2024 08:01:11 +0000 (09:01 +0100)] 
MINOR: cfgparse: Add a global option to expose deprecated directives

Similarly to "expose-exprimental-directives" option, there is no a global
option to expose some deprecated directives. Idea is to have a way to silent
warnings about deprecated directives when there is no alternative solution.

Of course, deprecated directives covered by this option are not listed and
may change. It is only a best effort to let users upgrade smoothly.

15 months agoMAJOR: spoe: Deprecate the SPOE filter
Christopher Faulet [Thu, 14 Mar 2024 10:53:27 +0000 (11:53 +0100)] 
MAJOR: spoe: Deprecate the SPOE filter

As announced on the ML few weeks (months ?) ago and on several GH issues,
the SPOE is now deprecated. Sadly, this filter should be refactored to work
properly. It was implemented as a functionnal PoC for the 1.7 and since
then, no time was invest to improve it and make it truly maintainable in
time. Worst, other parts of HAProxy evolve, especially applets part, making
maintenance ever more expensive.

Instead of keeping the SPOE filter in a this state and always reply to users
encountering issues or limitations that it is far from perfect but we cannot
work on it for now, we decided to deprecate it.

We can still change our mind before the 3.0.0 release if the situation
evolves. Otherwise the filter will be removed or marked as unmaintained for
the 3.1. If the situation does not change, it means the 3.0 will be the last
version with a true SPOE support.

15 months agoBUG/MINOR: spoe: Be sure to be able to quickly close IDLE applets on soft-stop
Christopher Faulet [Thu, 14 Mar 2024 09:49:01 +0000 (10:49 +0100)] 
BUG/MINOR: spoe: Be sure to be able to quickly close IDLE applets on soft-stop

On soft-stop, we try, as far as possible, to process all pending messages
before closing SPOE applets. However, in sync mode, when an applets waiting
for a response receives the ACK frame, it is switched to IDLE state without
checking if it may be closed. In this case, we will wait the idle timeout
before closing de applet, delaying the soft-stop.

To reduce this delay, on soft-stop, IDLE applets are woken up. On the next
wakeup, the applet will try to process pending messages or will be
closed.

This patch should be backported to all stable versions.

15 months agoBUG/MEDIUM: spoe: Don't rely on stream's expiration to detect processing timeout
Christopher Faulet [Thu, 14 Mar 2024 09:21:56 +0000 (10:21 +0100)] 
BUG/MEDIUM: spoe: Don't rely on stream's expiration to detect processing timeout

On stream side, the SPOE filter relied on the stream's expiration date to be
woken up and be able to detect processing timeout. However, the stream
expiration date must not be updated this way. Mainly because it may be
overwritten at the end of process_stream(). In the worst case, it is set to
TICK_ETERNITY for any reason. In this case, it is impossible to detect the
SPOE filter must time out and abort the processing.

The right way to do is to set an analysis expiration date on the
corresponding channel, depending on the direction. This expiration date will
be used to compute the stream's expiration date at the end of
process_stream().

This patch may be related to issue #2478. It must be backported to all
stable versions.

15 months agoBUG/MAJOR: server: do not delete srv referenced by session
Amaury Denoyelle [Tue, 12 Mar 2024 13:09:55 +0000 (14:09 +0100)] 
BUG/MAJOR: server: do not delete srv referenced by session

A server can only be deleted if there is no elements which reference it.
This is taken care via srv_check_for_deletion(), most notably for active
and idle connections.

A special case occurs for connections directly managed by a session.
This is for so-called private connections, when using http-reuse never
or H2 + http-reuse safe for example. In this case. server does not
account these connections into its idle lists. This caused a bug as the
server is deleted despite the session still being able to access it.

To properly fix this, add a new referencing element into the server for
these session connections. A mt_list has been chosen for this. On
default http-reuse, private connections are typically not used so it
won't make any difference. If using H2 servers, or more generally when
dealing with private connections, insert/delete should typically occur
only once per session lifetime so impact on performance should be
minimal.

This should be backported up to 2.4. Note that srv_check_for_deletion()
was introduced in 3.0 dev tree. On backport, the extra condition in it
should be placed in cli_parse_delete_server() instead.

15 months agoMINOR: session: rename private conns elements
Amaury Denoyelle [Thu, 14 Mar 2024 10:24:10 +0000 (11:24 +0100)] 
MINOR: session: rename private conns elements

By default, backend connections are attached to a server instance. This
allows to implement connection reuse. However, in some particular cases,
connection cannot be shared accross several clients. These connections
are considered and private and are attached to the session instance
instead.

These private connections are also indexed by the target server to not
mix them. All of this is implemented via a dedicated structure
previously named struct sess_srv_list.

Rename it to better reflect its usage to struct sess_priv_conns. Also
rename its internal members and all of the associated functions.

This commit is only a renaming, thus no functional impact is expected.

15 months agoBUG/MINOR: listener: Don't schedule frontend without task in listener_release()
Christopher Faulet [Thu, 14 Mar 2024 08:29:09 +0000 (09:29 +0100)] 
BUG/MINOR: listener: Don't schedule frontend without task in listener_release()

null pointer dereference was reported by Coverity in listener_release()
function. Indeed, we must not try to schedule frontend without task when a
limit is still blocking the frontend. This issue was introduced by commit
65ae1347c7 ("BUG/MINOR: listener: Wake proxy's mngmt task up if necessary on
session release")

This patch should fix issue #2488. It must be backported to all stable
version with the commit above.

15 months agoBUG/MINOR: listener: Wake proxy's mngmt task up if necessary on session release
Christopher Faulet [Tue, 12 Mar 2024 06:31:56 +0000 (07:31 +0100)] 
BUG/MINOR: listener: Wake proxy's mngmt task up if necessary on session release

When a session is released, listener_release() function is called to notify
the listener. It is an opportunity to resume limited/full listeners. We
first try to resume the listener owning the released session, then all
limited listeners in the global queue and finally all limited listeners in
the frontend's waiting queue. This last step is only performed if there is
no limit applied on the frontend. Nothing is performed if the session rate is
still limited. And it is an issue because if this happens for the last
listener's session, there is no other event to wake the frontend's managment
task up and the listener remains in the limited state.

To fix the issue, when a limit is still applied on the frontent, we must
compute the new wake up date from the sessions rate and schedule the
frontend's managment task.

It is easy to reproduce the issue in SSL by setting a maxconn and a rate
limit on sessions.

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

16 months agoCI: github: add -dI to haproxy arguments
William Lallemand [Wed, 13 Mar 2024 10:19:17 +0000 (11:19 +0100)] 
CI: github: add -dI to haproxy arguments

-dI is useful when running with ASAN, allow to fork addr2line

16 months agoMINOR: debug: enable insecure fork on the command line
William Lallemand [Wed, 13 Mar 2024 10:08:50 +0000 (11:08 +0100)] 
MINOR: debug: enable insecure fork on the command line

-dI allow to enable "insure-fork-wanted" directly from the command line,
which is useful when you want to run ASAN with addr2line with a lot of
configuration files without editing them.

16 months agoBUG/MEDIUM: hlua: streams don't support mixing lua-load with lua-load-per-thread...
Aurelien DARRAGON [Tue, 12 Mar 2024 16:05:54 +0000 (17:05 +0100)] 
BUG/MEDIUM: hlua: streams don't support mixing lua-load with lua-load-per-thread (2nd try)

While trying to reproduce another crash case involving lua filters
reported by @bgrooot on GH #2467, we found out that mixing filters loaded
from different contexts ('lua-load' vs 'lua-load-per-thread') for the same
stream isn't supported and may even cause the process to crash.

Historically, mixing lua-load and lua-load-per-threads for a stream wasn't
supported, but this changed thanks to 0913386 ("BUG/MEDIUM: hlua: streams
don't support mixing lua-load with lua-load-per-thread").

However, the above fix didn't consider lua filters's use-case properly:
unlike lua fetches, actions or even services, lua filters don't simply
use the stream hlua context as a "temporary" hlua running context to
process some hlua code. For fetches, actions.. hlua executions are
processed sequentially, so we simply reuse the hlua context from the
previous action/fetch to run the next one (this allows to bypass memory
allocations and initialization, thus it increases performance), unless
we need to run on a different hlua state-id, in which case we perform a
reset of the hlua context.

But this cannot work with filters: indeed, once registered, a filter will
last for the whole stream duration. It means that the filter will rely
on the stream hlua context from ->attach() to ->detach(). And here is the
catch, if for the same stream we register 2 lua filters from different
contexts ('lua-load' + 'lua-load-per-thread'), then we have an issue,
because the hlua stream will be re-created each time we switch between
runtime contexts, which means each time we switch between the filters (may
happen for each stream processing step), and since lua filters rely on the
stream hlua to carry context between filtering steps, this context will be
lost upon a switch. Given that lua filters code was not designed with that
in mind, it would confuse the code and cause unexpected behaviors ranging
from lua errors to crashing process.

So here we take another approach: instead of re-creating the stream hlua
context each time we switch between "global" and "per-thread" runtime
context, let's have both of them inside the stream directly as initially
suggested by Christopher back then when talked about the original issue.

For this we leverage hlua_stream_ctx_prepare() and hlua_stream_ctx_get()
helper functions which return the proper hlua context for a given stream
and state_id combination.

As for debugging infos reported after ha_panic(), we check for both hlua
runtime contexts to check if one of them was active when the panic occured
(only 1 runtime ctx per stream may be active at a given time).

This should be backported to all stable versions with 0913386
("BUG/MEDIUM: hlua: streams don't support mixing lua-load with lua-load-per-thread")

This commit depends on:
 - "DEBUG: lua: precisely identify if stream is stuck inside lua or not"
   [for versions < 2.9 the ha_thread_dump_one() part should be skipped]
 - "MINOR: hlua: use accessors for stream hlua ctx"

For 2.4, the filters API didn't exist. However it may be a good idea to
backport it anyway because ->set_priv()/->get_priv() from tcp/http lua
applets may also be affected by this bug, plus it will ease code
maintenance. Of course, filters-related parts should be skipped in this
case.

16 months agoMINOR: hlua: use accessors for stream hlua ctx
Aurelien DARRAGON [Tue, 12 Mar 2024 16:00:25 +0000 (17:00 +0100)] 
MINOR: hlua: use accessors for stream hlua ctx

Change hlua_stream_ctx_prepare() prototype so that it now returns the
proper hlua ctx on success instead of returning a boolean.

Add hlua_stream_ctx_get() to retrieve hlua ctx out of a given stream.

This way we may easily change the storage mechanism for hlua stream in
the future without extensive code changes.

No backport needed unless a commit depends on it.

16 months agoDEBUG: lua: precisely identify if stream is stuck inside lua or not
Aurelien DARRAGON [Mon, 11 Mar 2024 23:22:44 +0000 (00:22 +0100)] 
DEBUG: lua: precisely identify if stream is stuck inside lua or not

When ha_panic() is called by the watchdog, we try to guess from
ha_task_dump() and ha_thread_dump_one() if the thread was stuck while
executing lua from the stream context. However we consider this is the
case by simply checking if the stream hlua context was set, but this is
not very precise because if the hlua context is set, then it simply means
that at least one lua instruction was executed at the stream level, not
that the stuck was currently executing lua when the panic occured.

This is especially true with filters, one could simply register a lua
filter that does nothing but this will still end up initializing the
stream hlua context for each stream. If the thread end up being stuck
during the stream handling, then debug dumping functions will report
that the stream was stuck while handling lua, which is not necessarilly
true, and could in fact confuse us even more.

So here we take another approach, we add the BUSY flag to hlua context:
this flag is set by hlua_ctx_resume() around lua_resume() call, this way
we can precisely tell if the thread was handling lua when it was
interrupted, and we rely on this flag in debug functions to check if the
thread was effectively stuck inside lua or not while processing the stream

No backport needed unless a commit depends on it.

16 months agoBUG/MINOR: hlua: fix missing lock in hlua_filter_delete()
Aurelien DARRAGON [Mon, 11 Mar 2024 12:51:03 +0000 (13:51 +0100)] 
BUG/MINOR: hlua: fix missing lock in hlua_filter_delete()

hlua_filter_delete() calls hlua_unref() on the stream hlua stack, but
we should own the lock prior to manipulating the stack.

This should be backported up to 2.6.

16 months agoBUG/MINOR: hlua: missing lock in hlua_filter_new()
Aurelien DARRAGON [Mon, 11 Mar 2024 12:50:41 +0000 (13:50 +0100)] 
BUG/MINOR: hlua: missing lock in hlua_filter_new()

This is a complementary patch to 8670db7 ("BUG/MAJOR: hlua: improper lock
usage with hlua_ctx_resume()") for hlua_filter_new().

Indeed, the HLUA_E_ERRMSG case still relies on the lua stack but didn't
take the lock to do so.

This should be backported up to 2.6.

16 months agoBUG/MINOR: hlua: segfault when loading the same filter from different contexts
Aurelien DARRAGON [Mon, 11 Mar 2024 12:49:56 +0000 (13:49 +0100)] 
BUG/MINOR: hlua: segfault when loading the same filter from different contexts

Trying to register the same lua filter from global and per-thread context
(using 'lua-load' + 'lua-load-per-thread') causes a segmentation fault in
hlua_post_init().

This is due to a simple copy paste error as we try to print the function
name in the error message (like we do when loading the same lua function
from different contexts) instead of the filter name.

This should be backported up to 2.6.

16 months agoCI: github: add -DDEBUG_LIST to the default builds
William Lallemand [Wed, 13 Mar 2024 08:01:11 +0000 (09:01 +0100)] 
CI: github: add -DDEBUG_LIST to the default builds

Add the -DDEBUG_LIST flag which allow to check if a list element was
removed twice.

16 months agoCLEANUP: ssl: remove useless #ifdef in openssl-compat.h
William Lallemand [Wed, 13 Mar 2024 07:51:04 +0000 (08:51 +0100)] 
CLEANUP: ssl: remove useless #ifdef in openssl-compat.h

Remove a useless #ifdef in openssl-compat.h

16 months agoMEDIUM: ssl: allow to change the OpenSSL security level from global section
William Lallemand [Tue, 12 Mar 2024 15:22:34 +0000 (16:22 +0100)] 
MEDIUM: ssl: allow to change the OpenSSL security level from global section

The new "ssl-security-level" option allows one to change the OpenSSL
security level without having to change the openssl.cnf global file of
your distribution. This directives applies on every SSL_CTX context.

People sometimes change their security level directly in the ciphers
directive, however there are some cases when the security level change
is not applied in the right order (for example when applying a DH
param).

Before this patch, it was to possible to trick by using a specific
openssl.cnf file and start haproxy this way:

    OPENSSL_CONF=./openssl.cnf ./haproxy -f bug-2468.cfg

Values for the security level can be found there:

https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_security_level.html

This was discussed in github issue #2468.

16 months agoMEDIUM: ssl: initialize the SSL stack explicitely
William Lallemand [Tue, 12 Mar 2024 11:03:07 +0000 (12:03 +0100)] 
MEDIUM: ssl: initialize the SSL stack explicitely

In issue #2448, users are complaining that FIPS is not working correctly
since the removal of SSL_library_init().

This was removed because SSL_library_init() is deprecated with OpenSSL
3.x and emits a warning. But the initialization was not needed anymore
because it is done at the first openssl API call.

However it some cases it is needed. SSL_library_init() is now a define
to OPENSSL_init_ssl(0, NULL). This patch adds OPENSSL_init_ssl(0, NULL)
to the init.

This could be backported in every stable branches, however let's wait
before backporting it.

16 months agoBUG/MINOR: server: fix first server template not being indexed
Willy Tarreau [Tue, 12 Mar 2024 07:16:16 +0000 (08:16 +0100)] 
BUG/MINOR: server: fix first server template not being indexed

3.0-dev1 introduced a small regression with commit b4db3be86e ("BUG/MINOR:
server: fix server_find_by_name() usage during parsing"). By changing the
way servers are indexed and moving it into the server template loop, the
first one is no longer indexed because the loop starts at low+1 since it
focuses on duplication. Let's index the first one explicitly now.

This should not be backported, unless the commit above is backported.

16 months agoBUG/MINOR: ssl: do not set the aead_tag flags in sample_conv_aes_gcm()
Dragan Dosen [Mon, 11 Mar 2024 17:17:26 +0000 (18:17 +0100)] 
BUG/MINOR: ssl: do not set the aead_tag flags in sample_conv_aes_gcm()

This was not useful and was using uninitialized value. Introduced with
the commit 08ac28237 ("MINOR: Add aes_gcm_enc converter").

Must be backported wherever the commit 08ac28237 was backported.

16 months agoBUG/MINOR: ssl: fix possible ctx memory leak in sample_conv_aes_gcm()
Dragan Dosen [Mon, 11 Mar 2024 17:10:01 +0000 (18:10 +0100)] 
BUG/MINOR: ssl: fix possible ctx memory leak in sample_conv_aes_gcm()

The issue was introduced with the commit c31499d74 ("MINOR: ssl: Add
aes_gcm_dec converter").

This must be backported to all stable branches where the above converter
is present, but it may need to be adjusted for older branches because of
code refactoring.

16 months agoMINOR: tools: use public interface for FreeBSD get_exec_path()
Brooks Davis [Wed, 28 Feb 2024 18:12:40 +0000 (18:12 +0000)] 
MINOR: tools: use public interface for FreeBSD get_exec_path()

Where possible (FreeBSD 13+), use the public, documented interface to
the ELF auxiliary argument vector: elf_aux_info().

__elf_aux_vector is a private interface exported so that the runtime
linker can set its value during process startup and not intended for
public consumption.  In FreeBSD 15 it has been removed from libc and
moved to libsys.

16 months agoDOC: configuration: clarify ciphersuites usage (V2)
William Lallemand [Mon, 11 Mar 2024 14:48:14 +0000 (15:48 +0100)] 
DOC: configuration: clarify ciphersuites usage (V2)

The previous attempt removed the TLSv1.3 version for the
"ciphersuites" keywords. However it looks like the TLSv1.2 support for
SSL_CTX_set_ciphersuites() is a bug, and can have inconsistent behavior.

This patch revert the previous attempt and add explaining about this
problem and clear examples on how to configure TLSv1.2 ciphers + TLSv1.3
ciphersuites.

Revert "DOC: configuration: clarify ciphersuites usage"
This reverts commit e2a44d6c94b08d1bdf6294706c3b64267a13c86f.

This must be backported to all stable branches.

Fixes issue #2459.

16 months agoMINOR: quic: remove qc_treat_rx_crypto_frms()
Amaury Denoyelle [Fri, 8 Mar 2024 16:47:03 +0000 (17:47 +0100)] 
MINOR: quic: remove qc_treat_rx_crypto_frms()

This commit removes qc_treat_rx_crypto_frms(). This function was used in
a single place inside qc_ssl_provide_all_quic_data(). Besides, its
naming was confusing as conceptually it is directly linked to quic_ssl
module instead of quic_rx.

Thus, body of qc_treat_rx_crypto_frms() is inlined directly inside
qc_ssl_provide_all_quic_data(). Also, qc_ssl_provide_quic_data() is now
only used inside quic_ssl to its scope is set to static. Overall, API
for CRYPTO frame handling is now cleaner.

16 months agoMINOR: quic: simplify rescheduling for handshake
Amaury Denoyelle [Fri, 8 Mar 2024 16:40:16 +0000 (17:40 +0100)] 
MINOR: quic: simplify rescheduling for handshake

On CRYPTO frames reception, tasklet is rescheduled with TASK_HEAVY to
limit CPU consumption. This commit slighly simplifies this by regrouping
TASK_HEAVY setting and tasklet_wakeup() instructions in a single
location in qc_handle_crypto_frm(). All other unnecessary
tasklet_wakeup() are removed.

16 months agoMEDIUM: mux-h2: allow to set the glitches threshold to kill a connection
Willy Tarreau [Mon, 11 Mar 2024 06:33:44 +0000 (07:33 +0100)] 
MEDIUM: mux-h2: allow to set the glitches threshold to kill a connection

Till now it was still needed to write rules to eliminate bad behaving
H2 clients, while most of the time it would be desirable to just be able
to set a threshold on the level of anomalies on a connection.

This is what this patch does. By setting a glitches threshold for frontend
and backend, it allows to automatically turn a connection to the error
state when the threshold is reached so that the connection dies by itself
without having to write possibly complex rules.

One subtlety is that we still have the error state being exclusive to the
parser's state so this requires the h2c_report_glitches() function to return
a status indicating if the threshold was reached or not so that processing
can instantly stop and bypass the state update, otherwise the state could
be turned back to a valid one (e.g. after parsing CONTINUATION); we should
really contemplate the possibility to use H2_CF_ERROR for this. Fortunately
there were very few places where a glitch was reported outside of an error
path so the changes are quite minor.

Now by setting the front value to 1000, a client flooding with short
CONTINUATION frames is instantly stopped.

16 months agoMINOR: mux-h2: always use h2c_report_glitch()
Willy Tarreau [Mon, 11 Mar 2024 06:35:19 +0000 (07:35 +0100)] 
MINOR: mux-h2: always use h2c_report_glitch()

The function aims at centralizing counter measures but due to the fact
that it only increments the counter by one unit, sometimes it was not
used and the value was calculated directly. Let's pass the increment in
argument so that it can be used everywhere.

16 months ago[RELEASE] Released version 3.0-dev5 v3.0-dev5
Willy Tarreau [Sat, 9 Mar 2024 15:50:15 +0000 (16:50 +0100)] 
[RELEASE] Released version 3.0-dev5

Released version 3.0-dev5 with the following main changes :
    - BUG/MEDIUM: applet: Fix HTX .rcv_buf callback function to release outbuf buffer
    - BUG/MAJOR: ssl/ocsp: crash with ocsp when old process exit or using ocsp CLI
    - BUG/MEDIUM: server: fix dynamic servers initial settings
    - BUG/MINOR: ssl/cli: duplicate cleaning code in cli_parse_del_crtlist
    - LICENSE: event_hdl: fix GPL license version
    - LICENSE: http_ext: fix GPL license version
    - BUG/MEDIUM: mux-h1: Fix again 0-copy forwarding of chunks with an unknown size
    - BUG/MINOR: mux-h1: Properly report when mux is blocked during a nego
    - MINOR: mux-h1: Move checks performed before a shutdown in a dedicated function
    - MINOR: mux-h1: Move all stuff to detach a stream in an internal function
    - MAJOR: mux-h1: Drain requests on client side before shut a stream down
    - MEDIUM: htx/http-ana: No longer close connection on early HAProxy response
    - MINOR: quic: filter show quic by address
    - MINOR: quic: specify show quic output fields
    - MINOR: quic: add MUX output for show quic
    - CLEANUP: mux-h2: Fix h2s_make_data() comment about the return value
    - DOC: configuration: clarify ciphersuites usage
    - BUG/MINOR: config/quic: Alert about PROXY protocol use on a QUIC listener
    - BUG/MINOR: hlua: Fix log level to the right value when set via TXN:set_loglevel
    - MINOR: hlua: Be able to disable logging from lua
    - BUG/MINOR: tools: seed the statistical PRNG slightly better
    - BUG/MINOR: hlua: fix unsafe lua_tostring() usage with empty stack
    - BUG/MINOR: hlua: don't use lua_tostring() from unprotected contexts
    - BUG/MINOR: hlua: fix possible crash in hlua_filter_new() under load
    - BUG/MINOR: hlua: improper lock usage in hlua_filter_callback()
    - BUG/MINOR: hlua: improper lock usage in hlua_filter_new()
    - BUG/MEDIUM: hlua: improper lock usage with SET_SAFE_LJMP()
    - BUG/MAJOR: hlua: improper lock usage with hlua_ctx_resume()
    - BUG/MINOR: hlua: don't call ha_alert() in hlua_event_subscribe()
    - MINOR: hlua: use SEND_ERR to report errors in hlua_event_runner()
    - CLEANUP: hlua: txn class functions may LJMP
    - BUG/MINOR: sink: fix a race condition in the TCP log forwarding code
    - BUILD: thread: move lock label definitions to thread-t.h
    - BUILD: tree-wide: fix a few missing includes in a few files
    - BUILD: buf: make b_ncat() take a const for the source
    - CLEANUP: assorted typo fixes in the code and comments
    - CLEANUP: fix typo in naming for variable "unused"
    - CI: run more smoke tests on config syntax to check memory related issues
    - CI: enable monthly build only test on netbsd-9.3
    - CI: skip scheduled builds on forks
    - BUG/MINOR: ssl/cli: typo in new ssl crl-file CLI description
    - BUG/MEDIUM: quic: fix connection freeze on post handshake
    - BUG/MINOR: mux-quic: fix crash on aborting uni remote stream
    - CLEANUP: log: fix obsolete comment for add_sample_to_logformat_list()
    - CLEANUP: tree-wide: use proper ERR_* return values for PRE_CHECK fcts
    - BUG/MINOR: cfgparse: report proper location for log-format-sd errors
    - MINOR: vars: export var_set and var_unset functions
    - MINOR: Add aes_gcm_enc converter
    - BUG/MEDIUM: quic: fix handshake freeze under high traffic
    - MINOR: quic: always use ncbuf for rx CRYPTO
    - BUILD: ssl: define EVP_CTRL_AEAD_GET_TAG for older versions
    - DOC: design: write first notes about ring-v2
    - OPTIM: sink: try to merge "dropped" messages faster
    - OPTIM: sink: drop the sink lock used to count drops
    - DEV: haring: make haring not depend on the struct ring itself
    - DEV: haring: split the code between ring and buffer
    - DEV: haring: automatically use the advertised ring header size
    - BUILD: solaris: fix compilation errors

16 months agoBUILD: solaris: fix compilation errors
matthias sweertvaegher [Fri, 23 Feb 2024 16:05:01 +0000 (17:05 +0100)] 
BUILD: solaris: fix compilation errors

Compilation on solaris fails because of usage of names reserved on that
platform, i.e. 'queue' and 's_addr'.

This patch redefines 'queue' as '_queue' and renames 's_addr' to
'srv_addr' which fixes compilation for now.

Future plan: rename 'queue' in code base so define can be removed again.

Backporting: 2.9, 2.8

16 months agoDEV: haring: automatically use the advertised ring header size
Willy Tarreau [Mon, 4 Mar 2024 18:15:59 +0000 (19:15 +0100)] 
DEV: haring: automatically use the advertised ring header size

Instead of emitting a warning, since we don't need the ring struct
anymore, we can just read what we need, parse the buffer and use the
advertised offset. Thus for now -f is simply ignored.

16 months agoDEV: haring: split the code between ring and buffer
Willy Tarreau [Mon, 4 Mar 2024 18:12:33 +0000 (19:12 +0100)] 
DEV: haring: split the code between ring and buffer

By splitting the initialization and the parsing of the ring, we'll ease
the support for multiple ring sizes and get rid of the annoyances of the
optional lock.

16 months agoDEV: haring: make haring not depend on the struct ring itself
Willy Tarreau [Mon, 4 Mar 2024 18:04:09 +0000 (19:04 +0100)] 
DEV: haring: make haring not depend on the struct ring itself

haring needs to be self-sufficient about the ring format so that it continues
to build when the ring API changes. Let's import the struct ring definition
and call it "ring_v1".

16 months agoOPTIM: sink: drop the sink lock used to count drops
Willy Tarreau [Fri, 1 Mar 2024 18:22:04 +0000 (19:22 +0100)] 
OPTIM: sink: drop the sink lock used to count drops

The sink lock was made to prevent event producers from passing while
there were other threads trying to print a "dropped" message, in order
to guarantee the absence of reordering. It has a serious impact however,
which is that all threads need to take the read lock when producing a
regular trace even when there's no reader.

This patch takes a different approach. The drop counter is shifted left
by one so that the lowest bit is used to indicate that one thread is
already taking care of trying to dump the counter. Threads only read
this value normally, and will only try to change it if it's non-null,
in which case they'll first check if they are the first ones trying to
dump it, otherwise will simply count another drop and leave. This has
a large benefit. First, it will avoid the locking that causes stalls
as soon as a slow reader is present. Second, it avoids any write on the
fast path as long as there's no drop. And it remains very lightweight
since we just need to add +2 or subtract 2*dropped in operations, while
offering the guarantee that the sink_write() has succeeded before
unlocking the counter.

While a reader was previously limiting the traffic to 11k RPS under
4C/8T, now we reach 36k RPS vs 14k with no reader, so readers will no
longer slow the traffic down and will instead even speed it up due to
avoiding the contention down the chain in the ring. The locking cost
dropped from ~75% to ~60% now (it's in ring_write now).

16 months agoOPTIM: sink: try to merge "dropped" messages faster
Willy Tarreau [Fri, 1 Mar 2024 16:59:59 +0000 (17:59 +0100)] 
OPTIM: sink: try to merge "dropped" messages faster

When a reader doesn't read fast enough and causes drops, subsequent
threads try to produce a "dropped" message. But it takes time to
produce and emit this message, in part due to the use of chunk_printf()
that relies on vfprintf() which has to parse the printf format, and
during this time other threads may continue to increment the counter.
This is the reason why this is currently performed in a loop. When
reading what is received, it's common to see a large count followed
by one or two single-digit counts, indicating that we could possibly
have improved that by writing faster.

Let's improve the situation a little bit. First we're now using a
static message prefixed with enough space to write the digits, and a
call to ultoa_r() fills these digits from right to left so that we
don't have to process a format string nor perform a copy of the message.

Second, we now re-check the counter immediately after having prepared
the message so that we still get an opportunity for updating it. In
order to avoid too long loops, this is limited to 10 iterations.

Tests show that the number of single-digit "dropped" counters on output
now dropped roughly by 15-30%. Also, it was observed that with 8 threads,
there's almost never more than one retry.

16 months agoDOC: design: write first notes about ring-v2
Willy Tarreau [Wed, 21 Feb 2024 06:54:37 +0000 (07:54 +0100)] 
DOC: design: write first notes about ring-v2

This explains the observed limitations of the current ring applied to
traces and proposes a multi-step, more scalable, improvement.

16 months agoBUILD: ssl: define EVP_CTRL_AEAD_GET_TAG for older versions
Willy Tarreau [Fri, 8 Mar 2024 17:21:14 +0000 (18:21 +0100)] 
BUILD: ssl: define EVP_CTRL_AEAD_GET_TAG for older versions

Amaury reported that previous commit 08ac282375 ("MINOR: Add aes_gcm_enc
converter") broke the CI on OpenSSL 1.0.2 due to the define above not
existing there. Let's just map it to its older name when not existing.
For reference, these were renamed when switching to 1.1.0:

    https://marc.info/?l=openssl-cvs&m=142244190907706&w=2

No backport is needed.

16 months agoMINOR: quic: always use ncbuf for rx CRYPTO
Amaury Denoyelle [Fri, 8 Mar 2024 15:47:36 +0000 (16:47 +0100)] 
MINOR: quic: always use ncbuf for rx CRYPTO

The previous patch fix the handling of in-order CRYPTO frames which
requires the usage of a new buffer for these data as their handling is
delayed to run under TASK_HEAVY.

In fact, as now all CRYPTO frames handling must be delayed, their
handling can be unify. This is the purpose of this commit, which removes
the just introduced new buffer. Now, all CRYPTO frames are buffered
inside the ncbuf. Unused elements such as crypto_frms member for
encryption level are also removed.

This commit is not a bugcfix but is a direct follow-up to the last one.
As such, it can probably be backported with it to 2.9 to reduce code
differences between these versions.

16 months agoBUG/MEDIUM: quic: fix handshake freeze under high traffic
Amaury Denoyelle [Fri, 8 Mar 2024 14:19:22 +0000 (15:19 +0100)] 
BUG/MEDIUM: quic: fix handshake freeze under high traffic

QUIC relies on SSL_do_hanshake() to be able to validate handshake. As
this function is computation heavy, it is since 2.9 called only under
TASK_HEAVY. This has been implemented by the following patch :
  94d20be1388023bff36d795f501571adfefe8c75
  MEDIUM: quic: Heavy task mode during handshake

Instead of handling CRYPTO frames immediately during reception, this
patch delays the process to run under TASK_HEAVY tasklet. A frame copy
is stored in qel.rx.crypto_frms list. However, this frame still
reference the receive buffer. If the receive buffer is cleared before
the tasklet is rescheduled, it will point to garbage data, resulting in
haproxy decryption error. This happens if a fair amount of data is
received constantly to preempt the quic_conn tasklet execution.

This bug can be reproduced with a fair amount of clients. It is
exhibited by 'show quic full' which can report connections blocked on
handshake. Using the following commands result in h2load non able to
complete the last connections.

$ h2load --alpn-list h3 -t 8 -c 800 -m 10 -w 10 -n 8000 "https://127.0.0.1:20443/?s=10k"

Also, haproxy QUIC listener socket mode was active to trigger the issue.
This forces several connections to share the same reception buffer,
rendering the bug even more plausible to occur. It should be possible to
reproduce it with connection socket if increasing the clients amount.

To fix this bug, define a new buffer under quic_cstream. It is used
exclusively to copy CRYPTO data for in-order frame if ncbuf is empty.
This ensures data remains accessible even if receive buffer is cleared.

Note that this fix is only a temporary step. Indeed, a ncbuf is also
already used for out-of-order data. It should be possible to unify its
usage for both in and out-of-order data, rendering this new buffer
instance unnecessary. In this case, several unneeded elements will
become obsolete such as qel.rx.crypto_frms list. This will be done in a
future refactoring patch.

This must be backported up to 2.9.

16 months agoMINOR: Add aes_gcm_enc converter
Nenad Merdanovic [Tue, 5 Mar 2024 12:03:51 +0000 (13:03 +0100)] 
MINOR: Add aes_gcm_enc converter

The converter can be used to encrypt the raw byte input using the
AES-GCM algorithm, using provided nonce and key.

Co-authored-by: Dragan Dosen (ddosen@haproxy.com)
16 months agoMINOR: vars: export var_set and var_unset functions
Nenad Merdanovic [Tue, 5 Mar 2024 11:54:34 +0000 (12:54 +0100)] 
MINOR: vars: export var_set and var_unset functions

Co-authored-by: Dragan Dosen <ddosen@haproxy.com>
16 months agoBUG/MINOR: cfgparse: report proper location for log-format-sd errors
Aurelien DARRAGON [Wed, 28 Feb 2024 18:29:27 +0000 (19:29 +0100)] 
BUG/MINOR: cfgparse: report proper location for log-format-sd errors

When a parsing error occurs inside a log-format-sd expression, we report
the location of the log-format directive (which may not be set) instead
of reporting the proper log-format-sd directive location where the parsing
error occured.

 1|listen test
 2|  log-format "%B"      # no error
 3|  log-format-sd "%bad" # error

 | [ALERT]    (322261) : config : Parsing [empty.conf:2]: failed to parse log-format-sd : no such format variable 'bad'. If you wanted to emit the '%' character verbatim, you need to use '%%'.

The fix consists in using the config hints dedicated to log-format-sd
directive instead of the log-format one.

The bug was introduced in 8a4e4420 ("MEDIUM: log-format: Use standard
HAProxy log system to report errors").

This should be backported to every stable versions.

16 months agoCLEANUP: tree-wide: use proper ERR_* return values for PRE_CHECK fcts
Aurelien DARRAGON [Tue, 27 Feb 2024 15:12:40 +0000 (16:12 +0100)] 
CLEANUP: tree-wide: use proper ERR_* return values for PRE_CHECK fcts

httpclient_precheck(), ssl_ocsp_update_precheck(), and
resolvers_create_default() functions are registered through
REGISTER_PRE_CHECK() macro to be called by haproxy during init from the
pre_check_list list. When calling functions registered in pre_check_list,
haproxy expects ERR_* return values. However those 3 functions currently
use raw return values, so we better use explicit ERR_* macros to prevent
breakage in the future if ERR_* values mapping were to change.

16 months agoCLEANUP: log: fix obsolete comment for add_sample_to_logformat_list()
Aurelien DARRAGON [Thu, 22 Feb 2024 15:13:13 +0000 (16:13 +0100)] 
CLEANUP: log: fix obsolete comment for add_sample_to_logformat_list()

Since 833cc794 ("MEDIUM: sample: handle comma-delimited converter list")
logformat expressions now support having a comma-delimited converter list
right after the fetch. Let's remove a leftover comment from the initial
implementation that says otherwise.

16 months agoBUG/MINOR: mux-quic: fix crash on aborting uni remote stream
Amaury Denoyelle [Tue, 5 Mar 2024 14:14:08 +0000 (15:14 +0100)] 
BUG/MINOR: mux-quic: fix crash on aborting uni remote stream

A remote unidirectional stream can be aborted prematurely if application
layers cannot identify its type. In this case, a STOP_SENDING frame is
emitted.

Since QUIC MUX refactoring, a crash would occur in this scenario due to
2 specific characteristics of remote uni streams :
* qcs.tx.fctl was not initialized completely. This cause a crash due to
  BUG_ON() statement inside qcs_destroy().
* qcs.stream is never allocated. This caused qcs_prep_bytes() to crash
  inside qcc_io_send().

This bug is considered minor as it happens only on very specific QUIC
clients. It was detected when using s2n-quic over interop.

This does not need to be backported.

16 months agoBUG/MEDIUM: quic: fix connection freeze on post handshake
Amaury Denoyelle [Mon, 4 Mar 2024 17:41:39 +0000 (18:41 +0100)] 
BUG/MEDIUM: quic: fix connection freeze on post handshake

After handshake completion, QUIC server is responsible to emit
HANDSHAKE_DONE frame. Some clients wait for it to begin STREAM
transfers.

Previously, there was no explicit tasklet_wakeup() after handshake
completion, which is necessary to emit post-handshake frames. In most
cases, this was undetected as most client continue emission which will
reschedule the tasklet. However, as there is no tasklet_wakeup(), this
is not a consistent behavior. If this bug occurs, it causes a connection
freeze, preventing the client to emit any request. The connection is
finally closed on idle timeout.

To fix this, add an explicit tasklet_wakeup() after handshake
completion. It sounds simple enough but in fact it's difficult to find
the correct location efor tasklet_wakeup() invocation, as post-handshake
is directly linked to connection accept, with different orderings.
Notably, if 0-RTT is used, connection can be accepted prior handshake
completion. Another major point is that along HANDSHAKE_DONE frame, a
series of NEW_CONNECTION_ID frames are emitted. However, these new CIDs
allocation must occur after connection is migrated to its new thread as
these CIDs are tied to it. A BUG_ON() is present to check this in
qc_set_tid_affinity().

With all this in mind, 2 locations were selected for the necessary
tasklet_wakeup() :
* on qc_xprt_start() : this is useful for standard case without 0-RTT.
  This ensures that this is done only after connection thread migration.
* on qc_ssl_provide_all_quic_data() : this is done on handshake
  completion with 0-RTT used. In this case only, connection is already
  accepted and migrated, so tasklet_wakeup() is safe.

Note that as a side-change, quic_accept_push_qc() API has evolved to
better reflect differences between standard and 0-RTT usages. It is now
forbidden to call it multiple times on a single quic_conn instance. A
BUG_ON() has been added.

This issue is labelled as medium even though it seems pretty rare. It
was only reproducible using QUIC interop runner, with haproxy compiled
with LibreSSL with quic-go as client. However, affected code parts are
pretty sensible, which justify the chosen severity.

This should fix github issue #2418.

It should be backported up to 2.6, after a brief period of observation.
Note that the extra comment added in qc_set_tid_affinity() can be
removed in 2.6 as thread migration is not implemented for this version.
Other parts should apply without conflict.

16 months agoBUG/MINOR: ssl/cli: typo in new ssl crl-file CLI description
William Lallemand [Tue, 5 Mar 2024 13:49:17 +0000 (14:49 +0100)] 
BUG/MINOR: ssl/cli: typo in new ssl crl-file CLI description

The `new ssl crl-file` option description on the CLI lacks the dash.

Must be backported as far as 2.6.

16 months agoCI: skip scheduled builds on forks
Ilya Shipitsin [Wed, 21 Feb 2024 16:05:39 +0000 (17:05 +0100)] 
CI: skip scheduled builds on forks

tracking bleeding edge changes with some rare platforms or modern
compilers on scheduled basis is not what usually forks do. let's
skip by default in forks, if some fork is interested, it might be
enabled locally

16 months agoCI: enable monthly build only test on netbsd-9.3
Ilya Shipitsin [Mon, 19 Feb 2024 21:14:59 +0000 (22:14 +0100)] 
CI: enable monthly build only test on netbsd-9.3

it is interesting to try https://github.com/vmactions/netbsd-vm actions

16 months agoCI: run more smoke tests on config syntax to check memory related issues
Ilya Shipitsin [Sat, 17 Feb 2024 19:42:28 +0000 (20:42 +0100)] 
CI: run more smoke tests on config syntax to check memory related issues

config syntax check seems add a value on testing code path not
covered by VTest, also checks are very fast

16 months agoCLEANUP: fix typo in naming for variable "unused"
Ilya Shipitsin [Thu, 22 Feb 2024 09:12:27 +0000 (10:12 +0100)] 
CLEANUP: fix typo in naming for variable "unused"

In resolvers.c:rslv_promex_next_ts() and in
stick-tables.c:stk_promex_next_ts(), an unused argument was mistakenly
called "unsued" instead of "unused". Let's fix this in a separate patch
so that it can be omitted from backports if this causes build problems.

16 months agoCLEANUP: assorted typo fixes in the code and comments
Ilya Shipitsin [Thu, 22 Feb 2024 09:12:27 +0000 (10:12 +0100)] 
CLEANUP: assorted typo fixes in the code and comments

This is 39th iteration of typo fixes
The naming issue on the argument called "unsued" instead of "unused"
in two functions from resolvers and stick-tables was put into a second
patch so that it can be omitted if it were to cause backport issues.

16 months agoBUILD: buf: make b_ncat() take a const for the source
Willy Tarreau [Tue, 27 Feb 2024 18:06:41 +0000 (19:06 +0100)] 
BUILD: buf: make b_ncat() take a const for the source

In 2.7 with commit 35df34223b ("MINOR: buffers: split b_force_xfer() into
b_cpy() and b_force_xfer()"), b_ncat() was extracted from b_force_xfer()
but kept its source variable instead of constant, making it unusable for
calls from a const source. Let's just fix it.

16 months agoBUILD: tree-wide: fix a few missing includes in a few files
Willy Tarreau [Wed, 14 Feb 2024 07:41:11 +0000 (08:41 +0100)] 
BUILD: tree-wide: fix a few missing includes in a few files

Some include files, mostly types definitions, are missing a few includes
to define the types they're using, causing include ordering dependencies
between files, which are most often not seen due to the alphabetical
order of includes. Let's just fix them.

These were spotted by building pre-compiled headers for all these files
to .h.gch.

16 months agoBUILD: thread: move lock label definitions to thread-t.h
Willy Tarreau [Wed, 14 Feb 2024 07:39:57 +0000 (08:39 +0100)] 
BUILD: thread: move lock label definitions to thread-t.h

The 'lock_label' enum is defined in thread.h but it's used in a few
type files, so let's move it to thread-t.h to allow explicit includes.

16 months agoBUG/MINOR: sink: fix a race condition in the TCP log forwarding code
Willy Tarreau [Tue, 27 Feb 2024 16:32:44 +0000 (17:32 +0100)] 
BUG/MINOR: sink: fix a race condition in the TCP log forwarding code

That's exactly the same as commit 53bfab080c ("BUG/MINOR: sink: fix a race
condition between the writer and the reader") that went into 2.7 and was
backported as far as 2.4, except that since the code was duplicated, the
second instance was not noticed, leaving the race present. The race has
a limited impact, if a forwarder reaches the end of the logs and a new
message arrives before it leaves, the forwarder will only wake up after
yet another new message will be sent. In practice it remains unnoticeable
because for the race to trigger, one needs to have a steady flow of logs,
which means the wakeup will happen anyway.

This should be backported, but no need to insist on it if it resists.

16 months agoCLEANUP: hlua: txn class functions may LJMP
Aurelien DARRAGON [Fri, 1 Mar 2024 20:09:40 +0000 (21:09 +0100)] 
CLEANUP: hlua: txn class functions may LJMP

Clarify that some txn related class functions may LJMP by adding the
__LJMP tag to their prototype.

16 months agoMINOR: hlua: use SEND_ERR to report errors in hlua_event_runner()
Aurelien DARRAGON [Mon, 4 Mar 2024 10:19:46 +0000 (11:19 +0100)] 
MINOR: hlua: use SEND_ERR to report errors in hlua_event_runner()

Instead of reporting lua errors using ha_alert(), let's use SEND_ERR()
helper which will also try to generate a log message according to lua
log settings.

16 months agoBUG/MINOR: hlua: don't call ha_alert() in hlua_event_subscribe()
Aurelien DARRAGON [Mon, 4 Mar 2024 15:31:23 +0000 (16:31 +0100)] 
BUG/MINOR: hlua: don't call ha_alert() in hlua_event_subscribe()

hlua_event_subscribe() is meant to be called from a protected lua env
during init and/or runtime. As such, only hlua_event_sub() makes uses
of it: when an error happens hlua_event_sub() will already raise a Lua
exception. Thus it's not relevant to use ha_alert() there as it could
generate log pollution (error is relevant from Lua script point of view,
not from haproxy one).

This could be backported in 2.8.

16 months agoBUG/MAJOR: hlua: improper lock usage with hlua_ctx_resume()
Aurelien DARRAGON [Fri, 1 Mar 2024 20:17:51 +0000 (21:17 +0100)] 
BUG/MAJOR: hlua: improper lock usage with hlua_ctx_resume()

hlua_ctx_resume() itself can safely be used as-is in a multithreading
context because it takes care of taking the lua lock.

However, when hlua_ctx_resume() returns, the lock is released and it is
thus the caller's responsibility to ensure it owns the lock prior to
performing additional manipulations on the Lua stack. Unfortunately, since
early haproxy lua implementation, we used to do it wrong:

The most common hlua_ctx_resume() pattern we can find in the code (because
it was duplicated over and over over time) is the following:

  |ret = hlua_ctx_resume()
  |switch (ret) {
  |        case HLUA_E_OK:
  |        break;
  |        case HLUA_E_ERRMSG:
  |        break;
  |        [...]
  |}

Problem is: for some of the switch cases, we still perform lua stack
manipulations. This is the case for the HLUA_E_ERRMSG for instance where
we often use lua_tostring() to retrieve last lua error message on the top
of the stack, or sometimes for the HLUA_E_OK case, when we need to perform
some lua cleanup logic once the resume ended. But all of this is done
WITHOUT the lua lock, so this means that the main lua stack could be
accessed simultaneously by concurrent threads when a script was loaded
using 'lua-load'.

While it is not critical for switch-cases dedicated to error handling,
(those are not supposed to happen very often), it can be very problematic
for stack manipulations occuring in the HLUA_E_OK case under heavy load
for instance. In this case, main lua stack corruptions will eventually
happen. This is especially true inside hlua_filter_new(), where this bug
was known to cause lua stack corruptions under load, leading to lua errors
and even crashing the process as reported by @bgrooot in GH #2467.

The fix is relatively simple, once hlua_ctx_resume() returns: we should
consider that ANY lua stack access should be lua-lock protected. If the
related lua calls may raise lua errors, then (RE)SET_SAFE_LJMP
combination should be used as usual (it allows to lock the lua stack and
catch lua exceptions at the same time), else hlua_{lock,unlock} may be
used if no exceptions are expected.

This patch should fix GH #2467.

It should be backported to all stable versions.

[ada: some ctx adj will be required for older versions as event_hdl
 doesn't exist prior to 2.8 and filters were implemented in 2.5, thus
 some chunks won't apply]

16 months agoBUG/MEDIUM: hlua: improper lock usage with SET_SAFE_LJMP()
Aurelien DARRAGON [Mon, 4 Mar 2024 10:17:58 +0000 (11:17 +0100)] 
BUG/MEDIUM: hlua: improper lock usage with SET_SAFE_LJMP()

When we want to perform some unsafe lua stack manipulations from an
unprotected lua environment, we use SET_SAFE_LJMP() RESET_SAFE_LJMP()
combination to lock lua stack and catch potential lua exceptions that
may occur between the two.

Hence, we regularly find this pattern (duplicated over and over):

  |if (!SET_SAFE_LJMP(hlua)) {
  |        const char *error;
  |
  |        if (lua_type(hlua->T, -1) == LUA_TSTRING)
  |                error = hlua_tostring_safe(hlua->T, -1);
  |         else
  |                error = "critical error";
  |        SEND_ERR(NULL, "*: %s.\n", error);
  |}

This is wrong because when SET_SAFE_LJMP() returns false (meaning that an
exception was caught), then the lua lock was released already, thus the
caller is not expected to perform lua stack manipulations (because the
main lua stack may be shared between multiple threads). In the pattern
above we only want to retrieve the lua exception message which may be
found at the top of the stack, to do so we now explicitly take the lua
lock before accessing the lua stack. Note that hlua_lock() doesn't catch
lua exceptions so only safe lua functions are expected to be used there
(lua functions that may NOT raise exceptions).

It should be backported to every stable versions.

[ada: some ctx adj will be required for older versions as event_hdl
 doesn't exist prior to 2.8 and filters were implemented in 2.5, thus
 some chunks won't apply, but other fixes should stay relevant]

16 months agoBUG/MINOR: hlua: improper lock usage in hlua_filter_new()
Aurelien DARRAGON [Mon, 4 Mar 2024 10:25:47 +0000 (11:25 +0100)] 
BUG/MINOR: hlua: improper lock usage in hlua_filter_new()

In hlua_filter_new(), after each hlua resume, we systematically try to
empty the stack by calling lua_settop(). However we're doing this without
locking the lua context, so it is unsafe in multithreading context if the
script is loaded using 'lua-load'. To fix the issue, we protect the call
with hlua_{lock,unlock}() helpers.

This should be backported up to 2.6.

16 months agoBUG/MINOR: hlua: improper lock usage in hlua_filter_callback()
Aurelien DARRAGON [Mon, 4 Mar 2024 10:06:24 +0000 (11:06 +0100)] 
BUG/MINOR: hlua: improper lock usage in hlua_filter_callback()

In hlua_filter_callback(), some lua stack work is performed under
SET_SAFE_LJMP() guard which also takes care of locking the hlua context
when needed. However, a lua_gettop() call is performed out of the guard,
thus it is unsafe in multithreading context if the script is loaded using
'lua-load' because in this case the main lua stack is shared between
threads and each access to a lua stack must be performed under the lock,
thus we move lua_gettop() call under the lock.

It should be backported up to 2.6.

16 months agoBUG/MINOR: hlua: fix possible crash in hlua_filter_new() under load
Aurelien DARRAGON [Mon, 4 Mar 2024 08:39:58 +0000 (09:39 +0100)] 
BUG/MINOR: hlua: fix possible crash in hlua_filter_new() under load

hlua_filter_new() handles memory allocation errors by jumping to the
"end:" cleanup label in case of errors. Such errors may happen when the
system is heavily loaded for instance.

In hlua_filter_new(), we try to allocate two hlua contexts in a row before
checking if one of them failed (in which case we jump to the cleanup part
of the function), and only then we initialize them both.

If a memory allocation failure happens for only one out of the two
flt_ctx->hlua[] contexts pair, we still jump to the cleanup part.
It means that the hlua context that was successfully allocated and wasn't
initialized yet will be passed to hlua_ctx_destroy(), resulting in invalid
reads in the cleanup function, which may ultimately cause the process to
crash.

To fix the issue: we make sure flt_ctx hlua contexts are initialized right
after they are allocated, that is before any error handling condition that
may force the cleanup.

This bug was discovered when trying to reproduce GH #2467 with haproxy
started with "-dMfail" argument.

It should be backported up to 2.6.

16 months agoBUG/MINOR: hlua: don't use lua_tostring() from unprotected contexts
Aurelien DARRAGON [Fri, 1 Mar 2024 14:55:17 +0000 (15:55 +0100)] 
BUG/MINOR: hlua: don't use lua_tostring() from unprotected contexts

As per lua documentation, lua_tostring() may raise a memory error.
However, we're often using it to fetch the error message at the top of
the stack (ie: after a failing lua call) from unprotected environments.
In practise, lua_tostring() has rare chances of failing, but still, if
it happens to be the case, it could crash the process and we better not
risk it.

So here, we add hlua_tostring_safe() function, which works exactly as
lua_tostring(), but the function cannot LJMP as it will catch
lua_tostring() exceptions to return NULL instead.

Everywhere lua_tostring() was used to retrieve error string from such
unprotected contexts, we now rely on hlua_tostring_safe().

This should be backported to all stable versions.

[ada: ctx adj will be required, for versions prior to 2.8 event_hdl
 API didn't exist so some chunks won't apply, and prior to 2.5 filters
 API didn't exist either, so again, some chunks should be ignored]

16 months agoBUG/MINOR: hlua: fix unsafe lua_tostring() usage with empty stack
Aurelien DARRAGON [Fri, 1 Mar 2024 18:54:16 +0000 (19:54 +0100)] 
BUG/MINOR: hlua: fix unsafe lua_tostring() usage with empty stack

Lua documentation says that lua_tostring() returns a pointer that remains
valid as long as the object is not removed from the stack.

However there are some places were we use the returned string AFTER the
corresponding object is removed from the stack. In practise this doesn't
seem to cause visible bugs (probably because the pointer remains valid
waiting for a GC cycle), but let's fix that to comply with the
documentation and avoid undefined behavior.

It should be backported in all stable versions.

16 months agoBUG/MINOR: tools: seed the statistical PRNG slightly better
Willy Tarreau [Fri, 1 Mar 2024 15:17:47 +0000 (16:17 +0100)] 
BUG/MINOR: tools: seed the statistical PRNG slightly better

Thomas Baroux reported a very interesting issue. "balance random" would
systematically assign the same server first upon restart. That comes from
its use of statistical_prng() which is only seeded with the thread number,
and since at low loads threads are assigned to incoming connections in
round robin order, practically speaking, the same thread always gets the
same request and will produce the same random number.

We already have a much better RNG that's also way more expensive, but we
can use it at boot time to seed the PRNG instead of using the thread ID
only.

This needs to be backported to 2.4.

16 months agoMINOR: hlua: Be able to disable logging from lua
Christopher Faulet [Thu, 29 Feb 2024 14:41:17 +0000 (15:41 +0100)] 
MINOR: hlua: Be able to disable logging from lua

Add core.silent (-1) value to be able to disable logging via
TXN:set_loglevel() call. Otherwise, there is no way to do so and it may be
handy. This special value cannot be used with TXN:log() function.

This patch may be backported if necessary.

16 months agoBUG/MINOR: hlua: Fix log level to the right value when set via TXN:set_loglevel
Christopher Faulet [Thu, 29 Feb 2024 14:37:43 +0000 (15:37 +0100)] 
BUG/MINOR: hlua: Fix log level to the right value when set via TXN:set_loglevel

When the log level is changed in lua, by calling TXN:set_loglevel function,
it must be incremented by one because it is decremented in strm_log()
function.

This patch must be backport to all stable versions.

16 months agoBUG/MINOR: config/quic: Alert about PROXY protocol use on a QUIC listener
Christopher Faulet [Thu, 29 Feb 2024 13:27:45 +0000 (14:27 +0100)] 
BUG/MINOR: config/quic: Alert about PROXY protocol use on a QUIC listener

PROXY procotol is not supported on QUIC for now. Thus return an error during
configuration parsing if 'accept-proxy' option is used for a QUIC listener.

This patch should fix the issue #2186. It should be backport as far as 2.6.

16 months agoDOC: configuration: clarify ciphersuites usage
William Lallemand [Thu, 29 Feb 2024 17:04:12 +0000 (18:04 +0100)] 
DOC: configuration: clarify ciphersuites usage

Ciphersuites can be used with any TLS/SSL protocol version and are not
specific to TLSv1.3. However you can only specify the TLSv1.3 ciphers in
ciphersuite format.

Should fix issue #2459.

Backport to every stable branches.

16 months agoCLEANUP: mux-h2: Fix h2s_make_data() comment about the return value
Christopher Faulet [Thu, 29 Feb 2024 12:52:35 +0000 (13:52 +0100)] 
CLEANUP: mux-h2: Fix h2s_make_data() comment about the return value

2 return values are specified in the h2s_make_data() function comment. Both
are more or less equivalent but the later is probably more accurate. So,
keep the right one and remove the other one.

This patch should fix the issue #2175.

16 months agoMINOR: quic: add MUX output for show quic
Amaury Denoyelle [Fri, 23 Feb 2024 16:32:14 +0000 (17:32 +0100)] 
MINOR: quic: add MUX output for show quic

Extend "show quic" to be able to dump MUX related information. This is
done via the new function qcc_show_quic(). This replaces the old streams
dumping list which was incomplete.

These info are displayed on full output or by specifying "mux" field.

16 months agoMINOR: quic: specify show quic output fields
Amaury Denoyelle [Mon, 26 Feb 2024 08:57:05 +0000 (09:57 +0100)] 
MINOR: quic: specify show quic output fields

Add the possibility to customize show quic full output with only a
specific set of printed fields. This is specified as a comma-separated
list. Here are the currently supported values :
* tp: transport parameters
* sock: connection addresses and socket FD
* pktns: packet number space with ack ranges and in flight bytes
* cc: congestion controler and loss information

Note that streams output is not filtered by this mechanism. It's because
it will be replaced soon by an output generated from the MUX which will
use its owned field name.

16 months agoMINOR: quic: filter show quic by address
Amaury Denoyelle [Mon, 26 Feb 2024 09:56:30 +0000 (10:56 +0100)] 
MINOR: quic: filter show quic by address

Add the possibilty to restrict show quic output to only a single
connection. This is done by specifying a quic_conn address pointer.

Default format selection has evolved with it. Indeed, it seems more
fitting to use full format by default when filtering on a connection.
However, it's still possible to revert to the original oneline format
with it by specifying it explicitely.

16 months agoMEDIUM: htx/http-ana: No longer close connection on early HAProxy response
Christopher Faulet [Mon, 26 Feb 2024 07:36:58 +0000 (08:36 +0100)] 
MEDIUM: htx/http-ana: No longer close connection on early HAProxy response

When a response was returned by HAProxy, a dedicated HTX flag was
set. Thanks to this flag, it was possible to add a "connection: close"
header to the response if the request was not fully received and to close
the connection. In the same way, when a redirect rule was applied,
keep-alive was forcefully disabled for unfinished requests.

All these mechanisms are now useless because the H1 mux is able to drain the
response. So HTX_FL_PROXY_RESP flag is removed and no special processing is
performed on HAProxy response when the request is unfinished.

16 months agoMAJOR: mux-h1: Drain requests on client side before shut a stream down
Christopher Faulet [Mon, 26 Feb 2024 06:50:23 +0000 (07:50 +0100)] 
MAJOR: mux-h1: Drain requests on client side before shut a stream down

unlike for H2 and H3, there is no mechanism in H1 to notify the client it
must stop to upload data when a response is replied before the end of the
request without closing the connection. There is no RST_STREAM frame
equivalent.

Thus, there is only two ways to deal with this situation: closing the
connection or draining the request. Until now, HAProxy didn't support
draining H1 messages. Closing the connection in this case has however a
major drawback. It leads to send a TCP reset, dropping this way all in-fly
data. There is no warranty the client has fully received the response.

Draining H1 messages was never implemented because in old versions it was a
bit tricky to implement. However, it is now far simplier to support this
feature because it is possible to have a H1 stream without any applicative
stream. It is the purpose of this patch. Now, when a shutdown is requested
and the stream is detached from the connection, if the request is unfinished
while the response was fully sent, the request in drained.

To do so, in this case the shutdown and the detach are delayed. From the
upper layer point of view, there is no changes. The endpoint is shut down
and detached as usual. But on H1 mux point of view, the H1 stream is still
alive and is being able to drain data. However the stream-endpoint
descriptor is orphan. Once the request is fully received (and drained), the
connection is shut down if it cannot be reused for a new transaction and the
H1 stream is destroyed.

16 months agoMINOR: mux-h1: Move all stuff to detach a stream in an internal function
Christopher Faulet [Mon, 26 Feb 2024 06:44:52 +0000 (07:44 +0100)] 
MINOR: mux-h1: Move all stuff to detach a stream in an internal function

All code from h1_detach() function was moved in a internal function,
h1s_finish_detach(). It will be used to defer the detach and be able to
drain the requests payload.

16 months agoMINOR: mux-h1: Move checks performed before a shutdown in a dedicated function
Christopher Faulet [Mon, 26 Feb 2024 06:35:50 +0000 (07:35 +0100)] 
MINOR: mux-h1: Move checks performed before a shutdown in a dedicated function

Checks performed in h1_shutw() to determine if the connection must be
shutdown now or not was move in a dedicated function. This will be used to
be able to drain the requests payload.

16 months agoBUG/MINOR: mux-h1: Properly report when mux is blocked during a nego
Christopher Faulet [Wed, 28 Feb 2024 13:46:56 +0000 (14:46 +0100)] 
BUG/MINOR: mux-h1: Properly report when mux is blocked during a nego

During a zero-copy forwarding negociation, if the H1 mux is blocked for any
reason, the IOBUF_FL_FF_BLOCKED flag must be set on its iobuf to notfiy the
producer it must wait. However, there were two places where it was not
performed: when the output buffer allocation failed and when the chunk
formatting failed.

This patch fixes the issue. It must be backported to 2.9.

16 months agoBUG/MEDIUM: mux-h1: Fix again 0-copy forwarding of chunks with an unknown size
Christopher Faulet [Wed, 28 Feb 2024 07:01:06 +0000 (08:01 +0100)] 
BUG/MEDIUM: mux-h1: Fix again 0-copy forwarding of chunks with an unknown size

There is still an issue with zero-copy forwarding of chunks with an unknown
size. It is possible for a producer to fill the sapce reserved for the CRLF
at the end of the chunk. The root cause is that this space is not accounted
in the iobuf offset. So, from the producer point of view, the space may be
used. We can also argue the current design for iobuf is not well suited for
this case. Instead of using a pointer on the consumer's buffer, it could be
easier to use a custom buffer built on top of the consumer one, via a call
to b_make(), with the size, head and data field reflecting the avaialble
space the producer can use.

By the way, because of this bug, it is possible to trigger a BUG_ON() when
we try to write the CRLF at the end of the chunk because the buffer is
full. It is unexpected. Only the stats applet may hit this bug.

To fix the issue, instead of writting this CRLF when the current chunk is
consumed, it is written before consuming the next one. This way, all space
reserved to create the chunk formatting is always placed before forwarding
data.

No backport needed.

16 months agoLICENSE: http_ext: fix GPL license version
Aurelien DARRAGON [Wed, 28 Feb 2024 10:25:31 +0000 (11:25 +0100)] 
LICENSE: http_ext: fix GPL license version

This is a followup of the previous commit: GH user @songliumeng initially
reported an issue with the GPL license version for event_hdl source file
which was fixed by the previous commit. It turns out the same mistake was
made in http_ext source file: due to a mixup between LGPL and GPL, GPL
version '2.1' was referenced instead of '2'.

Again, clarify that this is indeed GPL by making use of the banner
provided in doc/gpl.txt

This should be backported in 2.8 with b2bb925 ("MINOR: proxy/http_ext:
introduce proxy forwarded option")

16 months agoLICENSE: event_hdl: fix GPL license version
Aurelien DARRAGON [Wed, 28 Feb 2024 10:22:49 +0000 (11:22 +0100)] 
LICENSE: event_hdl: fix GPL license version

As spotted by user @songliumeng in GH #2463, there was a mixup between
LGPL and GPL in event_hdl source file: GPL version '2.1' was referenced
instead of '2'. Clarify that this is indeed GPL by making use of the
banner provided in doc/gpl.txt.

This should be backported in 2.8 with 68e692d ("MINOR: event_hdl: add
event handler base api")

16 months agoBUG/MINOR: ssl/cli: duplicate cleaning code in cli_parse_del_crtlist
William Lallemand [Tue, 27 Feb 2024 16:22:15 +0000 (17:22 +0100)] 
BUG/MINOR: ssl/cli: duplicate cleaning code in cli_parse_del_crtlist

Since 23cab33 ("BUG/MINOR: ssl: Clear the ckch instance when deleting a
crt-list line"), LIST_DELETE is done twice, one time in
cli_parse_del_crtlist() and another time in ckch_inst_free().

It could trigger a crash with -DDEBUG_LIST.

This isn't a major problem since the ptr is not freed in the meantime so
it will only trigger with the debug.

This patch removes the LIST_DELETE as well as the loop done on link_ref
which is also don in ckch_inst_free()

Could be backported as far as 2.4. 2.4 version does not have a link_ref
loop.

16 months agoBUG/MEDIUM: server: fix dynamic servers initial settings
Amaury Denoyelle [Tue, 27 Feb 2024 14:33:59 +0000 (15:33 +0100)] 
BUG/MEDIUM: server: fix dynamic servers initial settings

Contrary to static servers, dynamic servers does not initialize their
settings from a default server instance. As such, _srv_parse_init() was
responsible to set a set of minimal values to have a correct behavior.

However, some settings were not properly initialized. This caused
dynamic servers to not behave as static ones without explicit
parameters.

Currently, the main issue detected is connection reuse which was
completely impossible. This is due to incorrect pool_purge_delay and
max_reuse settings incompatible with srv_add_to_idle_list().

To fix the connection reuse, but also more generally to ensure dynamic
servers are aligned with other server instances, define a new function
srv_settings_init(). This is used to set initial values for both default
servers and dynamic servers. For static servers, srv_settings_cpy() is
kept instead, using their default server as reference.

This patch could have unexpected effects on dynamic servers behavior as
it restored proper initial settings. Previously, they were set to 0 via
calloc() invocation from new_server().

This should be backported up to 2.6, after a brief period of
observation.

16 months agoBUG/MAJOR: ssl/ocsp: crash with ocsp when old process exit or using ocsp CLI
William Lallemand [Mon, 26 Feb 2024 16:53:02 +0000 (17:53 +0100)] 
BUG/MAJOR: ssl/ocsp: crash with ocsp when old process exit or using ocsp CLI

This patch reverts 2 fixes that were made in an attempt to fix the
ocsp-update feature used with the 'commit ssl cert' command.

The patches crash the worker when doing a soft-stop when the 'set ssl
ocsp-response' command was used, or during runtime if the ocsp-update
was used.

This was reported in issue #2462 and #2442.

The last patch reverted is the associated reg-test.

Revert "BUG/MEDIUM: ssl: Fix crash when calling "update ssl ocsp-response" when an update is ongoing"
This reverts commit 5e66bf26ecbf6439fafc8ef8857abe22e0874f4d.

Revert "BUG/MEDIUM: ocsp: Separate refcount per instance and per store"
This reverts commit 04b77f84d1b52185fc64735d7d81137479d68b00.

Revert "REGTESTS: ssl: Add OCSP related tests"
This reverts commit acd1b85d3442fc58164bd0fb96e72f3d4b501d15.

16 months agoBUG/MEDIUM: applet: Fix HTX .rcv_buf callback function to release outbuf buffer
Christopher Faulet [Mon, 26 Feb 2024 15:34:43 +0000 (16:34 +0100)] 
BUG/MEDIUM: applet: Fix HTX .rcv_buf callback function to release outbuf buffer

In appctx_htx_rcv_buf(), HTX blocks found in the appctx output buffer are
copied into the channel buffer. At the end, the state of the underlying
buffer must be updated. If everything was copied, the buffer is reset. This
way, it will be released later, at the end of the applet process function.

However, here there was a typo. We do it on the input buffer instead of the
output buffer. As side effect, an empty HTX message remained stuck in the
appctx outbut buffer, blocking the applet and leading to blocked session
with no expiration date.

No backport needed.

16 months ago[RELEASE] Released version 3.0-dev4 v3.0-dev4
Willy Tarreau [Fri, 23 Feb 2024 19:01:45 +0000 (20:01 +0100)] 
[RELEASE] Released version 3.0-dev4

Released version 3.0-dev4 with the following main changes :
    - BUG/MEDIUM: ssl: Fix crash when calling "update ssl ocsp-response" when an update is ongoing
    - BUG/MEDIUM: quic: Wrong K CUBIC calculation.
    - MINOR: quic: Update K CUBIC calculation (RFC 9438)
    - MINOR: quic: Dynamic packet reordering threshold
    - MINOR: quic: Add a counter for reordered packets
    - BUG/MAJOR: mux-h1: Fix zero-copy forwarding when sending chunks of unknown size
    - MINOR: stats: Use a dedicated function to check if output is almost full
    - BUG/MEDIUM: applet: Add a flag to state an applet is using zero-copy forwarding
    - BUG/MEDIUM: stconn/applet: Block 0-copy forwarding if producer needs more room
    - MINOR: applet: Remove uselelss test on SE_FL_SHR/SHW flags
    - MEDIUM: applet: Add notion of shutdown for write for applets
    - MINOR: cli: No longer check SC for shutdown to interrupt wait command
    - BUG/MEDIUM: stconn: Allow expiration update when READ/WRITE event is pending
    - BUG/MEDIUM: stconn: Don't check pending shutdown to wake an applet up
    - CLEANUP: stconn: Move SE flags set by app layer at the end of the bitfield
    - MINOR: stconn: Rename SE_FL_MAY_FASTFWD and reorder bitfield
    - MINOR: stconn: Add SE flag to announce zero-copy forwarding on consumer side
    - MINOR: muxes: Announce support for zero-copy forwarding on consumer side
    - BUG/MAJOR: stconn: Check support for zero-copy forwarding on both sides
    - MINOR: muxes/applet: Simplify checks on options to disable zero-copy forwarding
    - BUG/MINOR: quic: reject unknown frame type
    - MINOR: quic: handle all frame types on reception
    - BUG/MINOR: quic: reject HANDSHAKE_DONE as server
    - BUG/MINOR: qpack: reject invalid increment count decoding
    - BUG/MINOR: qpack: reject invalid dynamic table capacity
    - DOC/MINOR: userlists: mention solutions to high cpu with hashes
    - DOC: quic: Missing tuning setting in "Global parameters"
    - BUG/MEDIUM: applet: Immediately free appctx on early error
    - BUG/MEDIUM: hlua: Be able to garbage collect uninitialized lua sockets
    - BUG/MEDIUM: hlua: Don't loop if a lua socket does not consume received data
    - BUG/MEDIUM: quic: fix transient send error with listener socket
    - MINOR: log: custom name for logformat node
    - MINOR: sample: add type_to_smp() helper function
    - MINOR: log: explicit typecasting for logformat nodes
    - MINOR: log: simplify last_isspace in sess_build_logline()
    - MINOR: log: simplify quotes handling in sess_build_logline()
    - MINOR: log: print metadata prefixes separately in sess_build_logline()
    - MINOR: log: automate string array construction in sess_build_logline()
    - DOC: quic: fix recommandation for bind on multiple address
    - MINOR: quic: warn on bind on multiple addresses if no IP_PKTINFO support
    - OPTIM: quic: improve slightly qc_snd_buf() internal
    - MINOR: quic: move IP_PKTINFO on send on a dedicated function
    - MINOR: quic: remove sendto() usage variant
    - MINOR: quic: only use sendmsg() syscall variant
    - BUILD: applet: fix build on some 32-bit archs
    - BUG/MINOR: quic: initialize msg_flags before sendmsg
    - BUG/MEDIUM: mux-h1: Don't emit 0-CRLF chunk in h1_done_ff() when iobuf is empty
    - CLEANUP: proxy/log: remove unused proxy flag
    - CLEANUP: log: fix process_send_log() indentation
    - CLEANUP: log: use free_logformat_list() in parse_logformat_string()
    - MINOR: log: add free_logformat_node() helper function
    - BUG/MINOR: log: fix potential lf->name memory leak
    - BUG/MINOR: ist: allocate nul byte on istdup
    - BUG/MINOR: stats: drop srv refcount on early release
    - BUG/MAJOR: promex: fix crash on deleted server
    - BUG/MAJOR: server: fix stream crash due to deleted server
    - BUG/MEDIUM: mux-quic: do not crash on qcs_destroy for connection error
    - MINOR: cli: Remove useless loop on commands to find unescaped semi-colon
    - BUG/MEDIUM: cli: Warn if pipelined commands are delimited by a \n
    - BUG/MAJOR: cli: Restore non-interactive mode behavior with pipelined commands
    - BUG/MINOR: quic: fix output of show quic
    - MINOR: ssl: Call callback function after loading SSL CRL data
    - BUG/MINOR: ist: only store NUL byte on succeeded alloc

16 months agoBUG/MINOR: ist: only store NUL byte on succeeded alloc
Willy Tarreau [Fri, 23 Feb 2024 18:51:54 +0000 (19:51 +0100)] 
BUG/MINOR: ist: only store NUL byte on succeeded alloc

The trailing NUL added at the end of istdup() by recent commit de0216758
("BUG/MINOR: ist: allocate nul byte on istdup") was placed outside of
the pointer validity test, rightfully showing null deref warnings. This
fix should be backported along with the fix above, to the same versions.