]> git.ipfire.org Git - thirdparty/haproxy.git/log
thirdparty/haproxy.git
3 years agoBUG/MEDIUM: httpclient: Fix loop consuming HTX blocks from the response channel
Christopher Faulet [Fri, 29 Apr 2022 11:44:46 +0000 (13:44 +0200)] 
BUG/MEDIUM: httpclient: Fix loop consuming HTX blocks from the response channel

When the HTTP client consumes the response, it loops on the HTX message to
copy blocks content and it removes blocks by calling htx_remove_blk(). But
this function removes a block and returns the next one in the HTX
message. The result must be used instead of using htx_get_next(). It is
especially important because the block used in htx_get_next() loop was
removed. It only works because the message is not defragmented during the
loop.

In addition, the loop on the response was simplified to iter on blocks
instead of positions.

This patch must be backported to 2.5.

3 years agoBUG/MEDIUM: conn-stream: Don't erase endpoint flags on reset
Christopher Faulet [Thu, 28 Apr 2022 16:25:24 +0000 (18:25 +0200)] 
BUG/MEDIUM: conn-stream: Don't erase endpoint flags on reset

Only CS_EP_ERROR flag is now removed from the endpoint when a reset is
performed. When a new the endpoint is allocated, flags are preserved. It is
the caller responsibility to remove other flags, depending on its need.

Concretly, during a connection retry or a L7 retry, we must preserve
flags. In tcpcheck and the CLI, we reset flags.

This patch is 2.6-specific. No backport needed.

3 years agoBUG/MINOR: httpclient/ssl: use the correct verify constant
William Lallemand [Thu, 28 Apr 2022 17:35:21 +0000 (19:35 +0200)] 
BUG/MINOR: httpclient/ssl: use the correct verify constant

The SSL_SERVER_VERIFY_* constants were incorrectly set on the httpclient
server verify. The right constants are SSL_SOCK_VERIFY_* .

This could cause issues when using "httpclient-ssl-verify" or when the
SSL certificates can't be loaded.

No backport needed

3 years agoMINOR: quic: Drop 0-RTT packets if not allowed
Frédéric Lécaille [Wed, 27 Apr 2022 13:37:28 +0000 (15:37 +0200)] 
MINOR: quic: Drop 0-RTT packets if not allowed

Drop the 0-RTT packets for a listener without early data configuration enabled.

3 years agoCLEANUP: quic: Rely on the packet length set by qc_lstnr_pkt_rcv()
Frédéric Lécaille [Wed, 27 Apr 2022 13:09:53 +0000 (15:09 +0200)] 
CLEANUP: quic: Rely on the packet length set by qc_lstnr_pkt_rcv()

This function is used to parse the QUIC packets carried by a UDP datagram.
When a correct packet could be found, the ->len RX packet structure value
is set to the packet length value. On the contrary, it is set to the remaining
number of bytes in the UDP datagram if no correct QUIC packet could be found.
So, there is no need to make this function return a status value. It allows
the caller to parse any QUIC packet carried by a UDP datagram without this.

3 years agoBUG/MINOR: quic: Missing Initial packet length check
Frédéric Lécaille [Wed, 27 Apr 2022 09:42:08 +0000 (11:42 +0200)] 
BUG/MINOR: quic: Missing Initial packet length check

Any client Initial packet carried in a datagram smaller than QUIC_INITIAL_PACKET_MINLEN(200)
bytes must be discarded. This does not mean we must discard the entire datagram.
So we must at least try to parse the packet length before dropping the packet
and return its length from qc_lstnr_pkt_rcv().

3 years agoBUG/MEDIUM: quic: Possible crash on STREAM frame loss
Frédéric Lécaille [Wed, 27 Apr 2022 05:17:56 +0000 (07:17 +0200)] 
BUG/MEDIUM: quic: Possible crash on STREAM frame loss

A crash is possible under such circumtances:
    - The congestion window is drastically reduced to its miniaml value
    when a quic listener is experiencing extreme packet loss ;
    - we enqueue several STREAM frames to be resent and some of them could not be
    transmitted ;
    - some of the still in flight are acknowledged and trigger the
    stream memory releasing ;
    - when we come back to send the remaing STREAM frames, haproxy
    crashes when it tries to build them.

To fix this issue, we mark the STREAM frame as lost when detected as lost.
Then a lookup if performed for the stream the STREAM frames are attached
to before building them. They are released if the stream is no more available
or the data range of the frame is consumed.

3 years agoMINOR: quic: Wake up the mux to probe with new data
Frédéric Lécaille [Tue, 26 Apr 2022 11:54:28 +0000 (13:54 +0200)] 
MINOR: quic: Wake up the mux to probe with new data

When we have to probe the peer, we must first try to send new data. This is done
here waking up the mux after having set the number of maximum number of datagrams
to send to QUIC_MAX_NB_PTO_DGRAMS (2). Of course, this is only the case if the
mux was subscribed to SEND events.

3 years agoBUG/MINOR: quic: Traces fix about remaining frames upon packet build failure
Frédéric Lécaille [Mon, 25 Apr 2022 15:48:40 +0000 (17:48 +0200)] 
BUG/MINOR: quic: Traces fix about remaining frames upon packet build failure

3 years agoBUG/MINOR: quic: Avoid sending useless PADDING frame
Frédéric Lécaille [Mon, 25 Apr 2022 15:17:07 +0000 (17:17 +0200)] 
BUG/MINOR: quic: Avoid sending useless PADDING frame

This may happen in rare cases with extreme packet loss (30% for both TX and RX)
which leads the congestion window to decrease down to its minimal value (two
datagrams). Under such circumtances, no ack-eliciting frame can be added to
a packet by qc_build_frms(). In this case we must cancel the packet building
process if there is no ACK or probe (PING frame) to send.

3 years agoBUG/MINOR: quic: Wrong returned status by qc_build_frms()
Frédéric Lécaille [Mon, 25 Apr 2022 13:42:56 +0000 (15:42 +0200)] 
BUG/MINOR: quic: Wrong returned status by qc_build_frms()

This function must return a successful status as soon as it could be build
a frame to be embedded by a packet. This behavior was broken by the last
modifications. This was due to a dangerous "ret = 1" statement inside
a loop. This statement must be reach only if we go out of a switch/case
after a "break" statement.
Add comments to mention this information.

3 years agoMINOR: quic: Do not send ACK frames when probing
Frédéric Lécaille [Mon, 25 Apr 2022 08:38:27 +0000 (10:38 +0200)] 
MINOR: quic: Do not send ACK frames when probing

When we are probing, we do not receive packets, furthermore all ACK frames have
already been sent. This is useless to send ACK when probing the peer. This
modification does not reset the flag which marks the connection as requiring an
ACK frame to be sent. If this is the case, this will be taken into an account
by after the probing process.

3 years agoMEDIUM: quic: Enable the new datagram probing process
Frédéric Lécaille [Mon, 25 Apr 2022 08:33:12 +0000 (10:33 +0200)] 
MEDIUM: quic: Enable the new datagram probing process

Make the two I/O handlers quic_conn_io_cb() and quic_conn_app_io_cb() call
qc_dgrams_retransmit() after probing retransmissions need was detected by
the timer task (qc_process_timer()).
We must modify qc_prep_pkts() to support QUIC_TLS_ENC_LEVEL_NONE as <next_tel>
parameter when called from qc_dgrams_retransmit().

3 years agoMEDIUM: quic: Mark copies of acknowledged frames as acknowledged
Frédéric Lécaille [Mon, 25 Apr 2022 08:28:49 +0000 (10:28 +0200)] 
MEDIUM: quic: Mark copies of acknowledged frames as acknowledged

We call qc_release_frm() to do so from this function everywhere a frame
is released.

3 years agoMINOR: quic: Mark packets as probing with old data
Frédéric Lécaille [Mon, 25 Apr 2022 08:24:12 +0000 (10:24 +0200)] 
MINOR: quic: Mark packets as probing with old data

When probing retranmissions with old data are needed for the connection we
mark the packets as probing with old data to track them when acknowledged:
we do not resend frames with old data when lost.

