The "show ca-file" and "show crl-file" commands mix some generic pointers
from the "ctx.cli" struct and context-specific ones from "ctx.ssl" while
both are in a union. It's fortunate that the p0 pointer in use is located
immediately before the first one used (it overlaps with next_ckchi_link,
and old_cafile_entry is safe). But should these fields be reordered or
slightly updated this will break.
Comments were added on top of the affected functions to indicate what they
use.
This needs to be backported to 2.5.
When "show map" initializes itself, it first takes the reference to the
starting point under a lock, then releases it before switching to state
STATE_LIST, and takes the lock again. The problem is that it is possible
for another thread to remove the first element during this unlock/lock
sequence, and make the list run anywhere. This is of course extremely
unlikely but not impossible.
Let's initialize the pointer in the STATE_LIST part under the same lock,
which is simpler and more reliable.
This should be backported to all versions.
In case of write error in "show map", the backref is detached but
the list wasn't locked when this is done. The risk is very low but
it may happen that two concurrent "show map" one of which would fail
or one "show map" failing while the same entry is being updated could
cause a crash.
This should be backported to all stable versions.
Commit e7f74623e ("MINOR: stats: don't output internal proxies (PR_CAP_INT)")
in 2.5 ensured we don't dump internal proxies on the stats page, but the
same is needed for "show backend", as since the addition of the HTTP client
it now appears there:
$ socat /tmp/sock1 - <<< "show backend"
# name
<HTTPCLIENT>
This needs to be backported to 2.5.
This command was introduced in 1.8 with commit eceddf722 ("MEDIUM: cli:
'show cli sockets' list the CLI sockets") but its yielding doesn't work.
Each time it enters, it restarts from the last bind_conf but enumerates
all listening sockets again, thus it loops forever. The risk that it
happens in field is low but it easily triggers on port ranges after
400-500 sockets depending on the length of their addresses:
global
stats socket /tmp/sock1 level admin
stats socket 192.168.8.176:30000-31000 level operator
$ socat /tmp/sock1 - <<< "show cli sockets"
(...)
ipv4@192.168.8.176:30426 operator all
ipv4@192.168.8.176:30427 operator all
ipv4@192.168.8.176:30428 operator all
ipv4@192.168.8.176:30000 operator all
ipv4@192.168.8.176:30001 operator all
ipv4@192.168.8.176:30002 operator all
^C
This patch adds the minimally needed restart point for the listener so
that it can easily be backported. Some more cleanup is needed though.
The "show resolvers" command is bogus, it tries to implement a yielding
mechanism except that if it yields it restarts from the beginning, until
it manages to fill the buffer with only line breaks, and faces error -2
that lets it reach the final state and exit.
The risk is low since it requires about 50 name servers to reach that
state, but it's not impossible, especially when using multiple sections.
In addition, the extraneous line breaks, if sent over an interactive
connection, will desynchronize the commands and make the client believe
the end was reached after the first nameserver. This cannot be fixed
separately because that would turn this bug into an infinite loop since
it's the line feed that manages to fill the buffer and stop it.
The fix consists in saving the current resolvers section into ctx.cli.p1
and the current nameserver into ctx.cli.p2.
This should be backported, but that code moved a lot since it was
introduced and has always been bogus. It looks like it has mostly
stabilized in 2.4 with commit c943799c86 so the fix might be backportable
to 2.4 without too much effort.
Try to create a "default" resolvers section at startup, but does not
display any error nor warning. This section is initialized using the
/etc/resolv.conf of the system.
This is opportunistic and with no guarantee that it will work (but it should
on most systems).
This is useful for the httpclient as it allows to use the DNS resolver
without any configuration in most of the cases.
The function is called from the httpclient_pre_check() function to
ensure than we tried to create the section before trying to initiate the
httpclient. But it is also called from the resolvers.c to ensure the
section is created when the httpclient init was disabled.
Release the expression used by the set-{src,dst}[-port] actions so we
keep valgrind happy upon an exit or an haproxy -c.
Could be backported in every supported version.
Move the resolv.conf parser from the cfg_parse_resolvers so it could be
used separately.
Some changes were made in the memprintf in order to use a char **
instead of a char *. Also the variable is tested before each memprintf
so could skip them if no warnmsg nor errmsg were set.
Cleanup the alert and warning handling in the "parse-resolve-conf"
parser to use the errmsg and warnmsg variables and memprintf.
This will allow to split the parser and shut the alert/warning if
needed.
When an HTTP header rewrite failure is triggered, and 500-internal-error
response is returned. A "PR" termination state is logged if the error
occurred on the request and "PH" if the error is reported for the response.
The documentation was updated accordingly.
This patch is related to issue #1597.
The commit 2eb5243e7 ("BUG/MEDIUM: mux-h1: Set outgoing message to DONE when
payload length is reached") introduced a regression. An internal error is
reported when we try to forward a message with trailers while the
content-length header was specified. Indeed, this case does not exist for H1
messages but it is possible in H2.
This patch should solve the issue #1684. It must be backported as far as
2.4.
This bug was already fixed at many places (stats, promex, lua) but the FCGI
multiplexer is also affected. When there is no content-length specified in
the response and when the END_REQUEST record is delayed, the response may be
truncated because an abort is erroneously detected. If the connection is not
closed because "keep-conn" option is set, the response is aborted at the end
of the server timeout.
This bug is a design issue with the HTX. It should be addressed. But it will
probably not be possible to backport them as far as 2.4. So, for now, the
only solution is to explicitly add an EOT block with the EOM flag in this
case.
This patch should fix the issue #1682. It must be backported as far as 2.4.
The commit a6c4a4834 ("BUG/MEDIUM: conn-stream: Don't erase endpoint flags
on reset") was too laxy on reset. Only app layer flags must be preserved. On
reset, the endpoint is detached. Thus all flags set by the endpoint itself
or concerning its type must be removed.
Without this fix, we can experienced crashes when a stream is released while
a server connection attempt failed. Indeed, in this case, endpoint of the
backend conn-stream is reset. But the endpoint type is still set. Thus when
the stream is released, the endpoint is detached again.
This patch is 2.6-specific. No backport needed. This commit depends on the
previous one ("MINOR: conn-stream: Add mask from flags set by endpoint or
app layer").
In flags set on the endpoints, some are set by endpoints itself and some are
set by the app layer. To help flags manipulations, 2 masks have been
added. The first one, CS_EP_ENDP_MASK, for all flags that an endpoint may
set. The other one, CS_EP_APP_MASK, for flags that the app layer may set.
This patch is mandatory for the next commit.
Documentation about the 4 options in the global section for the
httpclient:
- httpclient.ssl.verify
- httpclient.ssl.ca-file
- httpclient.resolvers.id
- httpclient.resolvers.prefer
The httpclient.resolvers.prefer global keyword allows to configure an
ipv4 or ipv6 preference when resolving. This could be useful in
environment where the ipv6 is not supported.
By default the httpclient uses the resolvers section whose ID is
"default", the httpclient.resolvers.id global option allows to configure
another section to use.
The hard_error_ssl flag is set when the configuration is explicitely
done for the ssl in the httpclient.
If no configuration was made, the features are simply disabled and no
alert is emitted.
Cleanup the error handling in the initialization so we rely on the
ERR_CODE and use memprintf() to set the errmsg before printing it at the
end of the functions.
httpclient_set_dst() allows one to set the destination address instead
of using the one in the URL or resolving one from the host.
This function also support other types of socket like sockpair@, unix@,
anything that could be used on a server line.
In order to still support this behavior, the address must be set on the
backend in this particular case because the frontend connection does not
support anything other than ipv4 or ipv6.
To allow the http-request set-dst to work for the httpclient DNS
resolving, some changes need to be done:
- The destination address need to be set in the frontend (s->csf->dst)
instead of the backend (s->csb->dst) to be able to use
tcp_action_req_set_dst()
- SRV_F_MAPPORTS need to be set on the proxy in order to allow the port
change in alloc_dst_address()
The httpclient_resolve_init() adds http-request actions which does the
resolving using the Host header of the HTTP request.
The parse_http_req_cond function is directly used over an array of http
rules.
The do-resolve rule uses the "default" resolvers section. If this
section does not exist in the configuration, the resolving is disabling.
The httpclient DNS resolver will need a more efficient URL parser which
splits the URL into parts and does not try to resolve.
httpclient_spliturl uses the http_uri_parser in order to split the URL
into several ist.
The result of the function host part is then processed into str2ip2(),
and fails if it it not an IP, allowing us to resolve the domain later.
We rely on the largest ID which was used to open streams to know if the
stream we received STREAM frames for is closed or not. If closed, we return the
same status as the one for a STREAM frame which was a already received one for
on open stream.
It is possible that we continue to receive retransmitted STREAM frames after
the mux have been released. We rely on the ->rx.streams[].nb_streams counter
to check the stream was closed. If not, at this time we drop the packet.
This is required when the retransmitted frame types when the mux is released.
We add a counter for the number of streams which were opened or closed by the mux.
After the mux has been released, we can rely on this counter to know if the STREAM
frames are retransmitted ones or not.
That's similar to what was done for conn_streams and connections. The
flags were only set exactly when the relevant pointers were allocated,
so better test the pointer than the flag and stop setting the flag.
Just like for the conn_stream, now that these addresses are dynamically
allocated, there is no single case where the pointer is set without the
corresponding flag, and the flag is used as a permission to dereference
the pointer. Let's just replace the test of the flag with a test of the
pointer and remove all flag assignment. This makes the code clearer
(especially in "if" conditions) and saves the need for future code to
think about properly setting the flag after setting the pointer.
Some of the protocol-level ->connect() functions currently dereference
the connection's destination address while others test it and return an
error. There's normally no more non-bogus code path that calls such
functions without a valid destination address on the connection, so
let's unify these functions and just place a BUG_ON() there, and drop
the useless test that's supposed to return an internal error.
These flags indicate that the ->src or ->dst field in the conn_stream
is not null, which is something the caller already sees (and even tests
from the two sets of functions that set them). They maintain some burden
because an agent trying to set a source or destination has to manually
set the flags in addition to setting the pointer, so they provide no
value anymore, let's drop them.
This flag is no longer needed now that it must always match the presence
of a destination address on the backend conn_stream. Worse, before previous
patch, if it were to be accidently removed while the address is present, it
could result in a leak of that address since alloc_dst_address() would first
be called to flush it.
Its usage has a long history where addresses were stored in an area shared
with the connection, but as this is no longer the case, there's no reason
for putting this burden onto application-level code that should not focus
on setting obscure flags.
The only place where that made a small difference is in the dequeuing code
in case of queue redistribution, because previously the code would first
clear the flag, and only later when trying to deal with the queue, would
release the address. It's not even certain whether there would exist a
code path going to connect_server() without calling pendconn_dequeue()
first (e.g. retries on queue timeout maybe?).
Now the pendconn_dequeue() code will rely on SF_ASSIGNED to decide to
clear and release the address, since that flag is always set while in
a server's queue, and its clearance implies that we don't want to keep
the address. At least it remains consistent and there's no more risk of
leaking it.
These functions dynamically allocate a source or destination address but
start by clearing the previous one. There's a non-null risk of leaking
addresses there in case of misuse. Better have them do nothing if the
address was already allocated.
HTTP/3 implementation must ignore unknown frame type to support protocol
evolution. Clients can deliberately use unknown type to test that the
server is conformant : this principle is called greasing.
Quiche client uses greasing on H3 frame type with a zero length frame.
This reveals a bug in H3 parsing code which causes the transfer to be
interrupted. Fix this by removing the break statement on ret variable.
Now the parsing loop is only interrupted if input buffer is empty or the
demux is blocked.
This should fix http/3 freeze transfers with the quiche client. Thanks
to Lucas Pardue from Cloudflare for his report on the bug. Frédéric
Lecaille quickly found the source of the problem which helps me to write
this patch.
If the request channel buffer is full, H3 demuxing must be interrupted
on the stream until some read is performed. This condition is reported
if the HTX stream buffer qcs.rx.app_buf is full.
In this case, qcs instance is marked with a new flag QC_SF_DEM_FULL.
This flag cause the H3 demuxing to be interrupted. It is cleared when
the HTX buffer is read by the conn-stream layer through rcv_buf
operation.
When the flag is cleared, the MUX tasklet is woken up. However, as MUX
iocb does not treat Rx for the moment, this is useless. It must be fix
to prevent possible freeze on POST transfers.
In practice, for the moment the HTX buffer is never full as the current
Rx code is limited by the quic-conn receive buffer size and the
incomplete flow-control implementation. So for now this patch is not
testable under the current conditions.
Released version 2.6-dev8 with the following main changes :
- BUG/MINOR: quic: fix use-after-free with trace on ACK consume
- BUG/MINOR: rules: Forbid captures in defaults section if used by a backend
- BUG/MEDIUM: rules: Be able to use captures defined in defaults section
- BUG/MINOR: rules: Fix check_capture() function to use the right rule arguments
- BUG/MINOR: http-act: make release_http_redir() more robust
- BUG/MINOR: sample: add missing use_backend/use-server contexts in smp_resolve_args
- MINOR: sample: don't needlessly call c_none() in sample_fetch_as_type()
- MINOR: sample: make the bool type cast to bin
- MEDIUM: backend: add new "balance hash <expr>" algorithm
- MINOR: init: add global setting "fd-hard-limit" to bound system limits
- BUILD: pollers: use an initcall to register the pollers
- BUILD: xprt: use an initcall to register the transport layers
- BUILD: thread: use initcall instead of a constructor
- BUILD: http: remove the two unused constructors in rules and ana
- CLEANUP: compression: move the default setting of maxzlibmem to defaults
- MINOR: tree-wide: always consider EWOULDBLOCK in addition to EAGAIN
- BUG/MINOR: connection: "connection:close" header added despite 'close-spread-time'
- MINOR: fd: add functions to set O_NONBLOCK and FD_CLOEXEC
- CLEANUP: tree-wide: use fd_set_nonblock() and fd_set_cloexec()
- CLEANUP: tree-wide: remove 25 occurrences of unneeded fcntl.h
- REGTESTS: fix the race conditions in be2dec.vtc ad field.vtc
- REGTESTS: webstats: remove unused stats socket in /tmp
- MEDIUM: httpclient: disable SSL when the ca-file couldn't be loaded
- BUG/MINOR: httpclient/lua: error when the httpclient_start() fails
- BUG/MINOR: ssl: free the cafile entries on deinit
- BUG/MINOR: ssl: memory leak when trying to load a directory with ca-file
- MEDIUM: httpclient: re-enable the verify by default
- BUG/MEDIUM: ssl/cli: fix yielding in show_cafile_detail
- BUILD: compiler: properly distinguish weak and global symbols
- MINOR: connection: Add way to disable active connection closing during soft-stop
- BUG/MEDIUM: http-ana: Fix memleak in redirect rules with ignore-empty option
- CLEANUP: Destroy `http_err_chunks` members during deinit
- BUG/MINOR: resolvers: Fix memory leak in resolvers_deinit()
- MINOR: Call deinit_and_exit(0) for `haproxy -vv`
- BUILD: fd: disguise the fd_set_nonblock/cloexec result
- BUG/MINOR: pools: make sure to also destroy shared pools in pool_destroy_all()
- MINOR: ssl: add a new global option "tune.ssl.hard-maxrecord"
- CLEANUP: errors: also call deinit_errors_buffers() on deinit()
- CLEANUP: chunks: release trash also in deinit
- CLEANUP: deinit: release the pre-check callbacks
- CLEANUP: deinit: release the config postparsers
- CLEANUP: listeners/deinit: release accept queue tasklets on deinit
- CLEANUP: connections/deinit: destroy the idle_conns tasks
- BUG/MINOR: mux-quic: fix build in release mode
- MINOR: mux-quic: adjust comment on emission function
- MINOR: mux-quic: remove unused bogus qcc_get_stream()
- BUG/MINOR: mux-quic: fix leak if cs alloc failure
- MINOR: mux-quic: count local flow-control stream limit on reception
- BUG/MINOR: h3: fix incomplete POST requests
- BUG/MEDIUM: h3: fix use-after-free on mux Rx buffer wrapping
- MINOR: mux-quic: partially copy Rx frame if almost full buf
- MINOR: h3: change frame demuxing API
- MINOR: mux-quic: add a app-layer context in qcs
- MINOR: h3: implement h3 stream context
- MINOR: h3: support DATA demux if buffer full
- MINOR: quic: decode as much STREAM as possible
- MINOR: quic: Improve qc_prep_pkts() flexibility
- MINOR: quic: Prepare quic_frame struct duplication
- MINOR: quic: Do not retransmit frames from coalesced packets
- MINOR: quic: Add traces about TX frame memory releasing
- MINOR: quic: process_timer() rework
- MEDIUM: quic: New functions for probing rework
- MEDIUM: quic: Retransmission functions rework
- MEDIUM: quic: qc_requeue_nacked_pkt_tx_frms() rework
- MINOR: quic: old data distinction for qc_send_app_pkt()
- MINOR: quic: Mark packets as probing with old data
- MEDIUM: quic: Mark copies of acknowledged frames as acknowledged
- MEDIUM: quic: Enable the new datagram probing process
- MINOR: quic: Do not send ACK frames when probing
- BUG/MINOR: quic: Wrong returned status by qc_build_frms()
- BUG/MINOR: quic: Avoid sending useless PADDING frame
- BUG/MINOR: quic: Traces fix about remaining frames upon packet build failure
- MINOR: quic: Wake up the mux to probe with new data
- BUG/MEDIUM: quic: Possible crash on STREAM frame loss
- BUG/MINOR: quic: Missing Initial packet length check
- CLEANUP: quic: Rely on the packet length set by qc_lstnr_pkt_rcv()
- MINOR: quic: Drop 0-RTT packets if not allowed
- BUG/MINOR: httpclient/ssl: use the correct verify constant
- BUG/MEDIUM: conn-stream: Don't erase endpoint flags on reset
- BUG/MEDIUM: httpclient: Fix loop consuming HTX blocks from the response channel
- BUG/MINOR: httpclient: Count metadata in size to transfer via htx_xfer_blks()
- MINOR: httpclient: Don't use co_set_data() to decrement output
- BUG/MINOR: conn_stream: do not confirm a connection from the frontend path
- MEDIUM: quic: do not ACK packet with STREAM if MUX not present
- MEDIUM: quic: do not ack packet with invalid STREAM
- MINOR: quic: Drop 0-RTT packets without secrets
- CLEANUP: quic: Remaining fprintf() debug trace
- MINOR: quic: moving code for QUIC loss detection
- BUG/MINOR: quic: Missing time threshold multiplifier for loss delay computation
- CI: github actions: update LibreSSL to 3.5.2
- SCRIPTS: announce-release: add URL of dev packages
It seems this multiplier ended up in oblivion. Indeed a multiplier must be
applied to the loss delay expressed as an RTT multiplier: 9/8.
So, some packets were detected as lost too soon, leading to be retransmitted too
early!