qcs_new() allocates several elements in intermediary steps. All elements
must first be properly initialized to be able to free qcs instance in
case of an intermediary failure.
Previously, qc_stream_desc allocation was done in the middle of
qcs_new() before some elements initializations. In case this fails, a
crash can happened as some elements are left uninitialized.
To fix this, move qc_stream_desc allocation at the end of qcs_new().
This ensures that all qcs elements are initialized first.
This should be backported up to 2.6.
qc_new_conn() allocates several elements in intermediary steps. If one
of the fails, a global free is done on the quic_conn and its elements.
This requires that most elements are first initialized to NULL or
equivalent to ensure freeing operation is done only on proper values.
Once of this element is qc.tx.cc_buf_area. It was initialized too late
which could caused crashes. This is introduced by
9f7cfb0a56
MEDIUM: quic: Allow the quic_conn memory to be asap released.
No need to backport.
CIDs tree is now allocated dynamically since the following commit :
276697438d
MINOR: quic: Use a pool for the connection ID tree.
This can caused a crash if qc_new_conn() is interrupted due to an
intermediary failed allocation. When freeing all connection members,
free_quic_conn_cids() is used. However, this function does not support a
NULL cids.
To fix this, simply check that cids is NULL during free_quic_conn_cids()
prologue.
This bug was reproduced using -dMfail.
No need to backport.
Since commit 5afcb686b ("MAJOR: connection: purge idle conn by last usage")
in 2.9-dev4, the test on conn->toremove_list added to conn_get_idle_flag()
in 2.8 by commit 3a7b539b1 ("BUG/MEDIUM: connection: Preserve flags when a
conn is removed from an idle list") becomes misleading. Indeed, now both
toremove_list and idle_list are shared by a union since the presence in
these lists is mutually exclusive. However, in conn_get_idle_flag() we
check for the presence in the toremove_list to decide whether or not to
delete the connection from the tree. This test now fails because instead
it sees the presence in the idle or safe list via the union, and concludes
the element must not be removed. Thus the element remains in the tree and
can be found later after the connection is released, causing crashes that
Tristan reported in issue #2292.
The following config is sufficient to reproduce it with 2 threads:
defaults
mode http
timeout client 5s
timeout server 5s
timeout connect 1s
listen front
bind :8001
server next 127.0.0.1:8002
frontend next
bind :8002
timeout http-keep-alive 1
http-request redirect location /
Sending traffic with a few concurrent connections and some short timeouts
suffices to instantly crash it after ~10k reqs:
$ h2load -t 4 -c 16 -n 10000 -m 1 -w 1 http://0:8001/
With Amaury we analyzed the conditions in which the function is called
in order to figure a better condition for the test and concluded that
->toremove_list is never filled there so we can safely remove that part
from the test and just move the flag retrieval back to what it was prior
to the 2.8 patch above. Note that the patch is not reverted though, as
the parts that would drop the unexpected flags removal are unchanged.
This patch must NOT be backported. The code in 2.8 works correctly, it's
only the change in 2.9 that makes it misbehave.
In conn_delete_from_tree() there remains a cast of the toremove_list
to struct list while the introduction of the union precisely was to
avoid this cast. It's a leftover from the first version of patch
5afcb686b ("MAJOR: connection: purge idle conn by last usage") merged
into in 2.9-dev4, let's fix that.
No backport is needed.
HTTP/3 specification has several requirement when parsing authority or
host header inside a request. However, it was until then only partially
implemented.
This commit fixes this by ensuring the following :
* reject an empty authority/host header
* reject a host header if an authority was found with a different value
* no authority neither host header present
This must be backported up to 2.6.
Support stream opening with an initial max-stream-data of 0.
In normal case, QC_SF_BLK_SFCTL is set when a qcs instance cannot
transfer more data due to flow-control. This flag is set when
transfering data from MUX to quic-conn instance.
However, it's possible to define an initial value of 0 for
max-stream-data. In this case, qcs instance is blocked despite
QC_SF_BLK_SFCTL not set. No STREAM frame is prepared for this stream as
it's not possible to emit any byte, so QC_SF_BLK_SFCTL flag is never
set.
This behavior should cause no harm. However, this can cause a BUG_ON()
crash on qcc_io_send(). Indeed, when sending is retried, it ensures that
only qcs instance waiting for a new qc_stream_buf or with
QC_SF_BLK_SFCTL set is present in the send_list.
To fix this, initialize qcs with 0 value for msd and QC_SF_BLK_SFCTL.
The flag is removed only if transport parameter msd value is non null.
This should be backported up to 2.6.
When receiving a RESET_STREAM on a send-only stream, it is mandatory to
close the connection with an error STREAM_STATE error. However, this was
badly implemented as this caused two invocation of qcc_set_error() which
is forbidden by the mux-quic API.
To fix this, rely on qcc_get_qcs() to properly detect the error. Remove
qcc_set_error() usage from qcc_recv_reset_stream() instead.
This must be backported up to 2.7.
RFC 9000 indicates that a QUIC packet with no frame must trigger a
connection closure with PROTOCOL_VIOLATION error code. Implement this
via an early return inside qc_parse_pkt_frms().
This should be backported up to 2.6.
Move all QUIC trace definitions from quic_conn.h to quic_trace-t.h. Also
remove multiple definition trace_quic macro definition into
quic_trace.h. This forces all QUIC source files who relies on trace to
include it while reducing the size of quic_conn.h.
This bug was detected when compiling haproxy against aws-lc TLS stack
during QUIC interop runner tests. Some algorithms could be negotiated by haproxy
through the TLS stack but not fully supported by haproxy QUIC implentation.
This leaded tls_aead() to return NULL (same thing for tls_md(), tls_hp()).
As these functions returned values were never checked, they could triggered
segfaults.
To fix this, one closes the connection as soon as possible with a
handshake_failure(40) TLS alert. Note that as the TLS stack successfully
negotiates an algorithm, it provides haproxy with CRYPTO data before entering
->set_encryption_secrets() callback. This is why this callback
(ha_set_encryption_secrets() on haproxy side) is modified to release all
the CRYPTO frames before triggering a CONNECTION_CLOSE with a TLS alert. This is
done calling qc_release_pktns_frms() for all the packet number spaces.
Modify some quic_tls_keys_hexdump to avoid crashes when the ->aead or ->hp EVP_CIPHER
are NULL.
Modify qc_release_pktns_frms() to do nothing if the packet number space passed
as parameter is not intialized.
This bug does not impact the QUIC TLS compatibily mode (USE_QUIC_OPENSSL_COMPAT).
Thank you to @ilia-shipitsin for having reported this issue in GH #2309.
Must be backported as far as 2.6.
WolfSSL 5.6.3 does not pass all the haproxy reg-tests since some fixes
are still unreleased in the master branch.
Build wolfSSL with a recent git revision to have passing reg-tests.
The openssl-compat.h file has some function which were implemented in
order to provide compatibility with openssl < 1.0.0. Most of them where
to support the 0.9.8 version, but we don't support this version anymore.
This patch removes the deprecated code from openssl-compat.h
Released version 2.9-dev7 with the following main changes :
- MINOR: support for http-request set-timeout client
- BUG/MINOR: mux-quic: remove full demux flag on ncbuf release
- CLEANUP: freq_ctr: make all freq_ctr readers take a const
- CLEANUP: stream: make the dump code not depend on the CLI appctx
- MINOR: stream: split stats_dump_full_strm_to_buffer() in two
- CLEANUP: stream: use const filters in the dump function
- CLEANUP: stream: make strm_dump_to_buffer() take a const stream
- MINOR: stream: make strm_dump_to_buffer() take an arbitrary buffer
- MINOR: stream: make strm_dump_to_buffer() show the list of filters
- MINOR: stream: make stream_dump() always multi-line
- MINOR: streams: add support for line prefixes to strm_dump_to_buffer()
- MEDIUM: stream: now provide full stream dumps in case of loops
- MINOR: debug: use the more detailed stream dump in panics
- CLEANUP: stream: remove the now unused stream_dump() function
- Revert "BUG/MEDIUM: quic: missing check of dcid for init pkt including a token"
- MINOR: stream: fix output alignment of stuck thread dumps
- BUG/MINOR: proto_reverse_connect: fix FD leak on connection error
- BUG/MINOR: tcp_act: fix attach-srv rule ACL parsing
- MINOR: connection: define error for reverse connect
- MINOR: connection: define mux flag for reverse support
- MINOR: tcp_act: remove limitation on protocol for attach-srv
- BUG/MINOR: proto_reverse_connect: fix FD leak upon connect
- BUG/MAJOR: plock: fix major bug in pl_take_w() introduced with EBO
- Revert "MEDIUM: sample: Small fix in function check_operator for eror reporting"
- DOC: sample: Add a comment in 'check_operator' to explain why 'vars_check_arg' should ignore the 'err' buffer
- DEV: sslkeylogger: handle file opening error
- MINOR: quic: define quic-socket bind setting
- MINOR: quic: handle perm error on bind during runtime
- MINOR: backend: refactor specific source address allocation
- MINOR: proto_reverse_connect: support source address setting
- BUILD: pool: Fix GCC error about potential null pointer dereference
- MINOR: hlua: Set context's appctx when the lua socket is created
- MINOR: hlua: Don't preform operations on a not connected socket
- MINOR: hlua: Save the lua socket's timeout in its context
- MINOR: hlua: Save the lua socket's server in its context
- MINOR: hlua: Test the hlua struct first when the lua socket is connecting
- BUG/MEDIUM: hlua: Initialize appctx used by a lua socket on connect only
- DEBUG: mux-h1: Fix event label from trace messages about payload formatting
- BUG/MINOR: mux-h1: Handle read0 in rcv_pipe() only when data receipt was tried
- BUG/MINOR: mux-h1: Ignore C-L when sending H1 messages if T-E is also set
- BUG/MEDIUM: h1: Ignore C-L value in the H1 parser if T-E is also set
- REGTESTS: filters: Don't set C-L header in the successful response to CONNECT
- MINOR: mux-h1: Add flags if outgoing msg contains a header about its payload
- MINOR: mux-h1: Rely on H1S_F_HAVE_CHNK to add T-E in outgoing messages
- BUG/MEDIUM: mux-h1: Add C-L header in outgoing message if it was removed
- BUG/MEDIUM: mux-h1; Ignore headers modifications about payload representation
- BUG/MINOR: h1-htx: Keep flags about C-L/T-E during HEAD response parsing
- MINOR: h1-htx: Declare successful tunnel establishment as bodyless
- BUILD: quic: allow USE_QUIC to work with AWSLC
- CI: github: add USE_QUIC=1 to aws-lc build
- BUG/MINOR: hq-interop: simplify parser requirement
- MEDIUM: cache: Add "Origin" header to secondary cache key
- MINOR: haproxy: permit to register features during boot
- MINOR: tcp_rules: tcp-{request,response} requires TCP or HTTP mode
- MINOR: stktable: "stick" requires TCP or HTTP mode
- MINOR: filter: "filter" requires TCP or HTTP mode
- MINOR: backend/balance: "balance" requires TCP or HTTP mode
- MINOR: flt_http_comp: "compression" requires TCP or HTTP mode
- MINOR: http_htx/errors: prevent the use of some keywords when not in tcp/http mode
- MINOR: fcgi-app: "use-fcgi-app" requires TCP or HTTP mode
- MINOR: cfgparse-listen: "http-send-name-header" requires TCP or HTTP mode
- MINOR: cfgparse-listen: "dynamic-cookie-key" requires TCP or HTTP mode
- MINOR: proxy: dynamic-cookie CLIs require TCP or HTTP mode
- MINOR: cfgparse-listen: "http-reuse" requires TCP or HTTP mode
- MINOR: proxy: report a warning for max_ka_queue in proxy_cfg_ensure_no_http()
- MINOR: cfgparse-listen: warn when use-server rules is used in wrong mode
- DOC: config: unify "log" directive doc
- MINOR: sink/log: fix some typos around postparsing logic
- MINOR: sink: remove useless check after sink creation
- MINOR: sink: don't rely on p->parent in sink appctx
- MINOR: sink: don't rely on forward_px to init sink forwarding
- MINOR: sink: refine forward_px usage
- MINOR: sink: function to add new sink servers
- BUG/MEDIUM: stconn: Fix comparison sign in sc_need_room()
- BUG/MEDIUM: actions: always apply a longest match on prefix lookup
Many actions take arguments after a parenthesis. When this happens, they
have to be tagged in the parser with KWF_MATCH_PREFIX so that a sub-word
is sufficient (since by default the whole block including the parenthesis
is taken).
The problem with this is that the parser stops on the first match. This
was OK years ago when there were very few actions, but over time new ones
were added and many actions are the prefix of another one (e.g. "set-var"
is the prefix of "set-var-fmt"). And what happens in this case is that the
first word is picked. Most often that doesn't cause trouble because such
similar-looking actions involve the same custom parser so actually the
wrong selection of the first entry results in the correct parser to be
used anyway and the error to be silently hidden.
But it's getting worse when accidentally declaring prefixes in multiple
files, because in this case it will solely depend on the object file link
order: if the longest name appears first, it will be properly detected,
but if it appears last, its other prefix will be detected and might very
well not be related at all and use a distinct parser. And this is random
enough to make some actions succeed or fail depending on the build options
that affect the linkage order. Worse: what if a keyword is the prefix of
another one, with a different parser but a compatible syntax ? It could
seem to work by accident but not do the expected operations.
The correct solution is to always look for the longest matching name.
This way the correct keyword will always be matched and used and there
will be no risk to randomly pick the wrong anymore.
This fix must be backported to the relevant stable releases.
sc_need_room() function may be called with a negative value. In this case,
the intent is to be notified if any space was made in the channel buffer. In
the function, we get the min between the requested room and the maximum
possible room in the buffer, considering it may be an HTX buffer.
However this max value is unsigned and leads to an unsigned comparison,
casting the negative value to an unsigned value. Of course, in this case,
this always leads to the wrong result. This bug seems to have no effect but
it is hard to be sure.
To fix the issue, we take care to respect the requested room sign by casting
the max value to a signed integer.
This patch must be backported to 2.8.
now forward_px only serves as a hint to know if a proxy was created
specifically for the sink, in which case the sink is responsible for it.
Everywhere forward_px was used in appctx context: get the parent proxy from
the sft->srv instead.
This permits to finally get rid of the double link dependency between sink
and proxy.
Removing unnecessary dependency on proxy->parent pointer in
sink appctx functions by directly using the sink sft from the
applet->svcctx to get back to sink related structs.
Thanks to this, proxy used for a ringbuf does not have to be exclusive
to a single sink anymore.
It's useless to check if sink has been created with BUF type after
calling sink_new_buf() since the goal of the function is to create
a new sink of BUF type.
Fixing some typos that have been overlooked during the recent log/sink
API improvements. Using this patch to make sink_new_from_logsrv() static
since it is not used outside of sink.c
"log" directive description was found 2 times in the configuration file:
First, in 3.1 in the "global parameters" chapter, and then in 4.2 in the
per-proxy keyword options.
Both descriptions are almost identical: having to maintain the "same"
documentation in 2 different places is error-prone. Due to this, some
precisions have been added in one of them, and were missing from
the other, and vice-versa, probably because one didn't see that the
"log" directive was also documented elsewhere.
To prevent the 2 descriptions from further diverging, and make it easier
to maintain, we merge them in the per-proxy "log" directive description
(in 4.2 chapter), and we add a pointer to it in the global "log" to
encourage the user to refer to the per-proxy "log" documentation for
usage details.
haproxy will report a warning when "use-server" keyword is used within a
backend that doesn't support server rules to inform the user that rules
will be ignored.
To this day, only TCP and HTTP backends can make use of it.
Display a warning when max_ka_queue is set (it is the case when
"max-keep-alive-queue" directive is used within a proxy section) to inform
the user that this directives depends on the "http" mode to work and thus
will safely be ignored.