3 years agoMINOR: quic: old data distinction for qc_send_app_pkt()
Frédéric Lécaille [Mon, 25 Apr 2022 08:17:00 +0000 (10:17 +0200)] 
MINOR: quic: old data distinction for qc_send_app_pkt()

Modify qc_send_app_pkt() to distinguish the case where it sends new data
against the case where it sends old data during probing retransmissions.
We add <old_data> boolean parameter to this function to do so. The mux
never directly send old data when probing retransmissions are needed by
the connection.

3 years agoMEDIUM: quic: qc_requeue_nacked_pkt_tx_frms() rework
Frédéric Lécaille [Mon, 25 Apr 2022 07:40:19 +0000 (09:40 +0200)] 
MEDIUM: quic: qc_requeue_nacked_pkt_tx_frms() rework

This function is used to requeue the TX frames from TX packets which have
been detected as lost. The modifications consist in avoiding resending frames from
duplicated frames used to probe the peer. This is useless. Only the original
frames loss must be taken into an account because detected as lost before
the retransmitted frames. If these latter are also detected as lost, other
duplicated frames would have been retransmitted before their loss detection.

3 years agoMEDIUM: quic: Retransmission functions rework
Frédéric Lécaille [Mon, 25 Apr 2022 07:25:56 +0000 (09:25 +0200)] 
MEDIUM: quic: Retransmission functions rework

qc_prep_fast_retrans() and qc_prep_hdshk_fast_retrans() are modified to
take two list of frames as parameters. Two lists are needed for
qc_prep_hdshk_fast_retrans() to build datagrams with two packets during
handshake. qc_prep_fast_retrans() needs two lists of frames to be used
to send two datagrams with one list by datagram.

3 years agoMEDIUM: quic: New functions for probing rework
Frédéric Lécaille [Mon, 25 Apr 2022 06:58:04 +0000 (08:58 +0200)] 
MEDIUM: quic: New functions for probing rework

We want to be able to resend frames from list of frames during handshakes to
resend datagrams with the same frames as during the first transmissions.
This leads to decrease drasctically the chances of frame fragmentation due to
variable lengths of the packet fields. Furthermore the frames were not duplicated
when retransmitted from a packet to another one. This must be the case only during
packet loss dectection.

qc_dup_pkt_frms() is there to duplicate the frames from an input list to an output
list. A distinction is made between STREAM frames and the other ones because we
can rely on the "acknowledged offset" the aim of which is to track the number
of bytes which were acknowledged from TX STREAM frames.

qc_release_frm() in addition to release the frame passed as parameter, also mark
the duplicate STREAM frames as acknowledeged.

qc_send_hdshk_pkts() is the qc_send_app_pkts() counterpart to send datagrams from
at most two list of frames to be able to coalesced packets from two different
packet number spaces

qc_dgrams_retransmit() is there to probe the peer with datagrams depending on the
need of the packet number spaces which must be flag with QUIC_FL_PKTNS_PROBE_NEEDED
by the PTO timer task (qc_process_timer()).

3 years agoMINOR: quic: process_timer() rework
Frédéric Lécaille [Thu, 21 Apr 2022 16:26:22 +0000 (18:26 +0200)] 
MINOR: quic: process_timer() rework

Add QUIC_FL_CONN_RETRANS_NEEDED connection flag definition to mark a quic_conn
struct as needing a retranmission.
Add QUIC_FL_PKTNS_PROBE_NEEDED to mark a packet number space as needing a
datagram probing.
Set these flags from process_timer() to trigger datagram probings.
Do not initiate anymore datagrams probing from any quic encryption level.
This will be done from the I/O handlers (quic_conn_io_cb() during handshakes and
quic_conn_app_io_cb() after handshakes).

3 years agoMINOR: quic: Add traces about TX frame memory releasing
Frédéric Lécaille [Thu, 21 Apr 2022 16:10:41 +0000 (18:10 +0200)] 
MINOR: quic: Add traces about TX frame memory releasing

Add such traces in qc_treat_acked_tx_frm(). This should be helpful to track memory
leak issues for TX frames.

3 years agoMINOR: quic: Do not retransmit frames from coalesced packets
Frédéric Lécaille [Thu, 21 Apr 2022 15:58:46 +0000 (17:58 +0200)] 
MINOR: quic: Do not retransmit frames from coalesced packets

Add QUIC_FL_TX_PACKET_COALESCED flag to mark a TX packet as coalesced with others
to build a datagram.
Ensure we do not directly retransmit frames from such coalesced packets. They must
be retransmitted from their packet number spaces to avoid duplications.

3 years agoMINOR: quic: Prepare quic_frame struct duplication
Frédéric Lécaille [Thu, 21 Apr 2022 15:32:10 +0000 (17:32 +0200)] 
MINOR: quic: Prepare quic_frame struct duplication

We want to track the frames which have been duplicated during retransmissions so
that to avoid uselessly retransmitting frames which would already have been
acknowledged. ->origin new member is there to store the frame from which a copy
was done, ->reflist is a list to store the frames which are copies.
Also ensure all the frames are zeroed and that their ->reflist list member is
initialized.
Add QUIC_FL_TX_FRAME_ACKED flag definition to mark a TX frame as acknowledged.

3 years agoMINOR: quic: Improve qc_prep_pkts() flexibility
Frédéric Lécaille [Mon, 11 Apr 2022 13:39:34 +0000 (15:39 +0200)] 
MINOR: quic: Improve qc_prep_pkts() flexibility

We want to be able to chosse the list of frames we want to prepare in packets
to be send. This is to modify the retransmission process (to come).

3 years agoMINOR: quic: decode as much STREAM as possible
Amaury Denoyelle [Wed, 27 Apr 2022 14:53:16 +0000 (16:53 +0200)] 
MINOR: quic: decode as much STREAM as possible

Add a loop in the bidi STREAM function. This will call repeatdly
qcc_decode_qcs() and dequeue buffered frames.

This is useful when reception of more data is interrupted because the
MUX buffer was full. qcc_decode_qcs() has probably free some space so it
is useful to immediatly retry reception of buffered frames of the qcs
tree.

This may fix occurences of stalled Rx transfers with large payload.
Note however that there is still room for improvment. The conn-stream
layer is not able at this moment to retrigger demuxing. This is because
the mux io-handler does not treat Rx : this may continue to cause
stalled tranfers.

3 years agoMINOR: h3: support DATA demux if buffer full
Amaury Denoyelle [Wed, 27 Apr 2022 13:37:20 +0000 (15:37 +0200)] 
MINOR: h3: support DATA demux if buffer full

Previously, h3 layer was not able to demux a DATA frame if not fully
received in the Rx buffer. This causes evident limitation and prevents
to be able to demux a frame bigger than the buffer.

Improve h3_data_to_htx() to support partial frame demuxing. The demux
state is preserved in the h3s new fields : this is useful to keep the
current type and length of the demuxed frame.

3 years agoMINOR: h3: implement h3 stream context
Amaury Denoyelle [Wed, 27 Apr 2022 16:04:01 +0000 (18:04 +0200)] 
MINOR: h3: implement h3 stream context

Define a new structure h3s used to provide context for a H3 stream. This
structure is allocated and stored in the qcs thanks to previous commit
which provides app-layer context storage.

For now, h3s is empty. It will soon be completed to be able to support
stateful demux : this is required to be able to demux an incomplete
frame if the rx buffer is full.

3 years agoMINOR: mux-quic: add a app-layer context in qcs
Amaury Denoyelle [Wed, 27 Apr 2022 13:17:11 +0000 (15:17 +0200)] 
MINOR: mux-quic: add a app-layer context in qcs

Define 2 new callback for qcc_app_ops : attach and detach. They are
called when a qcs instance is respectively allocated and freed. If
implemented, they can allocate a custom context stored in the new
abstract field ctx of qcs.

For now, h3 and hq-interop does not use these new callbacks. They will
be soon implemented by the h3 layer to allocate a context used for
stateful demuxing.

This change is required to support the demuxing of H3 frames bigger than
a buffer.

3 years agoMINOR: h3: change frame demuxing API
Amaury Denoyelle [Wed, 27 Apr 2022 12:52:52 +0000 (14:52 +0200)] 
MINOR: h3: change frame demuxing API

Edit the functions used for HEADERS and DATA parsing. They now return
the number of bytes handled.

This change will help to demux H3 frames bigger than the buffer.

3 years agoMINOR: mux-quic: partially copy Rx frame if almost full buf
Amaury Denoyelle [Tue, 26 Apr 2022 09:36:40 +0000 (11:36 +0200)] 
MINOR: mux-quic: partially copy Rx frame if almost full buf

Improve the reception for STREAM frames. In qcc_recv(), if the frame is
bigger than the remaining space in rx buffer, do not reject it wholly.
Instead, copy as much data as possible. The rest of the data is
buffered.

This is necessary to handle H3 frames bigger than a buffer. The H3 code
does not demux until the frame is complete or the buffer is full.
Without this, the transfer on payload larger than the Rx buffer can
rapidly freeze.

3 years agoBUG/MEDIUM: h3: fix use-after-free on mux Rx buffer wrapping
Amaury Denoyelle [Wed, 27 Apr 2022 12:41:53 +0000 (14:41 +0200)] 
BUG/MEDIUM: h3: fix use-after-free on mux Rx buffer wrapping

Handle wrapping buffer in h3_data_to_htx(). If data is wrapping, first
copy the contiguous data, then copy the data in front of the buffer.

Note that h3_headers_to_htx() is not able to handle wrapping data. For
the moment, a BUG_ON was added as a reminder. This cas never happened,
most probably because HEADERS is the first frame of the stream.

3 years agoBUG/MINOR: h3: fix incomplete POST requests
Amaury Denoyelle [Tue, 26 Apr 2022 14:24:39 +0000 (16:24 +0200)] 
BUG/MINOR: h3: fix incomplete POST requests

Always set HTX flag HTX_SL_F_XFER_LEN for http/3. This is correct
becuase the size of H3 requests is always known thanks to the protocol
framing.

This may fix occurences of incomplete POST requests when the client side
of the connection has been closed before.

3 years agoMINOR: mux-quic: count local flow-control stream limit on reception
Amaury Denoyelle [Tue, 26 Apr 2022 09:21:10 +0000 (11:21 +0200)] 
MINOR: mux-quic: count local flow-control stream limit on reception

Add new qcs fields to count the sum of bytes received for each stream.
This is necessary to enforce flow-control for reception on the peer.

For the moment, the implementation is partial. No MAX_STREAM_DATA or
FLOW_CONTROL_ERROR are emitted. BUG_ON statements are here as a
remainder.

This means that for the moment we do not support POST payloads greater
that the initial max-stream-data announced (256k currently).

At least, we now ensure that we never buffer a frame which overflows the
flow-control limit : this ensures that the memory consumption per stream
should stay under control.

3 years agoBUG/MINOR: mux-quic: fix leak if cs alloc failure
Amaury Denoyelle [Wed, 27 Apr 2022 13:09:27 +0000 (15:09 +0200)] 
BUG/MINOR: mux-quic: fix leak if cs alloc failure

qcs and its field are not properly freed if the conn-stream allocation
fail in qcs_new(). Fix this by having a proper deinit code with a
dedicated label.

3 years agoMINOR: mux-quic: remove unused bogus qcc_get_stream()
Amaury Denoyelle [Tue, 26 Apr 2022 15:36:56 +0000 (17:36 +0200)] 
MINOR: mux-quic: remove unused bogus qcc_get_stream()

qcc_get_stream() was used when qcs and qc_stream_desc shared the same
node-tree. This is not the case anymore since
  e4301da5ed9e77844c653ea4caf233546febe591
  MINOR: quic-stream: use distinct tree nodes for quic stream and qcs

Now this function is broken as the qcc tree only contains qcs.
Thankfully it is unused so it can be removed without impact.

3 years agoMINOR: mux-quic: adjust comment on emission function
Amaury Denoyelle [Wed, 27 Apr 2022 14:44:49 +0000 (16:44 +0200)] 
MINOR: mux-quic: adjust comment on emission function

Comments were not properly edited since the splitting of functions for
stream emission. Also "payload" argument has been renamed to "in" as it
better reflects the function purpose.

3 years agoBUG/MINOR: mux-quic: fix build in release mode
Amaury Denoyelle [Thu, 28 Apr 2022 12:41:50 +0000 (14:41 +0200)] 
BUG/MINOR: mux-quic: fix build in release mode

Fix build when not using DEBUG_STRICT. 'ret' is reported as unused as it
is only tested in a BUG_ON statement.

3 years agoCLEANUP: connections/deinit: destroy the idle_conns tasks
Willy Tarreau [Wed, 27 Apr 2022 16:53:07 +0000 (18:53 +0200)] 
CLEANUP: connections/deinit: destroy the idle_conns tasks

This adds a deinit_idle_conns() function that's called on deinit to
release the per-thread idle connection management tasks. The global
task was already taken care of.

3 years agoCLEANUP: listeners/deinit: release accept queue tasklets on deinit
Willy Tarreau [Wed, 27 Apr 2022 16:42:47 +0000 (18:42 +0200)] 
CLEANUP: listeners/deinit: release accept queue tasklets on deinit

There was no function to release these ones, they were only created
so the patch adds an accept_queue_deinit() call.

3 years agoCLEANUP: deinit: release the config postparsers
Willy Tarreau [Wed, 27 Apr 2022 16:07:24 +0000 (18:07 +0200)] 
CLEANUP: deinit: release the config postparsers

These ones were not released either, it just requires to export the list
("postparsers") and it makes valgrind happy.

3 years agoCLEANUP: deinit: release the pre-check callbacks
Willy Tarreau [Wed, 27 Apr 2022 16:02:54 +0000 (18:02 +0200)] 
CLEANUP: deinit: release the pre-check callbacks

The freeing of pre-check callbacks was missing when this feature was
recently added with commit b53eb8790 ("MINOR: init: add the pre-check
callback"), let's do it to make valgrind happy.

3 years agoCLEANUP: chunks: release trash also in deinit
Willy Tarreau [Wed, 27 Apr 2022 15:55:41 +0000 (17:55 +0200)] 
CLEANUP: chunks: release trash also in deinit

Tim reported in issue #1676 that just like startup_logs, trash buffers
are not released on deinit since they're thread-local, but valgrind
notices it when quitting before creating threads like "-c -f ...". Let's
just subscribe the function to deinit in addition to threads' end.

The two "free(x);x=NULL;" in free_trash_buffers_per_thread() were
also simplified using ha_free().

3 years agoCLEANUP: errors: also call deinit_errors_buffers() on deinit()
Willy Tarreau [Wed, 27 Apr 2022 15:50:53 +0000 (17:50 +0200)] 
CLEANUP: errors: also call deinit_errors_buffers() on deinit()

Tim reported in issue #1676 that we don't release startup logs if we
warn during startup and quit before creating threads (e.g. -c -f ...).
Let's subscribe deinit_errors_buffers() to both thread's end and
deinit. That's OK since it uses both per-thread and global variables,
and is idempotent.

3 years agoMINOR: ssl: add a new global option "tune.ssl.hard-maxrecord"
Thomas Prückl [Wed, 27 Apr 2022 11:04:54 +0000 (13:04 +0200)] 
MINOR: ssl: add a new global option "tune.ssl.hard-maxrecord"

Low footprint client machines may not have enough memory to download a
complete 16KB TLS record at once. With the new option the maximum
record size can be defined on the server side.

Note: Before limiting the the record size on the server side, a client should
consider using the TLS Maximum Fragment Length Negotiation Extension defined
in RFC6066.

This patch fixes GitHub issue #1679.

3 years agoBUG/MINOR: pools: make sure to also destroy shared pools in pool_destroy_all()
Willy Tarreau [Wed, 27 Apr 2022 09:33:13 +0000 (11:33 +0200)] 
BUG/MINOR: pools: make sure to also destroy shared pools in pool_destroy_all()

In issue #1677, Tim reported that we don't correctly free some shared
pools on exit. What happens in fact is that pool_destroy() is meant to
be called once per pool *pointer*, as it decrements the use count for
each pass and only releases the pool when it reaches zero. But since
pool_destroy_all() iterates over the pools list, it visits each pool
only once and will not eliminate some of them, which thus remain in the
list.

In an ideal case, the function should loop over all pools for as long
as the list is not empty, but that's pointless as we know we're exiting,
so let's just set the users count to 1 before the call so that
pool_destroy() knows it can delete and release the entry.

This could be backported to all versions (memory.c in 2.0 and older) but
it's not a real problem in practice.

3 years agoBUILD: fd: disguise the fd_set_nonblock/cloexec result
Willy Tarreau [Wed, 27 Apr 2022 08:50:00 +0000 (10:50 +0200)] 
BUILD: fd: disguise the fd_set_nonblock/cloexec result

We thought that we could get rid of some DISGUISE() with commit a80e4a354
("MINOR: fd: add functions to set O_NONBLOCK and FD_CLOEXEC") thanks to
the calls being in a function but that was without counting on Coverity.
Let's put it directly in the function since most if not all callers don't
care about this result.

3 years agoMINOR: Call deinit_and_exit(0) for `haproxy -vv`
Tim Duesterhus [Tue, 26 Apr 2022 22:08:11 +0000 (00:08 +0200)] 
MINOR: Call deinit_and_exit(0) for `haproxy -vv`

It appears that it is safe to call perform a clean deinit at this point, so
let's do this to exercise the deinit paths some more.

Running `valgrind --leak-check=full --show-leak-kinds=all ./haproxy -vv` with
this change reports:

    ==261864== HEAP SUMMARY:
    ==261864==     in use at exit: 344 bytes in 11 blocks
    ==261864==   total heap usage: 1,178 allocs, 1,167 frees, 1,102,089 bytes allocated
    ==261864==
    ==261864== 24 bytes in 1 blocks are still reachable in loss record 1 of 2
    ==261864==    at 0x483DD99: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==261864==    by 0x324BA6: hap_register_pre_check (init.c:92)
    ==261864==    by 0x155824: main (haproxy.c:3024)
    ==261864==
    ==261864== 320 bytes in 10 blocks are still reachable in loss record 2 of 2
    ==261864==    at 0x483DD99: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==261864==    by 0x26E54E: cfg_register_postparser (cfgparse.c:4238)
    ==261864==    by 0x155824: main (haproxy.c:3024)
    ==261864==
    ==261864== LEAK SUMMARY:
    ==261864==    definitely lost: 0 bytes in 0 blocks
    ==261864==    indirectly lost: 0 bytes in 0 blocks
    ==261864==      possibly lost: 0 bytes in 0 blocks
    ==261864==    still reachable: 344 bytes in 11 blocks
    ==261864==         suppressed: 0 bytes in 0 blocks

which is looking pretty good.

3 years agoBUG/MINOR: resolvers: Fix memory leak in resolvers_deinit()
Tim Duesterhus [Tue, 26 Apr 2022 21:28:47 +0000 (23:28 +0200)] 
BUG/MINOR: resolvers: Fix memory leak in resolvers_deinit()

A config like the following:

    global
     stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners

    resolvers unbound
     nameserver unbound 127.0.0.1:53

will report the following leak when running a configuration check:

    ==241882== 6,991 (6,952 direct, 39 indirect) bytes in 1 blocks are definitely lost in loss record 8 of 13
    ==241882==    at 0x483DD99: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==241882==    by 0x25938D: cfg_parse_resolvers (resolvers.c:3193)
    ==241882==    by 0x26A1E8: readcfgfile (cfgparse.c:2171)
    ==241882==    by 0x156D72: init (haproxy.c:2016)
    ==241882==    by 0x156D72: main (haproxy.c:3037)

because the `.px` member of `struct resolvers` is not freed.

The offending allocation was introduced in
c943799c865c04281454a7a54fd6c45c2b4d7e09 which is a reorganization that
happened during development of 2.4.x. This fix can likely be backported without
issue to 2.4+ and is likely not needed for earlier versions as the leak happens
during deinit only.

3 years agoCLEANUP: Destroy `http_err_chunks` members during deinit
Tim Duesterhus [Tue, 26 Apr 2022 21:35:07 +0000 (23:35 +0200)] 
CLEANUP: Destroy `http_err_chunks` members during deinit

To make the deinit function a proper inverse of the init function we need to
free the `http_err_chunks`:

    ==252081== 311,296 bytes in 19 blocks are still reachable in loss record 50 of 50
    ==252081==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==252081==    by 0x2727EE: http_str_to_htx (http_htx.c:914)
    ==252081==    by 0x272E60: http_htx_init (http_htx.c:1059)
    ==252081==    by 0x26AC87: check_config_validity (cfgparse.c:4170)
    ==252081==    by 0x155DFE: init (haproxy.c:2120)
    ==252081==    by 0x155DFE: main (haproxy.c:3037)

3 years agoBUG/MEDIUM: http-ana: Fix memleak in redirect rules with ignore-empty option
Christopher Faulet [Tue, 26 Apr 2022 18:34:38 +0000 (20:34 +0200)] 
BUG/MEDIUM: http-ana: Fix memleak in redirect rules with ignore-empty option

A memory leak was introduced when ignore-empty option was added to redirect
rules. If there is no location, when this option is set, the redirection is
aborted and the processing continues. But when this happened, the trash buffer
allocated to format the redirect response was not released.

The bug was introduced by commit bc1223be7 ("MINOR: http-rules: add a new
"ignore-empty" option to redirects.").

This patch should fix the issue #1675. It must be backported to 2.5.

3 years agoMINOR: connection: Add way to disable active connection closing during soft-stop
Remi Tricot-Le Breton [Tue, 26 Apr 2022 13:17:18 +0000 (15:17 +0200)] 
MINOR: connection: Add way to disable active connection closing during soft-stop

If the "close-spread-time" option is set to "infinite", active
connection closing during a soft-stop can be disabled. The 'connection:
close' header or the GOAWAY frame will not be added anymore to the
server's response and active connections will only be closed once the
clients disconnect. Idle connections will not be closed all at once when
the soft-stop starts anymore, and each idle connection will follow its
own timeout based on the multiple timeouts set in the configuration (as
is the case during regular execution).

This feature request was described in GitHub issue #1614.
This patch should be backported to 2.5. It depends on 'MEDIUM: global:
Add a "close-spread-time" option to spread soft-stop on time window'.

3 years agoBUILD: compiler: properly distinguish weak and global symbols
Willy Tarreau [Tue, 26 Apr 2022 17:35:38 +0000 (19:35 +0200)] 
BUILD: compiler: properly distinguish weak and global symbols

While weak symbols were finally fixed with commit fb1b6f5bc ("BUILD:
compiler: use a more portable set of asm(".weak") statements"), it
was an error to think that initcall symbols were also weak. They must
not be and they're only global. The reason is that any externally
linked code loaded as a .so would drop its weak symbols when being
loaded, hence its initcalls that may contain various function
registration calls.

The ambiguity came from the fact that we initially reused the initcall's
HA_GLOBL macro for OSX then generalized it, then turned it to a choice
between .globl and .weak based on the OS, while in fact we needed a
macro to define weak symbols.

Let's rename the macro to HA_WEAK() to make it clear it's only for weak
symbols, and redefine HA_GLOBL() that initcall needs.

This will need to be backported wherever the commit above is backported
(at least 2.5 for now).

3 years agoBUG/MEDIUM: ssl/cli: fix yielding in show_cafile_detail
William Lallemand [Tue, 26 Apr 2022 16:17:15 +0000 (18:17 +0200)] 
BUG/MEDIUM: ssl/cli: fix yielding in show_cafile_detail

HAProxy crashes when "show ssl ca-file" is being called on a ca-file
which contains a lot of certificates. (127 in our test with
/etc/ssl/certs/ca-certificates.crt).

The root cause is the fonction does not yield when there is no available
space when writing the details, and we could write a lot.

To fix the issue, we try to put the data with ci_putchk() after every
show_cert_detail() and we yield if the ci_putchk() fails.

This patch also cleans up a little bit the code:

- the end label is now a real end with a return 1;
- i0 is used instead of (long)p1
- the ID is stored upon yield

3 years agoMEDIUM: httpclient: re-enable the verify by default
William Lallemand [Tue, 26 Apr 2022 10:00:06 +0000 (12:00 +0200)] 
MEDIUM: httpclient: re-enable the verify by default

Since the httpclient verify now has a fallback which disable the SSL in
the httpclient without exiting haproxy at startup, we can safely
re-enable it by default.

It could still be disabled with "httpclient-ssl-verify none".

3 years agoBUG/MINOR: ssl: memory leak when trying to load a directory with ca-file
William Lallemand [Tue, 26 Apr 2022 13:57:33 +0000 (15:57 +0200)] 
BUG/MINOR: ssl: memory leak when trying to load a directory with ca-file

This patch fixes a memory leak of the ca structure when trying to load a
directory with the ca-file directive.

No backport needed.

3 years agoBUG/MINOR: ssl: free the cafile entries on deinit
William Lallemand [Tue, 26 Apr 2022 13:44:53 +0000 (15:44 +0200)] 
BUG/MINOR: ssl: free the cafile entries on deinit

The cafile_tree was never free upon deinit, making valgrind and ASAN
complains when haproxy quits.

This could be backported as far as 2.2 but it requires the
ssl_store_delete_cafile_entry() helper from
5daff3c8abc658760a0d0c5fbbc633bfff1afe44.

3 years agoBUG/MINOR: httpclient/lua: error when the httpclient_start() fails
William Lallemand [Tue, 26 Apr 2022 09:46:13 +0000 (11:46 +0200)] 
BUG/MINOR: httpclient/lua: error when the httpclient_start() fails

Jump to an luaL_error() when the httpclient fails, it could be the
result of an allocation failure, or even a wrong URL.

Must be backported in 2.5.

3 years agoMEDIUM: httpclient: disable SSL when the ca-file couldn't be loaded
William Lallemand [Mon, 25 Apr 2022 16:23:35 +0000 (18:23 +0200)] 
MEDIUM: httpclient: disable SSL when the ca-file couldn't be loaded

Emit a warning when the ca-file couldn't be loaded for the httpclient,
and disable the SSL of the httpclient.

We must never be in a case where the verify is disabled without any
configuration, so better disable the SSL completely.

Move the check on the scheme above the initialization of the applet so
we could abort before initializing the appctx.

3 years agoREGTESTS: webstats: remove unused stats socket in /tmp
William Lallemand [Mon, 25 Apr 2022 16:16:34 +0000 (18:16 +0200)] 
REGTESTS: webstats: remove unused stats socket in /tmp

Remove a useless stats socket which was configured outside the reg-tests
directories.

3 years agoREGTESTS: fix the race conditions in be2dec.vtc ad field.vtc
Christopher Faulet [Tue, 26 Apr 2022 09:20:10 +0000 (11:20 +0200)] 
REGTESTS: fix the race conditions in be2dec.vtc ad field.vtc

A "Connection: close" header is added to all responses to avoid any
connection reuse. This should avoid any "HTTP header incomplete" errors.

3 years agoCLEANUP: tree-wide: remove 25 occurrences of unneeded fcntl.h
Willy Tarreau [Tue, 26 Apr 2022 08:30:35 +0000 (10:30 +0200)] 
CLEANUP: tree-wide: remove 25 occurrences of unneeded fcntl.h

There were plenty of leftovers from old code that were never removed
and that are not needed at all since these files do not use any
definition depending on fcntl.h, let's drop them.

3 years agoCLEANUP: tree-wide: use fd_set_nonblock() and fd_set_cloexec()
Willy Tarreau [Tue, 26 Apr 2022 08:24:14 +0000 (10:24 +0200)] 
CLEANUP: tree-wide: use fd_set_nonblock() and fd_set_cloexec()

This gets rid of most open-coded fcntl() calls, some of which were passed
through DISGUISE() to avoid a useless test. The FD_CLOEXEC was most often
set without preserving previous flags, which could become a problem once
new flags are created. Now this will not happen anymore.

3 years agoMINOR: fd: add functions to set O_NONBLOCK and FD_CLOEXEC
Willy Tarreau [Tue, 26 Apr 2022 08:18:07 +0000 (10:18 +0200)] 
MINOR: fd: add functions to set O_NONBLOCK and FD_CLOEXEC

Instead of seeing each location manipulate the fcntl() themselves and
often forget to check previous flags, let's centralize the functions to
do this. It also allows to drop fcntl.h from most call places and will
ease the adoption of different OS-specific mechanisms if needed. Note
that the fd_set_nonblock() function purposely doesn't check the previous
flags as it's meant to be used on new FDs only.

3 years agoBUG/MINOR: connection: "connection:close" header added despite 'close-spread-time'
Remi Tricot-Le Breton [Mon, 25 Apr 2022 15:50:48 +0000 (17:50 +0200)] 
BUG/MINOR: connection: "connection:close" header added despite 'close-spread-time'

Despite what the 'close-spread-time' option should do, the
'connection:close' header was always added to HTTP responses during
soft-stops even with a soft-stop window defined.
This patch adds the proper random based closing to HTTP connections
during a soft-stop (based on the time left in the soft close window).

It should be backported to 2.5 once 'MEDIUM: global: Add a
"close-spread-time" option to spread soft-stop on time window' is
backported as well.

3 years agoMINOR: tree-wide: always consider EWOULDBLOCK in addition to EAGAIN
Willy Tarreau [Mon, 25 Apr 2022 18:32:15 +0000 (20:32 +0200)] 
MINOR: tree-wide: always consider EWOULDBLOCK in addition to EAGAIN

Some older systems may routinely return EWOULDBLOCK for some syscalls
while we tend to check only for EAGAIN nowadays. Modern systems define
EWOULDBLOCK as EAGAIN so that solves it, but on a few older ones (AIX,
VMS etc) both are different, and for portability we'd need to test for
both or we never know if we risk to confuse some status codes with
plain errors.

There were few entries, the most annoying ones are the switch/case
because they require to only add the entry when it differs, but the
other ones are really trivial.

3 years agoCLEANUP: compression: move the default setting of maxzlibmem to defaults
Willy Tarreau [Mon, 25 Apr 2022 17:29:10 +0000 (19:29 +0200)] 
CLEANUP: compression: move the default setting of maxzlibmem to defaults

__comp_fetch_init() only presets the maxzlibmem, and only when both
USE_ZLIB and DEFAULT_MAXZLIBMEM are set. The intent is to preset a
default value to protect the system against excessive memory usage
when no setting is set by the user.

Nowadays the entry in the global struct is always there so there's no
point anymore in passing via a constructor to possibly set this value.
Let's go the cleaner way by always presetting DEFAULT_MAXZLIBMEM to 0
in defaults.h unless these conditions are met, and always assigning it
instead of pre-setting the entry to zero. This is more straightforward
and removes some ifdefs and the last constructor. In addition, now the
setting has a chance of being found.

3 years agoBUILD: http: remove the two unused constructors in rules and ana
Willy Tarreau [Mon, 25 Apr 2022 17:26:26 +0000 (19:26 +0200)] 
BUILD: http: remove the two unused constructors in rules and ana

__http_protocol_init() and __http_rules_init() were empty leftovers
from a previous more intense use of constructors. Let's just get rid
of them now.

3 years agoBUILD: thread: use initcall instead of a constructor
Willy Tarreau [Mon, 25 Apr 2022 17:23:17 +0000 (19:23 +0200)] 
BUILD: thread: use initcall instead of a constructor

The constructor present there could be replaced with an initcall.
This one is set at level STG_PREPARE because it also zeroes the
lock_stats, and it's a bit odd that it could possibly have been
scheduled to run after other constructors that might already
preset some of these locks by accident.

3 years agoBUILD: xprt: use an initcall to register the transport layers
Willy Tarreau [Mon, 25 Apr 2022 17:18:24 +0000 (19:18 +0200)] 
BUILD: xprt: use an initcall to register the transport layers

Transport layers (raw_sock, ssl_sock, xprt_handshake and xprt_quic)
were using 4 constructors and 2 destructors. The 4 constructors were
replaced with INITCALL and the destructors with REGISTER_POST_DEINIT()
so that we do not depend on this anymore.

3 years agoBUILD: pollers: use an initcall to register the pollers
Willy Tarreau [Mon, 25 Apr 2022 17:00:55 +0000 (19:00 +0200)] 
BUILD: pollers: use an initcall to register the pollers

Pollers are among the few remaining blocks still using constructors
to register themselves. That's not needed anymore since the initcalls
so better turn to initcalls.

3 years agoMINOR: init: add global setting "fd-hard-limit" to bound system limits
Willy Tarreau [Mon, 25 Apr 2022 16:02:03 +0000 (18:02 +0200)] 
MINOR: init: add global setting "fd-hard-limit" to bound system limits

On some systems, the hard limit for ulimit -n may be huge, in the order
of 1 billion, and using this to automatically compute maxconn doesn't
work as it requires way too much memory. Users tend to hard-code maxconn
but that's not convenient to manage deployments on heterogenous systems,
nor when porting configs to developers' machines. The ulimit-n parameter
doesn't work either because it forces the limit. What most users seem to
want (and it makes sense) is to respect the system imposed limits up to
a certain value and cap this value. This is exactly what fd-hard-limit
does.

This addresses github issue #1622.

3 years agoMEDIUM: backend: add new "balance hash <expr>" algorithm
Willy Tarreau [Mon, 25 Apr 2022 08:25:34 +0000 (10:25 +0200)] 
MEDIUM: backend: add new "balance hash <expr>" algorithm

Almost all of our hash-based LB algorithms are implemented as special
cases of something that can now be achieved using sample expressions,
and some of them have adopted some options to adapt their behavior in
ways that could also be achieved using converters.

There are users who want to hash other parameters that are combined
into variables, and who set headers from these values and use
"balance hdr(name)" for this.

Instead of constantly implementing specific options and having users
hack around when they want a real hash, let's implement a native hash
mode that applies to a standard sample expression. This way, any
fetchable element (including variables) may be used to construct the
hash, even modified by any converter if desired.

3 years agoMINOR: sample: make the bool type cast to bin
Willy Tarreau [Mon, 25 Apr 2022 08:46:16 +0000 (10:46 +0200)] 
MINOR: sample: make the bool type cast to bin

Any type except bool could cast to bin, while it can cast to string.
That's a bit inconsistent, and prevents a boolean from being used as
the entry of a hash function while any other type can. This is a
problem when passing via variable where someone could use:

    ... set-var(txn.bar) always_false

to temporarily disable something, but this would result in an empty
hash output when later doing:

    ... var(txn.bar),sdbm

Instead of using c_int2bin() as is done for the string output, better
enfore an set of inputs or exactly 0 or 1 so that a poorly written sample
fetch function does not result in a difficult to debug hash output.

3 years agoMINOR: sample: don't needlessly call c_none() in sample_fetch_as_type()
Willy Tarreau [Mon, 25 Apr 2022 08:02:11 +0000 (10:02 +0200)] 
MINOR: sample: don't needlessly call c_none() in sample_fetch_as_type()

Surprisingly, while about all calls to a sample cast function carefully
avoid calling c_none(), sample_fetch_as_type() makes no effort regarding
this, while by nature, the function is most often called with an expected
output type similar to the one of the expresison. Let's add it to shorten
the most common call path.

3 years agoBUG/MINOR: sample: add missing use_backend/use-server contexts in smp_resolve_args
Willy Tarreau [Mon, 25 Apr 2022 06:15:46 +0000 (08:15 +0200)] 
BUG/MINOR: sample: add missing use_backend/use-server contexts in smp_resolve_args

The use_backend and use-server contexts were not enumerated in
smp_resolve_args, and while use-server doesn't currently take an
expression, at least use_backend supports that, and both entries ought
to be listed for completeness. Now an error in a use_backend rule
becomes more precise, from:

  [ALERT]    (12373) : config : parsing [use-srv.cfg:33]: unable to find
                       backend 'foo' referenced in arg 1 of sample fetch
                       keyword 'nbsrv' in proxy 'echo'.
to:

  [ALERT]    (12307) : config : parsing [use-srv.cfg:33]: unable to find
                       backend 'foo' referenced in arg 1 of sample fetch
                       keyword 'nbsrv' in use_backend expression in proxy
                       'echo'.

This may be backported though this is totally harmless.

3 years agoBUG/MINOR: http-act: make release_http_redir() more robust
Willy Tarreau [Mon, 25 Apr 2022 08:25:15 +0000 (10:25 +0200)] 
BUG/MINOR: http-act: make release_http_redir() more robust

Since commit dd7e6c6dc ("BUG/MINOR: http-rules: completely free incorrect
TCP rules on error") free_act_rule() is called on some error paths, and one
of them involves incomplete redirect rules that may cause a crash if the
rule wasn't yet initialized, as shown in this config snippet:

   frontend ft
      mode http
      bind *:8001
      http-request redirect location /%[always_false,sdbm]

Let's simply make release_http_redir() more robust against null redirect
rules.

No backport needed since it seems that the only way to trigger this was
the extra check above that was merged during 2.6-dev.

3 years agoBUG/MINOR: rules: Fix check_capture() function to use the right rule arguments
Christopher Faulet [Mon, 25 Apr 2022 12:57:58 +0000 (14:57 +0200)] 
BUG/MINOR: rules: Fix check_capture() function to use the right rule arguments

The function checking captures defined in tcp-request content ruleset didn't
use the right rule arguments. "arg.trk_ctr" was used instead of "arg.cap".

This patch must be backported as far as 2.2.

3 years agoBUG/MEDIUM: rules: Be able to use captures defined in defaults section
Christopher Faulet [Mon, 25 Apr 2022 12:30:58 +0000 (14:30 +0200)] 
BUG/MEDIUM: rules: Be able to use captures defined in defaults section

Since the 2.5, it is possible to define TCP/HTTP ruleset in defaults
sections. However, rules defining a capture in defaults sections was not
properly handled because they was not shared with the proxies inheriting
from the defaults section. This led to crash when haproxy tried to store a
new capture.

So now, to fix the issue, when a new proxy is created, the list of captures
points to the list of its defaults section. It may be NULL or not. All new
caputres are prepended to this list. It is not a problem to share the same
defaults section between several proxies, because it is not altered and we
take care to not release it when corresponding proxies are freed but only
when defaults proxies are freed. To do so, defaults proxies are now
unreferenced at the end of free_proxy() function instead of the beginning.

This patch should fix the issue #1674. It must be backported to 2.5.

3 years agoBUG/MINOR: rules: Forbid captures in defaults section if used by a backend
Christopher Faulet [Mon, 25 Apr 2022 12:24:56 +0000 (14:24 +0200)] 
BUG/MINOR: rules: Forbid captures in defaults section if used by a backend

Captures must only be defined in proxies with the frontend capabilities or
in defaults sections used by proxies with the frontend capabilities. Thus,
an extra check is added to be sure a defaults section defining a capture
will never be references by a backend.

Note that in this case, only named captures in "tcp-request content" or
"http-request" rules are possible. It is not possible in a defaults section
to decalre a capture slot. Not yet at least.

This patch must be backported to 2.5. It is releated to issue #1674.

3 years agoBUG/MINOR: quic: fix use-after-free with trace on ACK consume
Amaury Denoyelle [Mon, 25 Apr 2022 12:26:54 +0000 (14:26 +0200)] 
BUG/MINOR: quic: fix use-after-free with trace on ACK consume

When using qc_stream_desc_ack(), the stream instance may be freed if
there is no more data in its buffers. This also means that all frames
still stored waiting for ACK for this stream are freed via
qc_stream_desc_free().

This is particularly important in quic_stream_try_to_consume() where we
loop over the frames tree of the stream. A use-after-free is present in
cas the stream has been freed in the trace "stream consumed" which
dereference the frame. Fix this by first checking if the stream has been
freed or not.

This bug was detected by using ASAN + quic traces enabled.

3 years ago[RELEASE] Released version 2.6-dev7 v2.6-dev7
Willy Tarreau [Sat, 23 Apr 2022 02:38:36 +0000 (04:38 +0200)] 
[RELEASE] Released version 2.6-dev7

Released version 2.6-dev7 with the following main changes :
    - BUILD: calltrace: fix wrong include when building with TRACE=1
    - MINOR: ssl: Use DH parameters defined in RFC7919 instead of hard coded ones
    - MEDIUM: ssl: Disable DHE ciphers by default
    - BUILD: ssl: Fix compilation with OpenSSL 1.0.2
    - MINOR: mux-quic: split xfer and STREAM frames build
    - REORG: quic: use a dedicated module for qc_stream_desc
    - MINOR: quic-stream: use distinct tree nodes for quic stream and qcs
    - MINOR: quic-stream: add qc field
    - MEDIUM: quic: implement multi-buffered Tx streams
    - MINOR: quic-stream: refactor ack management
    - MINOR: quic: limit total stream buffers per connection
    - MINOR: mux-quic: implement immediate send retry
    - MINOR: cfg-quic: define tune.quic.conn-buf-limit
    - MINOR: ssl: Add 'show ssl providers' cli command and providers list in -vv option
    - REGTESTS: ssl: Update error messages that changed with OpenSSLv3.1.0-dev
    - BUG/MEDIUM: quic: Possible crash with released mux
    - BUG/MINOR: mux-quic: unsubscribe on release
    - BUG/MINOR: mux-quic: handle null timeout
    - BUG/MEDIUM: logs: fix http-client's log srv initialization
    - BUG/MINOR: mux-quic: remove dead code in qcs_xfer_data()
    - DEV: stream: Fix conn-streams dump in full stream message
    - CLEANUP: conn-stream: Rename cs_conn_close() and cs_conn_drain_and_close()
    - CLEANUP: conn-stream: Rename cs_applet_release()
    - MINOR: conn-stream: Rely on endpoint shutdown flags to shutdown an applet
    - BUG/MINOR: cache: Disable cache if applet creation fails
    - BUG/MINOR: backend: Don't allow to change backend applet
    - BUG/MEDIUM: conn-stream: Set back CS to RDY state when the appctx is created
    - MINOR: stream: Don't needlessly detach server endpoint on early client abort
    - MINOR: conn-stream: Make cs_detach_* private and use cs_destroy() from outside
    - MINOR: init: add the pre-check callback
    - MEDIUM: httpclient: change the init sequence
    - MEDIUM: httpclient/ssl: verify required
    - MINOR: httpclient/mworker: disable in the master process
    - MEDIUM: httpclient/ssl: verify is configurable and disabled by default
    - BUG/MAJOR: connection: Never remove connection from idle lists outside the lock
    - BUG/MEDIUM: mux-quic: fix stalled POST requets
    - BUG/MINOR: mux-quic: fix POST with abortonclose
    - MINOR: task: add a new task_instant_wakeup() function
    - MEDIUM: queue: use tasklet_instant_wakeup() to wake tasks
    - DOC: remove my name from the config doc

3 years agoDOC: remove my name from the config doc
Willy Tarreau [Sat, 23 Apr 2022 02:32:43 +0000 (04:32 +0200)] 
DOC: remove my name from the config doc

I was surprised to notice that my name was still present as the author
at the top of the config manual. It turns out that this line and a few
other ones in this file remained unchanged since commit 6a06a40501 that
added this doc 15 years ago! It's long been time to get rid of this!

3 years agoMEDIUM: queue: use tasklet_instant_wakeup() to wake tasks
Willy Tarreau [Fri, 22 Apr 2022 16:37:56 +0000 (18:37 +0200)] 
MEDIUM: queue: use tasklet_instant_wakeup() to wake tasks

It's long been known that queues didn't scale with threads for various
reasons ranging from the cost of the queue lock to the cost of the
massive amount of inter-thread wakeups.

But some recent reports showing deplorable perfs with threads used at
100% CPU helped us notice that the two elements above add on top of
each other:
  - with plenty of inter-thread wakeups, the scheduler takes a lot of
    time to dequeue pending tasks from the shared queue ;
  - the lock held by the scheduler to do this slows down subsequent
    task_wakeup() calls from the the queue that are made under the
    queue's lock
  - the queue's lock slows down addition of new requests to the queue
    and adds up to the number of needed queue entries for a steady
    traffic.

But the cost of the share queue has no reason for being paid because
it had already been paid when process_stream() added the request to
the queue. As such an instant wakeup is perfectly fit for this.

This is exactly what this patch does, it uses tasklet_instant_wakeup()
to dequeue pending requests, which has the effect of not bloating the
shared queue, hence not requiring the global queue lock, which in turn
results in the wakeup to be much faster, and the queue lock to be much
shorter. In the end, a test with 4k concurrent connections that was
being limited to 40-80k requests/s before with 16 threads, some of
which were stuck at 100% CPU now reaches 570k req/s with 4% idle.

Given that it's been found that it was possible to trigger the watchdog
on the queue lock under extreme conditions, and that such conditions
could happen when users want to protect their servers during a DoS, it
would definitely make sense to backport it to the most recent releases
(2.5 and 2.4 seem like good candidates especially because their scheduler
is modern enough to receive the change above). If a backport is performed,
the following patch is needed:

    MINOR: task: add a new task_instant_wakeup() function

3 years agoMINOR: task: add a new task_instant_wakeup() function
Willy Tarreau [Fri, 22 Apr 2022 16:22:03 +0000 (18:22 +0200)] 
MINOR: task: add a new task_instant_wakeup() function

This function's purpose is to wake up either a local or remote task,
bypassing the tree-based run queue. It is meant for fast wakeups that
are supposed to be equivalent to those used with tasklets, i.e. a task
had to pause some processing and can complete (typically a resource
becomes available again). In all cases, it's important to keep in mind
that the task must have gone through the regular scheduling path before
being blocked, otherwise the task priorities would be ignored.

The reason for this is that some wakeups are massively inter-thread
(e.g. server queues), that these inter-thread wakeups cause a huge
contention on the shared runqueue lock. A user reported 47% CPU spent
in process_runnable_tasks with only 32 threads and 80k requests in
queues. With this mechanism, purely one-to-one wakeups can avoid
taking the lock thanks to the mt_list used for the shared tasklet
queue.

Right now the shared tasklet queue moves everything to the TL_URGENT
queue. It's not dramatic but it would seem better to have a new shared
list dedicated to tasks, and that would deliver into TL_NORMAL, for an
even better fairness. This could be improved in the future.

3 years agoBUG/MINOR: mux-quic: fix POST with abortonclose
Amaury Denoyelle [Fri, 22 Apr 2022 14:52:14 +0000 (16:52 +0200)] 
BUG/MINOR: mux-quic: fix POST with abortonclose

Remove CS_EP_EOS set erroneously on qc_rcv_buf().

This fixes POST with abortonclose. Previously, request was preemptively
aborted by haproxy due to the incorrect EOS flag.

For the moment, EOS flag is not set anymore. It should be set to warn
about a premature close from the client.

3 years agoBUG/MEDIUM: mux-quic: fix stalled POST requets
Amaury Denoyelle [Fri, 22 Apr 2022 15:38:43 +0000 (17:38 +0200)] 
BUG/MEDIUM: mux-quic: fix stalled POST requets

Add a missing notify RECV for conn-stream in qcc_decode_qcs(). This
fixes stalled POST requests which may occur with some clients such as
ngtcp2.

3 years agoBUG/MAJOR: connection: Never remove connection from idle lists outside the lock
Christopher Faulet [Fri, 22 Apr 2022 15:56:24 +0000 (17:56 +0200)] 
BUG/MAJOR: connection: Never remove connection from idle lists outside the lock

Since the idle connections management changed to use eb-trees instead of MT
lists, a lock must be acquired to manipulate servers idle/safe/available
connection lists. However, it remains an unprotected use in
connect_server(), when a connection is removed from an idle list if the mux
has no more streams available. Thus it is possible to remove a connection
from an idle list on a thread, while another one is looking for a idle
connection. Of couse, this may lead to a crash.

To fix the bug, we must take care to acquire the idle connections lock
first. The bug was introduced by the commit f232cb3e9 ("MEDIUM: connection:
replace idle conn lists by eb trees").

The patch must be backported as far as 2.4.

3 years agoMEDIUM: httpclient/ssl: verify is configurable and disabled by default
William Lallemand [Fri, 22 Apr 2022 15:52:33 +0000 (17:52 +0200)] 
MEDIUM: httpclient/ssl: verify is configurable and disabled by default

Disable temporary the SSL verify by default in the httpclient. The
initialization of the @system-ca during the init of the httpclient is a
problem in some cases.

The verify can be reactivated with "httpclient-ssl-verify required" in
the global section.

3 years agoMINOR: httpclient/mworker: disable in the master process
William Lallemand [Fri, 22 Apr 2022 14:49:53 +0000 (16:49 +0200)] 
MINOR: httpclient/mworker: disable in the master process

Disable the httpclient in the master process.

3 years agoMEDIUM: httpclient/ssl: verify required
William Lallemand [Fri, 22 Apr 2022 12:48:45 +0000 (14:48 +0200)] 
MEDIUM: httpclient/ssl: verify required

The httpclient HTTPS requests now enable the "verify required" option.
To achieve this, the "@system-ca" ca-file is configured in the
httpclient ssl server. Which means all the system CAs will be loaded at
haproxy startup.

3 years agoMEDIUM: httpclient: change the init sequence
William Lallemand [Fri, 22 Apr 2022 13:16:09 +0000 (15:16 +0200)] 
MEDIUM: httpclient: change the init sequence

Change the init order of the httpclient, a different init sequence is
required to allow a more complicated init.

The init is splitted in two parts:

- the first part is executed before config_check_validity(), which
  allows to create proxy and more advanced stuff than STG_INIT, because
  we might want to use stuff already initialized in haproxy (trash
  buffers for example)

- the second part is executed after the config_check_validity(),
  currently it is used for the log configuration.

3 years agoMINOR: init: add the pre-check callback
William Lallemand [Thu, 21 Apr 2022 16:02:53 +0000 (18:02 +0200)] 
MINOR: init: add the pre-check callback

This adds a call to function <fct> to the list of functions to be called at
the step just before the configuration validity checks. This is useful when you
need to create things like it would have been done during the configuration
parsing and where the initialization should continue in the configuration
check.
It could be used for example to generate a proxy with multiple servers using
the configuration parser itself. At this step the trash buffers are allocated.
Threads are not yet started so no protection is required. The function is
expected to return non-zero on success, or zero on failure. A failure will make
the process emit a succinct error message and immediately exit.

3 years agoMINOR: conn-stream: Make cs_detach_* private and use cs_destroy() from outside
Christopher Faulet [Thu, 21 Apr 2022 12:22:53 +0000 (14:22 +0200)] 
MINOR: conn-stream: Make cs_detach_* private and use cs_destroy() from outside

A conn-stream is never detached from an endpoint or an application alone,
except on a reset. Thus, to avoid any error, these functions are now
private. And cs_destroy() function is added to destroy a conn-stream. This
function is called when a stream is released, on the front and back
conn-streams, and when a health-check is finished.

3 years agoMINOR: stream: Don't needlessly detach server endpoint on early client abort
Christopher Faulet [Thu, 21 Apr 2022 10:23:30 +0000 (12:23 +0200)] 
MINOR: stream: Don't needlessly detach server endpoint on early client abort

When a client abort is detected with the server conn-stream in CS_ST_INI
state, there is no reason to detach the endpoing because we know there is no
endpoint attached to this conn-stream. This patch depends on the commit
"BUG/MEDIUM: conn-stream: Set back CS to RDY state when the appctx is
created".

3 years agoBUG/MEDIUM: conn-stream: Set back CS to RDY state when the appctx is created
Christopher Faulet [Thu, 21 Apr 2022 09:52:07 +0000 (11:52 +0200)] 
BUG/MEDIUM: conn-stream: Set back CS to RDY state when the appctx is created

When an appctx is created on the server side, we now set the corresponding
conn-stream to ready state (CS_ST_RDY). When it happens, the backend
conn-stream is in CS_ST_INI state. It is not consistant to let the
conn-stream in this state because it means it is possible to have a target
installed in CS_ST_INI state, while with a connection, the conn-stream is
switch to CS_ST_RDY or CS_ST_EST state.

It is especially anbiguous because we may be tempted to think there is no
endpoint attached to the conn-stream before the CS_ST_CON state. And it is
indeed the reason for a bug leading to a crash because a cs_detach_endp() is
performed if an abort is detected on the backend conn-stream in CS_ST_INI
state. With a mux or a appctx attached to the conn-stream, "->endp" field is
set to NULL. It is unexpected. The API will be changed to be sure it is not
possible. But it exposes a consistency issue with applets.

So, the conn-stream must not stay in CS_ST_INI state when an appctx is
attached. But there is no reason to set it in CS_ST_REQ. The conn-stream
must be set to CS_ST_RDY to handle applets and connections in the same
way. Note that if only the target is set but no appctx is created, the
backend conn-stream is switched from CS_ST_INI to CS_ST_REQ state to be able
to create the corresponding appctx. This part is unchanged.

This patch depends on the commit "MINOR: backend: Don't allow to change
backend applet".

The ambiguity exists on previous versions. But the issue is
2.6-specific. Thus, no backport is needed.

3 years agoBUG/MINOR: backend: Don't allow to change backend applet
Christopher Faulet [Thu, 21 Apr 2022 08:28:30 +0000 (10:28 +0200)] 
BUG/MINOR: backend: Don't allow to change backend applet

This part was inherited from haproxy-1.5. But since a while (at least 1.8),
the backend applet, once created, is no longer changed. Thus there is no
reason to still check if the target has changed. And in fact, if it was
still possible, there would be a memory leak because the old applet would be
lost and never released.

There is no reason to backport this fix because the leak only exists on a
dead code path.

3 years agoBUG/MINOR: cache: Disable cache if applet creation fails
Christopher Faulet [Thu, 21 Apr 2022 09:30:43 +0000 (11:30 +0200)] 
BUG/MINOR: cache: Disable cache if applet creation fails

When we want to serve a resource from the cache, if the applet creation
fails, the "cache-use" action must not yield. Otherwise, the stream will
hang. Instead, we now disable the cache. Thus the request may be served by
the server.

This patch must be backported as far as 1.8.

3 years agoMINOR: conn-stream: Rely on endpoint shutdown flags to shutdown an applet
Christopher Faulet [Thu, 21 Apr 2022 06:50:00 +0000 (08:50 +0200)] 
MINOR: conn-stream: Rely on endpoint shutdown flags to shutdown an applet

cs_applet_shut() now relies on CS_EP_SH* flags to performed the applet
shutdown. It means the applet release callback is called if there is no
CS_EP_SHR or CS_EP_SHW flags set. And it set these flags, CS_EP_SHRR and
CS_EP_SHWN more specifically, before exiting.

This way, cs_applet_shut() is the really equivalent to cs_conn_shut().

3 years agoCLEANUP: conn-stream: Rename cs_applet_release()
Christopher Faulet [Thu, 21 Apr 2022 06:44:09 +0000 (08:44 +0200)] 
CLEANUP: conn-stream: Rename cs_applet_release()

This function does not release the applet but only call the applet release
callback. It is equivalent to cs_conn_shut() but for applets. Thus the
function is renamed cs_applet_shut().

3 years agoCLEANUP: conn-stream: Rename cs_conn_close() and cs_conn_drain_and_close()
Christopher Faulet [Thu, 21 Apr 2022 06:38:54 +0000 (08:38 +0200)] 
CLEANUP: conn-stream: Rename cs_conn_close() and cs_conn_drain_and_close()

These functions don't close the connection but only perform shutdown for
reads and writes at the mux level. It is a bit ambiguous. Thus,
cs_conn_close() is renamed cs_conn_shut() and cs_conn_drain_and_close() is
renamed cs_conn_drain_and_shut(). These both functions rely on
cs_conn_shutw() and cs_conn_shutr().