]> git.ipfire.org Git - thirdparty/haproxy.git/log
thirdparty/haproxy.git
2 years agoBUG/MINOR: mux-h1: Report EOS on parsing/internal error for not running stream
Christopher Faulet [Fri, 16 Dec 2022 09:43:11 +0000 (10:43 +0100)] 
BUG/MINOR: mux-h1: Report EOS on parsing/internal error for not running stream

When an error occurred during the request parsing while the stream is not
running, an EOS must be reported. It is not an issue for an embryonic
connection because the H1 stream is orphan. However, it is an issue with
connections upgraded from TCP to H1. In this case, the upgrade is not
performed because there is an early error. However the H1 stream is not
orphan and is not destroyed. The H1 multiplexer will wait for the detach
event. But without EOS, the upper layer is unable to perform the shutdown.

This patch is related to #1966. It must be backported to 2.7. Older versions
are not affected by this issue.

2 years agoBUG/MEDIUM: tests: use tmpdir to create UNIX socket
Bertrand Jacquin [Sat, 17 Dec 2022 21:39:38 +0000 (21:39 +0000)] 
BUG/MEDIUM: tests: use tmpdir to create UNIX socket

testdir can be a very long directory since it depends on source
directory path, this can lead to failure during tests when UNIX socket
path exceeds maximum allowed length of 97 characters as defined in
str2sa_range().

  16:48:14 [ALERT] ***  h1    debug|    (10082) : config : parsing [/tmp/haregtests-2022-12-17_16-47-39.4RNzIN/vtc.4850.5d0d728a/h1/cfg:19] : 'bind' : socket path 'unix@/local/p4clients/pkgbuild-bB20r/workspace/build/HAProxy/HAProxy-2.7.x.68.0/AL2_x86_64/DEV.STD.PTHREAD/build/private/HAProxy-2.7.x/src/reg-tests/lua/srv3' too long (max 97)

Also, it is not advisable to create UNIX socket in actual source
directory, but instead use dedicated temporary directory create for test
purpose.

This should be backported to 2.6

2 years agoBUILD: peers: peers-t.h depends on stick-table-t.h
William Lallemand [Fri, 16 Dec 2022 14:40:31 +0000 (15:40 +0100)] 
BUILD: peers: peers-t.h depends on stick-table-t.h

peers-t.h uses "struct stktable" as well as STKTABLE_DATA_TYPES which
are defined in stick-table-t.h. It works by accident because
stick-table-t.h was always included before. But could provoke build
issue with EXTRA code.

To be backported as far as 2.2.

2 years agoREGTESTS: startup: disable automatic_maxconn.vtc
William Lallemand [Fri, 16 Dec 2022 07:24:04 +0000 (08:24 +0100)] 
REGTESTS: startup: disable automatic_maxconn.vtc

The test still need to have more start condition, like ulimit checks
and less strict value checks.

To be backported where it was activated (as far as 2.5)

2 years agoBUILD: 51d: fix build issue with recent compilers
Willy Tarreau [Thu, 15 Dec 2022 18:34:23 +0000 (19:34 +0100)] 
BUILD: 51d: fix build issue with recent compilers

With gcc-11.2 and binutils-2.37 I'm getting link errors due to multiply
defined symbols when enabling USE_51DEGREES_V4. This is caused by two
variables being present in hash.h instead of hash.c, hence they're
defined twice.

This patch just moves them to hash.c and turns their declaration to
extern.

No backport is needed since this was introduced in 2.8-dev.

2 years agoBUG/MINOR: quic: fix crash on PTO rearm if anti-amplification reset
Amaury Denoyelle [Wed, 14 Dec 2022 17:04:06 +0000 (18:04 +0100)] 
BUG/MINOR: quic: fix crash on PTO rearm if anti-amplification reset

There is a possible segfault when accessing qc->timer_task in
quic_conn_io_cb() without testing it. It seems however very rare as it
requires several condition to be encounter.
* quic_conn must be in CLOSING state after having sent a
  CONNECTION_CLOSE which free the qc.timer_task
* quic_conn handshake must still be in progress : in fact, qc.timer_task
  is accessed on this path because of the anti-amplification limit
  lifted.

I was unable thus far to trigger it but benchmarking tests seems to have
fire it with the following backtrace as a result :

  #0  _task_wakeup (f=4096, caller=0x5620ed004a40 <_.46868>, t=0x0) at include/haproxy/task.h:195
  195             state = _HA_ATOMIC_OR_FETCH(&t->state, f);
  [Current thread is 1 (Thread 0x7fc714ff1700 (LWP 14305))]
  (gdb) bt
  #0  _task_wakeup (f=4096, caller=0x5620ed004a40 <_.46868>, t=0x0) at include/haproxy/task.h:195
  #1  quic_conn_io_cb (t=0x7fc5d0e07060, context=0x7fc5d0df49c0, state=<optimized out>) at src/quic_conn.c:4393
  #2  0x00005620ecedab6e in run_tasks_from_lists (budgets=<optimized out>) at src/task.c:596
  #3  0x00005620ecedb63c in process_runnable_tasks () at src/task.c:861
  #4  0x00005620ecea971a in run_poll_loop () at src/haproxy.c:2913
  #5  0x00005620ecea9cf9 in run_thread_poll_loop (data=<optimized out>) at src/haproxy.c:3102
  #6  0x00007fc773c3f609 in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0
  #7  0x00007fc77372d133 in clone () from /lib/x86_64-linux-gnu/libc.so.6
  (gdb) up
  #1  quic_conn_io_cb (t=0x7fc5d0e07060, context=0x7fc5d0df49c0, state=<optimized out>) at src/quic_conn.c:4393
  4393                            task_wakeup(qc->timer_task, TASK_WOKEN_MSG);
  (gdb) p qc
  $1 = (struct quic_conn *) 0x7fc5d0df49c0
  (gdb) p qc->timer_task
  $2 = (struct task *) 0x0

This fix should be backported up to 2.6.

2 years agoMINOR: stats: make show info json future-proof
Aurelien DARRAGON [Thu, 15 Dec 2022 13:24:30 +0000 (14:24 +0100)] 
MINOR: stats: make show info json future-proof

This is a follow up of "BUG/MINOR: stats: fix show stat json buffer limitation"

However this time this is purely preemptive as we did not reach the buffer
limitation yet. But now is the proper time so that this won't be an issue
in the upcoming versions.

No backport needed.

2 years agoBUG/MINOR: stats: fix show stat json buffer limitation
Aurelien DARRAGON [Thu, 15 Dec 2022 13:17:09 +0000 (14:17 +0100)] 
BUG/MINOR: stats: fix show stat json buffer limitation

json output type is a lot more verbose than other output types.
Because of this and the increasing number of metrics implemented within
haproxy, we are starting to reach max bufsize limit (defaults to 16k)
when dumping stats to json since 2.6-dev1.
This results in stats output being truncated with
    "[{"errorStr":"output buffer too short"}]"

This was reported by Gabriel in #1964.

Thanks to "MINOR: stats: introduce stats field ctx", we can now make
multipart (using multiple buffers) dumping, in case a single buffer is not big
enough to hold the complete stat line.
For now, only stats_dump_fields_json() makes use of it as it is by
far the most verbose stats output type.
(csv, typed and html outputs should be good for a while and may use this
capability if the need arises in some distant future)

--

It could be backported to 2.6 and 2.7.
This commit depends on:
  - MINOR: stats: provide ctx for dumping functions
  - MINOR: stats: introduce stats field ctx

2 years agoMINOR: stats: introduce stats field ctx
Aurelien DARRAGON [Thu, 15 Dec 2022 13:01:04 +0000 (14:01 +0100)] 
MINOR: stats: introduce stats field ctx

Add a new value in stats ctx: field.
Implement field support in line dumping parent functions
stats_print_proxy_field_json() and stats_dump_proxy_to_buffer().

This will allow child dumping functions to support partial line dumping
when needed. ie: when dumping buffer is exhausted: do a partial send and
wait for a new buffer to finish the dump. Thanks to field ctx, the function
can start dumping where it left off on previous (unterminated) invokation.

2 years agoMINOR: stats: provide ctx for dumping functions
Aurelien DARRAGON [Thu, 15 Dec 2022 11:10:03 +0000 (12:10 +0100)] 
MINOR: stats: provide ctx for dumping functions

This is a minor refactor to allow stats_dump_info_* and stats_dump_fields_*
functions to directly access stat ctx pointer instead of explicitly
passing stat ctx struct members to them.

This will allow dumping functions to benefit from upcoming ctx updates.

2 years agoBUG/MINOR: ssl: Fix memory leak of find_chain in ssl_sock_load_cert_chain
Remi Tricot-Le Breton [Thu, 15 Dec 2022 14:44:37 +0000 (15:44 +0100)] 
BUG/MINOR: ssl: Fix memory leak of find_chain in ssl_sock_load_cert_chain

The certificate chain that gets passed in the SSL_CTX through
SSL_CTX_set1_chain has its reference counter increased by OpenSSL
itself. But since the ssl_sock_load_cert_chain function might create a
brand new certificate chain if none exists in the ckch_data
(sk_X509_new_null), then we ended up returning a new certificate chain
to the caller that was never destroyed.

This patch can be backported to all stable branches but it might need to
be reworked for branches older than 2.4 because of commit ec805a32b9
that refactorized the modified code.

2 years agoMINOR: ssl: Remove unnecessary alloc'ed trash chunk in show ocsp-response
Remi Tricot-Le Breton [Thu, 15 Dec 2022 14:44:36 +0000 (15:44 +0100)] 
MINOR: ssl: Remove unnecessary alloc'ed trash chunk in show ocsp-response

When displaying the content of an OCSP response in the CLI, a buffer is
alloc'ed when a temporary buffer would be enough.

2 years agoMINOR: ssl: Remove unneeded buffer allocation in show ocsp-response
Remi Tricot-Le Breton [Thu, 15 Dec 2022 14:44:35 +0000 (15:44 +0100)] 
MINOR: ssl: Remove unneeded buffer allocation in show ocsp-response

When calling 'show ssl ocsp-response' from the CLI, a temporary buffer
was created in parse_binary when we could just use a local static buffer
instead. This does not change the behavior of the function, it just
simplifies it.

2 years agoMINOR: h3: check return values of htx_add_* on headers parsing
Amaury Denoyelle [Thu, 15 Dec 2022 09:58:05 +0000 (10:58 +0100)] 
MINOR: h3: check return values of htx_add_* on headers parsing

Check return values of htx_add_header()/htx_add_eof() during H3 HEADERS
conversion to HTX. In case of error, the connection is interrupted with
a CONNECTION_CLOSE.

This commit is useful to detect abnormal situation on headers parsing.
It should be backported up to 2.7.

2 years agoBUG/MINOR: h3: fix memleak on HEADERS parsing failure
Amaury Denoyelle [Thu, 15 Dec 2022 09:53:55 +0000 (10:53 +0100)] 
BUG/MINOR: h3: fix memleak on HEADERS parsing failure

If an error is triggered on H3 HEADERS parsing, the allocated buffer for
HTX data is not freed.

To prevent this memleak, all return path have been centralized using
goto statements.

Also, as a small bonus, offer_buffers() is not called anymore if buffer
is not freed because sedesc has taken it. However this change has
probably no noticeable effect as dynamic buffers management is not
functional currently.

This should be backported up to 2.6.

2 years agoBUG/MEDIUM: h3: fix cookie header parsing
Amaury Denoyelle [Thu, 15 Dec 2022 08:18:25 +0000 (09:18 +0100)] 
BUG/MEDIUM: h3: fix cookie header parsing

Cookie header are treated specifically to merge multiple occurences in a
single HTX header. This is treated in a if-block condition inside the
'while (1)' loop for headers parsing. The length value of ist
representing cookie header is set to -1 by http_cookie_register(). The
problem is that then a continue statement is used but without
incrementing 'hdr_idx' to pass on the next header.

This issue was revealed by the introduction of commit :
  commit d6fb7a0e0f3a79afa1f4b6fc7b62053c3955dc4a
  BUG/MEDIUM: h3: reject request with invalid header name

Before the aformentionned patch, the bug was hidden : on the next while
iteration, all isteq() invocations won't match with cookie header length
now set to -1. htx_add_header() fails silently because length is
invalid. hdr_idx is finally incremented which allows parsing to proceed
normally with the next header.

Now, a cookie header with length -1 do not pass the test on header name
conformance introduced by the above patch. Thus, a spurrious
RESET_STREAM is emitted. This behavior has been reported on the mailing
list by Shawn Heisey who found out that browsers disabled H3 usage due
to the RESET_STREAM received. Big thanks to him for his testing on the
master branch.

This issue is simply resolved by incrementing hdr_idx before continue
statement. It could have been detected earlier if htx_add_header()
return value was checked. This will be the subject of a dedicated commit
outside of the backport scope.

This must be backported up to 2.6.

2 years agoMINOR: http-htx: add BUG_ON to prevent API error on http_cookie_register
Amaury Denoyelle [Thu, 15 Dec 2022 08:27:34 +0000 (09:27 +0100)] 
MINOR: http-htx: add BUG_ON to prevent API error on http_cookie_register

http_cookie_register() must be called on first invocation with the last
two arguments pointing both to a negative value. After it, they will be
updated to a valid index.

We must never have only the last argument as NULL as this will cause an
invalid array addressing. To clarify this a BUG_ON statement is
introduced.

This is linked to github issue #1967.

2 years agoBUG/MINOR: mux-h1: Fix test instead a BUG_ON() in h1_send_error()
Christopher Faulet [Thu, 15 Dec 2022 08:59:50 +0000 (09:59 +0100)] 
BUG/MINOR: mux-h1: Fix test instead a BUG_ON() in h1_send_error()

In the previous patch (86924532db "BUG/MINOR: mux-h1: Fix test instead a
BUG_ON() in h1_send_error()"), a BUG_ON() condition was inverted by error in
h1_send_error(). The stream-connector must be NULL to be able to destroy the H1
stream.

This patch must be backported with the commit above (to 2.7).

2 years agoBUG/MEDIUM: mux-h1: Don't release H1 stream upgraded from TCP on error
Christopher Faulet [Thu, 15 Dec 2022 08:22:35 +0000 (09:22 +0100)] 
BUG/MEDIUM: mux-h1: Don't release H1 stream upgraded from TCP on error

When an error occurred during the request parsing, the H1 multiplexer is
responsible to sent a response to the client and to release the H1 stream
and the H1 connection. In HTTP mode, it is not an issue because at this
stage the H1 connection is in embryonic state. Thus it can be released
immediately.

However, it is a problem if the connection was first upgraded from a TCP
connection. In this case, a stream-connector is attached. The H1 stream is
not orphan. Thus it must not be released at this stage. It must be detached
first. Otherwise a BUG_ON() is triggered in h1s_destroy().

So now, the H1S is destroyed on early errors but only if the H1C is in
embryonic state.

This patch may be related to #1966. It must be backported to 2.7.

2 years agoCI: github: split matrix for development and stable branches
Ilya Shipitsin [Wed, 14 Dec 2022 13:23:24 +0000 (18:23 +0500)] 
CI: github: split matrix for development and stable branches

ML ref: https://www.mail-archive.com/haproxy@formilux.org/msg42934.html

we agreed to use "latest" images for development branches and fixed
images for stable branches

Can be backported to 2.6.

2 years agoCI: github: remove redundant ASAN loop
Ilya Shipitsin [Wed, 14 Dec 2022 13:18:20 +0000 (18:18 +0500)] 
CI: github: remove redundant ASAN loop

it was there because we only ran ASAN for clang, now no need to separate loop

Can be backported to 2.6.

2 years agoBUG/MEDIUM: h3: parse content-length and reject invalid messages
Amaury Denoyelle [Thu, 8 Dec 2022 15:54:42 +0000 (16:54 +0100)] 
BUG/MEDIUM: h3: parse content-length and reject invalid messages

Ensure that if a request contains a content-length header it matches
with the total size of following DATA frames. This is conformance with
HTTP/3 RFC 9114.

For the moment, this kind of errors triggers a connection close. In the
future, it should be handled only with a stream reset. To reduce
backport surface, this will be implemented in another commit.

This must be backported up to 2.6. It relies on the previous commit :
  MINOR: http: extract content-length parsing from H2

2 years agoMINOR: http: extract content-length parsing from H2
Amaury Denoyelle [Thu, 8 Dec 2022 15:53:58 +0000 (16:53 +0100)] 
MINOR: http: extract content-length parsing from H2

Extract function h2_parse_cont_len_header() in the generic HTTP module.
This allows to reuse it for all HTTP/x parsers. The function is now
available as http_parse_cont_len_header().

Most notably, this will be reused in the next bugfix for the H3 parser.
This is necessary to check that content-length header match the length
of DATA frames.

Thus, it must be backported to 2.6.

2 years agoBUG/MEDIUM: h3: reject request with invalid pseudo header
Amaury Denoyelle [Wed, 7 Dec 2022 13:33:26 +0000 (14:33 +0100)] 
BUG/MEDIUM: h3: reject request with invalid pseudo header

RFC 9114 dictates several requirements for pseudo header usage in H3
request. Previously only minimal checks were implemented. Enforce all
the following requirements with this patch :
* reject request with undefined or invalid pseudo header
* reject request with duplicated pseudo header
* reject non-CONNECT request with missing mandatory pseudo header
* reject request with pseudo header after standard ones

For the moment, this kind of errors triggers a connection close. In the
future, it should be handled only with a stream reset. To reduce
backport surface, this will be implemented in another commit.

This must be backported up to 2.6.

2 years agoBUG/MEDIUM: h3: reject request with invalid header name
Amaury Denoyelle [Wed, 7 Dec 2022 13:31:42 +0000 (14:31 +0100)] 
BUG/MEDIUM: h3: reject request with invalid header name

Reject request containing invalid header name. This concerns every
header containing uppercase letter or a non HTTP token such as a space.

For the moment, this kind of errors triggers a connection close. In the
future, it should be handled only with a stream reset. To reduce
backport surface, this will be implemented in another commit.

Thanks to Yuki Mogi from FFRI Security, Inc. for having reported this.

This must be backported up to 2.6.

2 years agoREGTESTS: startup: add alternatives values in automatic_maxconn.vtc
William Lallemand [Wed, 14 Dec 2022 10:04:58 +0000 (11:04 +0100)] 
REGTESTS: startup: add alternatives values in automatic_maxconn.vtc

The calculated maxconn could produce other values when compiled with
debug options.

Must be backported where 6b6f082 was backported (as far as 2.5).

2 years agoBUG/MEDIUM: resolvers: Use tick_first() to update the resolvers task timeout
Christopher Faulet [Wed, 14 Dec 2022 09:26:25 +0000 (10:26 +0100)] 
BUG/MEDIUM: resolvers: Use tick_first() to update the resolvers task timeout

In resolv_update_resolvers_timeout(), the resolvers task timeout is updated
by checking running and waiting resolutions. However, to find the next
wakeup date, MIN() operator is used to compare ticks. Ticks must never be
compared with such operators, tick helper functions must be used, to
properly handled TICK_ETERNITY value. In this case, tick_first() must be
used instead of MIN().

It is an old bug but it is pretty visible since the commit fdecaf6ae4
("BUG/MINOR: resolvers: do not run the timeout task when there's no
resolution"). Because of this bug, the resolvers task timeout may be set to
TICK_ETERNITY, stopping periodic resolutions.

This patch should solve the issue #1962. It must be backported to all stable
versions.

2 years agoBUG/MEDIUM: freq-ctr: Don't compute overshoot value for empty counters
Christopher Faulet [Wed, 14 Dec 2022 09:38:01 +0000 (10:38 +0100)] 
BUG/MEDIUM: freq-ctr: Don't compute overshoot value for empty counters

The function computing the excess of events of a frequency counter over the
current period for a target frequency must handle empty counters (no event
and no start date). In this case, no excess must be reported.

Because of this bug, long pauses may be experienced on the bandwith
limitation filter.

This patch must be backported to 2.7.

2 years agoCLEANUP: ssl: remove check on srv->proxy
William Lallemand [Wed, 14 Dec 2022 09:34:36 +0000 (10:34 +0100)] 
CLEANUP: ssl: remove check on srv->proxy

Remove a useless check on srv->proxy which triggers coverity.

Should fix issue #1965.

2 years agoMINOR: sample: add param converter
Thayne McCombs [Wed, 14 Dec 2022 07:19:59 +0000 (00:19 -0700)] 
MINOR: sample: add param converter

Add a converter that extracts a parameter from string of delimited
key/value pairs.

Fixes: #1697
2 years agoREGTESTS: startup: activate automatic_maxconn.vtc
William Lallemand [Tue, 13 Dec 2022 17:44:35 +0000 (18:44 +0100)] 
REGTESTS: startup: activate automatic_maxconn.vtc

Check if USE_OBSOLETE_LINK=1 was used so it could run this test when
ASAN is not built, since ASAN require this option.

For this test to work, the ulimit -n value must be big enough.

Could be backported at least to 2.5.

2 years agoCI: github: set ulimit -n to a greater value
William Lallemand [Tue, 13 Dec 2022 23:03:13 +0000 (00:03 +0100)] 
CI: github: set ulimit -n to a greater value

Set ulimit -n to 65536 to limit less the maxconn computation.

Could be backported at least to 2.5.

2 years agoREGTESTS: startup: change the expected maxconn to 11000
William Lallemand [Tue, 13 Dec 2022 17:13:56 +0000 (18:13 +0100)] 
REGTESTS: startup: change the expected maxconn to 11000

change the expected maxconn from 10000 to 11000 in
automatic_maxconn.vtc

To be backported only if the test failed, the value might be the right
one in previous versions.

2 years agoBUG/MINOR: startup: don't use internal proxies to compute the maxconn
William Lallemand [Tue, 13 Dec 2022 17:17:44 +0000 (18:17 +0100)] 
BUG/MINOR: startup: don't use internal proxies to compute the maxconn

With internal proxies using the SSL activated (httpclient for example)
the automatic computation of the maxconn is wrong because these proxies
are always activated by default.

This patch fixes the issue by not counting these internal proxies during
the computation.

Must be backported as far as 2.5.

2 years agoREGTESTS: startup: check maxconn computation
William Lallemand [Tue, 13 Dec 2022 16:17:17 +0000 (17:17 +0100)] 
REGTESTS: startup: check maxconn computation

Check the maxconn computation with multiple -m parameters.

Broken with ASAN for now.

Could be backported as far as 2.2.

2 years agoCI: github: split ssl lib selection based on git branch
Ilya Shipitsin [Mon, 12 Dec 2022 14:15:22 +0000 (19:15 +0500)] 
CI: github: split ssl lib selection based on git branch

when *SSL_VERSION="latest" behaviour was introduced, it seems to be fine
for development branches, but too intrusive for stable branches.

let us limit "latest" semantic only for development builds, if branch name
contains "haproxy-" it is supposed to be stable branch, no latest openssl
should be taken

[wla: must be backported as far as 2.6]
Signed-off-by: William Lallemand <wlallemand@haproxy.org>
2 years agoBUG/MINOR: mux-quic: handle properly alloc error in qcs_new()
Amaury Denoyelle [Mon, 12 Dec 2022 08:59:50 +0000 (09:59 +0100)] 
BUG/MINOR: mux-quic: handle properly alloc error in qcs_new()

Use qcs_free() on allocation failure in qcs_new() This ensures that all
qcs content is properly deallocated and prevent memleaks. Most notably,
qcs instance is now removed from qcc tree.

This bug is labelled as MINOR as it occurs only on qcs allocation
failure due to memory exhaustion.

This must be backported up to 2.6.

2 years agoBUG/MINOR: mux-quic: remove qcs from opening-list on free
Amaury Denoyelle [Wed, 7 Dec 2022 10:26:16 +0000 (11:26 +0100)] 
BUG/MINOR: mux-quic: remove qcs from opening-list on free

qcs instances for bidirectional streams are inserted in
<qcc.opening_list>. It is removed from the list once a full HTTP request
has been parsed. This is required to implement http-request timeout.

If a qcs instance is freed before receiving a full HTTP request, it must
be removed from the <qcc.opening_list>. Else a segfault will occur in
qcc_refresh_timeout() when accessing a dangling pointer.

For the moment this bug was not reproduced in production. This is
because there exists only few rare cases where a qcs is freed before
HTTP request parsing. However, as error detection will be improved on
H3, this will occur more frequently in the near future.

This must be backported up to 2.6.

2 years agoCLEANUP: mux-quic: remove unused attribute on qcs_is_close_remote()
Amaury Denoyelle [Fri, 9 Dec 2022 15:26:03 +0000 (16:26 +0100)] 
CLEANUP: mux-quic: remove unused attribute on qcs_is_close_remote()

qcs_is_close_remote() is used in qcc_decode_qcs(). Thus the unused
function attribute is now unneeded.

This can be backported up to 2.7.

2 years agoBUG/MINOR: quic: handle alloc failure on qc_new_conn() for owned socket
Amaury Denoyelle [Mon, 12 Dec 2022 10:24:05 +0000 (11:24 +0100)] 
BUG/MINOR: quic: handle alloc failure on qc_new_conn() for owned socket

This patch is the follow up of previous fix :
  BUG/MINOR: quic: properly handle alloc failure in qc_new_conn()

quic_conn owned socket FD is initialized as soon as possible in
qc_new_conn(). This guarantees that we can safely call
quic_conn_release() on allocation failure. This function uses internally
qc_release_fd() to free the socket FD unless it has been initialized to
an invalid FD value.

Without this patch, a segfault will occur if one inner allocation of
qc_new_conn() fails before qc.fd is initialized.

This change is linked to quic-conn owned socket implementation.
This should be backported up to 2.7.

2 years agoBUG/MINOR: quic: properly handle alloc failure in qc_new_conn()
Amaury Denoyelle [Mon, 12 Dec 2022 10:22:42 +0000 (11:22 +0100)] 
BUG/MINOR: quic: properly handle alloc failure in qc_new_conn()

qc_new_conn() is used to allocate a quic_conn instance and its various
internal members. If one allocation fails, quic_conn_release() is used
to cleanup things.

For the moment, pool_zalloc() is used which ensures that all content is
null. However, some members must be initialized to a special values
to be able to use quic_conn_release() safely. This is the case for
quic_conn lists and its tasklet.

Also, some quic_conn internal allocation functions were doing their own
cleanup on failure without reset to NULL. This caused an issue with
quic_conn_release() which also frees this members. To fix this, these
functions now only return an error without cleanup. It is the caller
responsibility to free the allocated content, which is done via
quic_conn_release().

Without this patch, allocation failure in qc_new_conn() would often
result in segfault. This was reproduced easily using fail-alloc at 10%.

This should be backported up to 2.6.

2 years agoCI: github: reintroduce openssl 1.1.1
William Lallemand [Mon, 12 Dec 2022 07:52:03 +0000 (08:52 +0100)] 
CI: github: reintroduce openssl 1.1.1

OpenSSL 1.1.1 is not tested anymore since github updated "ubuntu-latest"
to 22.04, let's reintroduce this version.

2 years agoREGTESTS: fix the race conditions in iff.vtc
Christopher Faulet [Fri, 9 Dec 2022 16:11:22 +0000 (17:11 +0100)] 
REGTESTS: fix the race conditions in iff.vtc

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

2 years agoBUG/MAJOR: fcgi: Fix uninitialized reserved bytes
Youfu Zhang [Fri, 9 Dec 2022 11:15:48 +0000 (19:15 +0800)] 
BUG/MAJOR: fcgi: Fix uninitialized reserved bytes

The output buffer is not zero-initialized. If we don't clear reserved
bytes, fcgi requests sent to backend will leak sensitive data.

This patch must be backported as far as 2.2.

2 years agoDOC: promex: Add missing backend metrics
Christopher Faulet [Fri, 9 Dec 2022 10:04:11 +0000 (11:04 +0100)] 
DOC: promex: Add missing backend metrics

"haproxy_backend_agg_server_status" and "haproxy_backend_agg_check_status"
were not referenced in promex README.

"haproxy_backend_agg_server_check_status" is also missing but it is a
deprecated metric. Thus, it is better to not reference it.

2 years agoMINOR: promex: introduce haproxy_backend_agg_check_status
Cedric Paillet [Thu, 8 Dec 2022 09:17:01 +0000 (09:17 +0000)] 
MINOR: promex: introduce haproxy_backend_agg_check_status

This patch introduces haproxy_backend_agg_check_status metric
as we wanted in 42d7c402d but with the right data source.

This patch could be backported as far as 2.4.

2 years agoBUG/MINOR: promex: create haproxy_backend_agg_server_status
Cedric Paillet [Thu, 8 Dec 2022 09:17:00 +0000 (09:17 +0000)] 
BUG/MINOR: promex: create haproxy_backend_agg_server_status

haproxy_backend_agg_server_check_status currently aggregates
haproxy_server_status instead of haproxy_server_check_status.
We deprecate this and create a new one,
haproxy_backend_agg_server_status to clarify what it really
does.

This patch could be backported as far as 2.4.

2 years agoMINOR: pools: make DEBUG_UAF a runtime setting
Willy Tarreau [Thu, 8 Dec 2022 16:47:59 +0000 (17:47 +0100)] 
MINOR: pools: make DEBUG_UAF a runtime setting

Since the massive pools cleanup that happened in 2.6, the pools
architecture was made quite more hierarchical and many alternate code
blocks could be moved to runtime flags set by -dM. One of them had not
been converted by then, DEBUG_UAF. It's not much more difficult actually,
since it only acts on a pair of functions indirection on the slow path
(OS-level allocator) and a default setting for the cache activation.

This patch adds the "uaf" setting to the options permitted in -dM so
that it now becomes possible to set or unset UAF at boot time without
recompiling. This is particularly convenient, because every 3 months on
average, developers ask a user to recompile haproxy with DEBUG_UAF to
understand a bug. Now it will not be needed anymore, instead the user
will only have to disable pools and enable uaf using -dMuaf. Note that
-dMuaf only disables previously enabled pools, but it remains possible
to re-enable caching by specifying the cache after, like -dMuaf,cache.
A few tests with this mode show that it can be an interesting combination
which catches significantly less UAF but will do so with much less
overhead, so it might be compatible with some high-traffic deployments.

The change is very small and isolated. It could be helpful to backport
this at least to 2.7 once confirmed not to cause build issues on exotic
systems, and even to 2.6 a bit later as this has proven to be useful
over time, and could be even more if it did not require a rebuild. If
a backport is desired, the following patches are needed as well:

  CLEANUP: pools: move the write before free to the uaf-only function
  CLEANUP: pool: only include pool-os from pool.c not pool.h
  REORG: pool: move all the OS specific code to pool-os.h
  CLEANUP: pools: get rid of CONFIG_HAP_POOLS
  DEBUG: pool: show a few examples in -dMhelp

2 years agoDEBUG: pool: show a few examples in -dMhelp
Willy Tarreau [Thu, 8 Dec 2022 17:42:51 +0000 (18:42 +0100)] 
DEBUG: pool: show a few examples in -dMhelp

It's not always easy to remember what certain options do together nor
which ones are only relevant when combined with others, so let's add a
few examples with the "help" command on -dM.

2 years agoCLEANUP: pools: get rid of CONFIG_HAP_POOLS
Willy Tarreau [Thu, 8 Dec 2022 16:45:08 +0000 (17:45 +0100)] 
CLEANUP: pools: get rid of CONFIG_HAP_POOLS

This one was set in defaults.h only when neither DEBUG_NO_POOLS nor
DEBUG_UAF were set. This was not the most convenient location to look
for it, and it was only used in pool.c to decide on the initial value
of POOL_DBG_NO_CACHE.

Let's just use DEBUG_NO_POOLS || DEBUG_UAF directly on this flag and
get rid of the intermediary condition. This also has the benefit of
removing a double inversion, which is always nice for understanding.

2 years agoREORG: pool: move all the OS specific code to pool-os.h
Willy Tarreau [Thu, 8 Dec 2022 14:30:49 +0000 (15:30 +0100)] 
REORG: pool: move all the OS specific code to pool-os.h

Till now pool-os used to contain a mapping from pool_{alloc,free}_area()
to pool_{alloc,free}_area_uaf() in case of DEBUG_UAF, or the regular
malloc-based function. And the *_uaf() functions were in pool.c. But
since 2.4 with the first cleanup of the pools, there has been no more
calls to pool_{alloc,free}_area() from anywhere but pool.c, from exactly
one place each. As such, there's no more need to keep *_uaf() apart in
pool.c, we can inline it into pool-os.h and leave all the OS stuff there,
with pool.c calling either based on DEBUG_UAF. This is cleaner with less
round trips between both files and easier to find.

2 years agoCLEANUP: pool: only include pool-os from pool.c not pool.h
Willy Tarreau [Thu, 8 Dec 2022 16:26:50 +0000 (17:26 +0100)] 
CLEANUP: pool: only include pool-os from pool.c not pool.h

There's no need for the low-level pool functions to be known from all
callers anymore, they're only used by pool.c. Let's reduce the amount
of header files processed.

2 years agoCLEANUP: pools: move the write before free to the uaf-only function
Willy Tarreau [Thu, 8 Dec 2022 08:29:42 +0000 (09:29 +0100)] 
CLEANUP: pools: move the write before free to the uaf-only function

In UAF mode, pool_put_to_os() performs a write to the about-to-be-freed
memory area so as to make sure the page is properly mapped and catch a
possible double-free. However there's no point keeping that in an ifdef
in the generic function, because we now have a pool_free_area_uaf()
that is the UAF-specific version of pool_free_area() and the one that
is called immediately after this write. Let's move the code there, it
will be cleaner.

2 years agoBUG/MEDIUM: httpclient/lua: double LIST_DELETE on end of lua task
William Lallemand [Thu, 8 Dec 2022 10:11:36 +0000 (11:11 +0100)] 
BUG/MEDIUM: httpclient/lua: double LIST_DELETE on end of lua task

The lua httpclient cleanup can be called in 2 places, the
hlua_httpclient_gc() and the hlua_httpclient_destroy_all().

A LIST_DELETE() is performed to remove the hlua_hc struct of the list.
However, when the lua task ends and call hlua_ctx_destroy(), it does a
LIST_DELETE() first, and then the gc tries to do a LIST_DELETE() again
in hlua_httpclient_gc(), provoking a crash.

This patch fixes the issue by doing a LIST_DEL_INIT() instead of
LIST_DELETE() in both cases.

Should fix issue #1958.

Must be backported where bb58142 is backported.

2 years agoBUILD: makefile/da: also clean Os/ in Device Atlas dummy lib dir
Willy Tarreau [Thu, 8 Dec 2022 08:27:36 +0000 (09:27 +0100)] 
BUILD: makefile/da: also clean Os/ in Device Atlas dummy lib dir

Commit b81483cf2 ("MEDIUM: da: update doc and build for new scheduler
mode service.") added a new directory to the Device Atlas dummy lib,
but this one is not cleaned during "make clean", causing build failures
sometimes when switching between compiler versions during development.

This should be backported to 2.6.

2 years agoBUILD: atomic: atomic.h may need compiler.h on ARMv8.2-a
Willy Tarreau [Thu, 8 Dec 2022 07:32:57 +0000 (08:32 +0100)] 
BUILD: atomic: atomic.h may need compiler.h on ARMv8.2-a

We get a build error in ncbuf.c when building for ARMv8.2-a because ncbuf
has minimal includes and among them bug.h which includes atomic.h. Atomic.h
may use "forceinline" without including compiler.h, hence the build error.
It was verified that adding it doesn't inflate the total headers.

Since all other C files include api.h which already covers this, there's
no real need to bapkport this. The issue was already there in 2.3 though.

2 years agoCLEANUP: init: remove useless assignment of nbthread
Willy Tarreau [Thu, 8 Dec 2022 07:13:20 +0000 (08:13 +0100)] 
CLEANUP: init: remove useless assignment of nbthread

The old test consisting in setting global.nbthread if lower than 1
is useless nowadays since it's already done in check_config_validity().

2 years agoBUG/MINOR: init/threads: continue to limit default thread count to max per group
Willy Tarreau [Thu, 8 Dec 2022 07:04:46 +0000 (08:04 +0100)] 
BUG/MINOR: init/threads: continue to limit default thread count to max per group

Jakub Vojacek reported in issue #1955 that haproxy 2.7.0 doesn't start
anymore on a 128-CPU machine with a default config. The reason is the
raise of the default MAX_THREADS value that came with thread groups.
Previously, the maximum number of threads was simply limited to this
value, and all of them fit into one group. Now the limit being higher,
all threads cannot fit by default into a single group, and haproxy fails
to start.

The solution adopted here is to continue to limit the number of threads
to the max supported per group, but to multiply it by the number of groups
(usually 1 by default). In addition, a diag warning is now emitted when
this happens, reminding the user to set nbthread or adjust thread-groups.
We can hardly do more than a diag warning if we don't want to make the
upgrade painful for users.

Thanks to Jakub for reporting this early. This must be backported to 2.7.

2 years agoMINOR: peers: unused code path in process_peer_sync
Aurelien DARRAGON [Wed, 23 Nov 2022 17:32:26 +0000 (18:32 +0100)] 
MINOR: peers: unused code path in process_peer_sync

In process_peer_sync: a check was performed to know whether the peers section
handler should kill itself if the corresponding proxy was not started on the
current process.

This logic was initially implemented in early 1.6 development to prevent
some issues when peers where used in conjunction with nbproc > 1:
f83d3fe00a MEDIUM: init: stop any peers section not bound to the correct process
46dc1ca    MEDIUM: peers: unregister peers that were never started

But later in 1.6 dev, a new commit has been introduced:
47c8c029db MEDIUM: init: completely deallocate unused peers

With the latter, the check implemented in 46dc1ca ("MEDIUM: peers: unregister
peers that were never started") will never succeed: it is dead code.

Since nbproc support has been dropped in 2.5, things have changed a bit:

f83d3fe00a logic was moved in mworker_cleanlisteners, but as in 46dc1ca :
peers task is safely destroyed before peers_fe is set to NULL.
Conversely, peers_fe is first set by init_peers_frontend() before peers task
is scheduled by peers_init_sync() in check_config_validity().
Again, it is safe to say that we will never reach !peers->peers_fe
in process_peer_sync(): this self-killing mechanism is not relevant anymore.

--

To cut a long story short: I stumbled on this while tracking down
current signal api usage.

This led me to a signal_unregister_handler() call performed in the
aforementionned dead code. To me this code was potentially unsafe because
signal_unregister_handler() is not thread safe and here it was used within a
task initialized via task_new_anywhere(). So I decided to check how bad this
could be (ie: conditions to be met for this code to run).. and here we are.

2 years agoMINOR: mworker: remove unused legacy code in mworker_cleanlisteners
Aurelien DARRAGON [Wed, 23 Nov 2022 18:56:35 +0000 (19:56 +0100)] 
MINOR: mworker: remove unused legacy code in mworker_cleanlisteners

This cleanup is a follow up of "CLEANUP: peers: unused code path in
process_peer_sync"

There are some remnants of 1.6 peers specific code in mworker_cleanlisteners()
that was introduced with this patch serie:
f83d3fe00a MEDIUM: init: stop any peers section not bound to the correct process
47c8c029db MEDIUM: init: completely deallocate unused peers

Back then, nbthread did not exist, nbproc was used instead.
Updating some comments to make them more relevant to current haproxy design.
(multithreaded single process)

Moreover, in 47c8c029db, task_free() was performed on peers_fe->task.
But by looking at the code, from 1.6 til now, peers_fe->task
is never used for peers proxies, it is only used for main proxies (referenced
in proxies_list).
Removing this extra task cleanup because it is misleading.

2 years agoMINOR: stats: properly handle ST_F_CHECK_DURATION metric
Aurelien DARRAGON [Wed, 7 Dec 2022 13:52:10 +0000 (14:52 +0100)] 
MINOR: stats: properly handle ST_F_CHECK_DURATION metric

ST_F_CHECK_DURATION metric is typed as unsigned int variable, and it is
derived from check->duration that is signed.

While most of the time check->duration > 0, it is not always true:
with HCHK_STATUS_HANA checks, check->duration is set to -1 to prevent server
logs from including irrelevant duration info (HCHK_STATUS_HANA checks are not
time related).

Because of this, stats could report UINT64_MAX value for ST_F_CHECK_DURATION
metric. This was quite confusing. To prevent this, we make sure not to assign
negative value to ST_F_CHECK_DURATION.

This is only a minor printing issue, not backport needed.

2 years agoMINOR: check: use atomic for s->consecutive_errors
Aurelien DARRAGON [Wed, 7 Dec 2022 13:27:42 +0000 (14:27 +0100)] 
MINOR: check: use atomic for s->consecutive_errors

Properly use atomic operations when dealing with s->consecutive_errors as
we're using it out of server's lock.

Race is negligible, no backport needed.

2 years agoBUG/MINOR: checks: restore legacy on-error fastinter behavior
Aurelien DARRAGON [Wed, 7 Dec 2022 11:17:24 +0000 (12:17 +0100)] 
BUG/MINOR: checks: restore legacy on-error fastinter behavior

With previous commit, 9e080bf ("BUG/MINOR: checks: make sure fastinter is used
even on forced transitions"), on-error mark-down|sudden-death|fail-check are
now working as expected.

However, on-error fastinter remains broken because srv_getinter(), used in
the above commit to check the expiration date, won't return fastinter interval
if server health is maxed out (which is the case with on-error fastinter mode).

To fix this, we introduce a check flag named CHK_ST_FASTINTER.
This flag is set when on-error is triggered. This way we can force
srv_getinter() to return fastinter interval whenever the flag is set.
The flag is automatically cleared as soon as the new check task expiry is
recalculated in process_chk_conn().
This restores original behavior prior to d114f4a ("MEDIUM: checks: spread the
checks load over random threads").

It must be backported to 2.7 along with the aforementioned commits.

2 years agoBUG/MEDIUM: mworker: create the mcli_reload socketpairs in case of upgrade
William Lallemand [Wed, 7 Dec 2022 13:25:41 +0000 (14:25 +0100)] 
BUG/MEDIUM: mworker: create the mcli_reload socketpairs in case of upgrade

In ticket #1956, it was reported that an upgrade from 2.6 to 2.7 via a
reload would stop the master process.

When upgrading the binary, the new process is considered reexec and does
not try to creates the socketpair for the mcli_reload listener, then
tries to bind on -1 since the socket doesn't exit. The failure provokes
an exit() of the master.

This patch fixes the issue by trying to create the mcli_reload sockets
only when they don't exist, instead of creating them at first start.
This way we also avoid possible fd leak since we always try to use the
existing FDs first.

Must be backported in 2.7.

2 years agoBUG/MEDIUM: mworker: fix segv in early failure of mworker mode with peers
William Lallemand [Wed, 7 Dec 2022 14:21:24 +0000 (15:21 +0100)] 
BUG/MEDIUM: mworker: fix segv in early failure of mworker mode with peers

During an early failure of the mworker mode, the
mworker_cleanlisteners() function is called and tries to cleanup the
peers, however the peers are in a semi-initialized state and will use
NULL pointers.

The fix check the variable before trying to use them.

Bug revealed in issue #1956.

Could be backported as far as 2.0.

2 years agoMINOR: mworker: display an alert upon a wait-mode exit
William Lallemand [Wed, 7 Dec 2022 14:03:55 +0000 (15:03 +0100)] 
MINOR: mworker: display an alert upon a wait-mode exit

When the mworker wait mode fails it does an exit, but there is no
error message which says it exits.

Add a message which specify that the error is non-recoverable.

Could be backported in 2.7 and possibly earlier branch.

2 years agoCLEANUP: assorted typo fixes in the code and comments
Ilya Shipitsin [Wed, 7 Dec 2022 04:46:19 +0000 (09:46 +0500)] 
CLEANUP: assorted typo fixes in the code and comments

This is 34th iteration of typo fixes

2 years agoBUG/MINOR: checks: make sure fastinter is used even on forced transitions
Willy Tarreau [Tue, 6 Dec 2022 17:20:56 +0000 (18:20 +0100)] 
BUG/MINOR: checks: make sure fastinter is used even on forced transitions

Aurélien also found that while previous commit a56798ea4 ("BUG/MEDIUM:
checks: do not reschedule a possibly running task on state change")
addressed one specific case where the check's task had to be woken up
quickly, but it's not always sufficient as the check will not be
considered as expired regarding the fastinter yet.

Let's make sure we do consider this specific case to update the timer
based on the new state if the new value is shorter. This particularly
means that even if the timer is not expired yet during a wakeup when
nothing is in progress, we need to check if applying the currently
effective interval right now to the current date would expire earlier
than what is programmed, then the timer needs to be updated. I.e.
make sure we never miss fastinter during a state transition before
the end of the current period.

The approach is not pretty, but it forces to repass via the existing
block dedicated to updating the timer if the current one is expired
and the updated one would appear earlier.

This must be backported to 2.7 along with the commit above.

2 years agoBUG/MEDIUM: checks: do not reschedule a possibly running task on state change
Willy Tarreau [Tue, 6 Dec 2022 10:38:18 +0000 (11:38 +0100)] 
BUG/MEDIUM: checks: do not reschedule a possibly running task on state change

Aurélien found an issue introduced in 2.7-dev8 with commit d114f4a68
("MEDIUM: checks: spread the checks load over random threads"), but which
in fact has deeper roots.

When a server's state is changed via __health_adjust(), if a fastinter
setting is set, the task gets rescheduled to run at the new date. The
way it's done is not thread safe, as nothing prevents another thread
where the task is already running from also updating the expire field
in parallel. But since such events are quite rare, this statistically
never happens. However, with the commit above, the tasks are no longer
required to go to the shared wait queue and are no longer marked as
shared between multiple threads. It's just that *any* thread may run
them at a time without implying that all of them are allowed to modify
them. And this change is sufficient to trigger the BUG_ON() condition
in the scheduler that detects the inconsistency between a task queued
in one thread and being manipulated in parallel by another one:

  FATAL: bug condition "task->tid != tid" matched at
  include/haproxy/task.h:670
    call trace(13):
    | 0x55f61cf520c9 [c6 04 25 01 00 00 00 00]: main-0x2ee7
    | 0x55f61d0646e8 [8b 45 08 a8 40 0f 85 65]: back_handle_st_cer+0x78/0x4d7
    | 0x55f61cff3e72 [41 0f b6 4f 01 e9 c8 df]: process_stream+0x2252/0x364f
    | 0x55f61d0d2fab [48 89 c3 48 85 db 74 75]: run_tasks_from_lists+0x34b/0x8c4
    | 0x55f61d0d38ad [29 44 24 18 8b 54 24 18]: process_runnable_tasks+0x37d/0x6c6
    | 0x55f61d0a22fa [83 3d 0b 63 1e 00 01 0f]: run_poll_loop+0x13a/0x536
    | 0x55f61d0a28c9 [48 8b 1d f0 46 19 00 48]: main+0x14d919
    | 0x55f61cf56dfe [31 c0 e8 eb 93 1b 00 31]: main+0x1e4e/0x2d5d

At first glance it looked like it could be addressed in the scheduler
only, but in fact the problem clearly is at the application level, since
some shared fields are manipulated without protection. At minima, the
task's expiry ought to be touched only under the server's lock. While
it's arguable that the scheduler could make such updates easier, changing
it alone will not be sufficient here.

Looking at the sequencing closer, it becomes obvious that we do not need
this task_schedule() at all: a simple task_wakeup() is sufficient for the
callee to update its timers. Indeed, the process_chk_con() function already
deals with spurious wakeups, and already uses srv_getinter() to calculate
the next wakeup date based on the current state. So here, instead of
having to queue the task from __health_adjust() to anticipate a new check,
we can simply wake the task up and let it decide when it needs to run
next. This is much cleaner as the expiry calculation remains performed at
a single place, from the task itself, as it should be, and it fixes the
problem above.

This should be backported to 2.7, but not to older versions where the
risks of breakage are higher than the chance to fix something that
ever happened.

2 years agoMINOR: server/event_hdl: add support for SERVER_UP and SERVER_DOWN events
Aurelien DARRAGON [Fri, 25 Nov 2022 17:07:49 +0000 (18:07 +0100)] 
MINOR: server/event_hdl: add support for SERVER_UP and SERVER_DOWN events

We're using srv_update_status() as the only event source or UP/DOWN server
events in an attempt to simplify the support for these 2 events.

It seems srv_update_status() is the common path for server state changes anyway

Tested with server state updated from various sources:
  - the cli
  - server-state file (maybe we could disable this or at least don't publish
  in global event queue in the future if it ends in slower startup for setups
  relying on huge server state files)
  - dns records (ie: srv template)
  (again, could be fined tuned to only publish in server specific subscriber
  list and no longer in global subscription list if mass dns update tend to
  slow down srv_update_status())
  - normal checks and observe checks (HCHK_STATUS_HANA)
  (same as above, if checks related state update storms are expected)
  - lua scripts
  - html stats page (admin mode)

2 years agoMINOR: server/event_hdl: add support for SERVER_ADD and SERVER_DEL events
Aurelien DARRAGON [Thu, 17 Nov 2022 09:37:58 +0000 (10:37 +0100)] 
MINOR: server/event_hdl: add support for SERVER_ADD and SERVER_DEL events

Basic support for ADD and DEL server events are added through this commit:
SERVER_ADD is published on dynamic server addition through cli.
SERVER_DEL is published on dynamic server deletion through cli.

This work depends on:
"MINOR: event_hdl: add event handler base api"
"MINOR: server: add srv->rid (revision id) value"

2 years agoMINOR: stats: add server revision id support
Aurelien DARRAGON [Thu, 17 Nov 2022 15:34:07 +0000 (16:34 +0100)] 
MINOR: stats: add server revision id support

Make use of the new srv->rid value in stats.

Stat is referred as ST_F_SRID, it is now used in stats_fill_sv_stats
function in order to be included in csv and json stats dumps.

Moreover, "rid: $value" will be displayed next to server puid
in html stats page if "stats show-legend" is specified in the stats frontend.
(mouse hovering tooltip)

Depends on the following commit:
"MINOR: server: add srv->rid (revision id) value"

2 years agoMINOR: server: add srv->rid (revision id) value
Aurelien DARRAGON [Thu, 17 Nov 2022 15:10:35 +0000 (16:10 +0100)] 
MINOR: server: add srv->rid (revision id) value

With current design, we could not distinguish between
previously existing deleted server and a new server reusing
the deleted server name/id.

This can cause some confusion when auditing stats/events/logs,
because the new server will look similar to the old
one.

To address this, we're adding a new value in server structure: rid

rid (revision id) value is an unsigned 32bits value that is set upon
server creation. Value is derived from a global counter that starts
at 0 and is incremented each time one or multiple server deletions are
followed by a server addition (meaning that old name/id reuse could occur).

Thanks to this revision id, it is now easy to tell whether the server
we're looking at is the same as before or if it has been deleted and
re-added in the meantime.
(combining server name/id + server revision id yields a process-wide unique
identifier)

2 years agoBUG/MEDIIM: stconn: Flush output data before forwarding close to write side
Christopher Faulet [Mon, 5 Dec 2022 06:42:00 +0000 (07:42 +0100)] 
BUG/MEDIIM: stconn: Flush output data before forwarding close to write side

In process_stream(), we wait to have an empty output channel to forward a
close to the write side (a shutw). However, at the stream-connector level,
when a close is detected on one side and we don't want to keep half-close
connections, the shutw is unconditionally forwarded to the write side. This
typically happens on server side.

At first glance, this bug may truncate messages. But depending on the muxes
and the stream states, the bug may be more visible. On recent versions
(2.8-dev and 2.7) and on 2.2 and 2.0, the stream may be freezed, waiting for
the client timeout, if the client mux is unable to forward data because the
client is too slow _AND_ the response channel is not empty _AND_ the server
closes its connection _AND_ the server mux has forwarded all data to the
upper layer _AND_ the client decides to send some data and to close its
connection. On 2.6 and 2.4, it is worst. Instead of a freeze, the client mux
is woken up in loop.

Of course, conditions are pretty hard to meet. Especially because it is highly
time dependent. For what it's worth, I reproduce it with tcploop on client and
server sides and a basic HTTP configuration for HAProxy:

  * client: tcploop -v 8889 C S:"GET / HTTP/1.1\r\nConnection: upgrade\r\n\r\n" P5000 S:"1234567890" K
  * server: tcploop -v 8000 L A R S:"HTTP/1.1 101 ok\r\nConnection: upgrade\r\n\r\n" P2000 S2660000 F R

On 2.8-dev, without this patch, the stream is freezed and when the client
connection timed out, client data are truncated and '--cL' is reported in
logs. With the patch, the client data are forwarded to the server and the
connection is closed. A '--CD' is reported in logs.

It is an old bug. It was probably introduced with the multiplexers. To fix
it, in stconn (Formerly the stream-interface), we must wait all output data
be flushed before forwarding close to write side.

This patch must be backported as far as 2.2 and must be evaluated for 2.0.

2 years agoBUG/MINOR: quic: fix fd leak on startup check quic-conn owned socket
Amaury Denoyelle [Mon, 5 Dec 2022 09:24:54 +0000 (10:24 +0100)] 
BUG/MINOR: quic: fix fd leak on startup check quic-conn owned socket

A startup check is done for first QUIC listener to detect if quic-conn
owned socket is supported by the system. This is done by creating a
dummy socket reusing the listener address. This socket must be closed as
soon as the check is done.

The socket condition is invalid as it excludes zero which is a valid
file-descriptor value. Fix this bug by adjusting this condition.

In theory, this bug could prevent the usage of quic-conn owned socket as
startup check would report a false error. Also, the file-descriptor
would leak as it is not closed. In practice, this cannot happen when
startup check is done after a 'quic4/quic6' listener is instantiated as
file-descriptor are allocated in ascending order by the system.

This should fix github issue #1954.

quic-conn owned socket implementation is scheduled for backport on 2.7.
This commit must be backported with it, more specifically to fix the
following patch :
  75839a44e7e904bd1e332b58bd579e03b6d106f0
  MINOR: quic: startup detect for quic-conn owned socket support

2 years agoBUG/MINOR: ssl: initialize WolfSSL before parsing
William Lallemand [Fri, 2 Dec 2022 16:17:43 +0000 (17:17 +0100)] 
BUG/MINOR: ssl: initialize WolfSSL before parsing

The wolfSSL library need to be initialized before parsing the
configuration which uses some SSL functions.

To be backported in 2.6.

2 years agoBUG/MINOR: ssl: initialize SSL error before parsing
William Lallemand [Fri, 2 Dec 2022 16:06:59 +0000 (17:06 +0100)] 
BUG/MINOR: ssl: initialize SSL error before parsing

The SSL error initialization need to be done before the configuration
parsing, because it uses the SSL.

Need to be backported to 2.6.

2 years agoMINOR: quic: activate socket per conn by default
Amaury Denoyelle [Mon, 21 Nov 2022 10:54:13 +0000 (11:54 +0100)] 
MINOR: quic: activate socket per conn by default

Activate QUIC connection socket to achieve the best performance. The
previous behavior can be reverted by tune.quic.socket-owner
configuration option.

This change is part of quic-conn owned socket implementation.

Contrary to its siblings patches, I suggest to not backport it to 2.7.
This should ensure that stable releases behavior is perserved. If a user
faces issues with QUIC performance on 2.7, he can nonetheless change the
default configuration.

2 years agoMINOR: quic: reconnect quic-conn socket on address migration
Amaury Denoyelle [Thu, 1 Dec 2022 15:20:06 +0000 (16:20 +0100)] 
MINOR: quic: reconnect quic-conn socket on address migration

UDP addresses may change over time for a QUIC connection. When using
quic-conn owned socket, we have to detect address change to break the
bind/connect association on the socket.

For the moment, on change detected, QUIC connection socket is closed and
a new one is opened. In the future, we may improve this by trying to
keep the original socket and reexecute only bind/connect syscalls.

This change is part of quic-conn owned socket implementation.
It may be backported to 2.7 after a period of observation.

2 years agoMEDIUM: quic: requeue datagrams received on wrong socket
Amaury Denoyelle [Wed, 5 Oct 2022 15:56:08 +0000 (17:56 +0200)] 
MEDIUM: quic: requeue datagrams received on wrong socket

There is a small race condition when QUIC connection socket is
instantiated between the bind() and connect() system calls. This means
that the first datagram read on the sockets may belong to another
connection.

To detect this rare case, we compare the DCID for each QUIC datagram
read on the QUIC socket. If it does not match the connection CID, the
datagram is requeue using quic_receiver_buf to be able to handle it on
the correct thread.

This change is part of quic-conn owned socket implementation.
It may be backported to 2.7 after a period of observation.

2 years agoMINOR: mux-quic: rename duplicate function names
Amaury Denoyelle [Thu, 24 Nov 2022 09:51:19 +0000 (10:51 +0100)] 
MINOR: mux-quic: rename duplicate function names

qc_rcv_buf and qc_snd_buf are names used for static functions in both
quic-sock and quic-mux. To remove this ambiguity, slightly modify names
used in MUX code.

In the future, we should properly define a unique prefix for all QUIC
MUX functions to avoid such problem in the future.

This change is part of quic-conn owned socket implementation.
It may be backported to 2.7 after a period of observation.

2 years agoMEDIUM: quic: move receive out of FD handler to quic-conn io-cb
Amaury Denoyelle [Wed, 16 Nov 2022 10:01:02 +0000 (11:01 +0100)] 
MEDIUM: quic: move receive out of FD handler to quic-conn io-cb

This change is the second part for reception on QUIC connection socket.
All operations inside the FD handler has been delayed to quic-conn
tasklet via the new function qc_rcv_buf().

With this change, buffer management on reception has been simplified. It
is now possible to use a local buffer inside qc_rcv_buf() instead of
quic_receiver_buf().

This change is part of quic-conn owned socket implementation.
It may be backported to 2.7 after a period of observation.

2 years agoMEDIUM: quic: use quic-conn socket for reception
Amaury Denoyelle [Mon, 24 Oct 2022 15:40:37 +0000 (17:40 +0200)] 
MEDIUM: quic: use quic-conn socket for reception

Try to use the quic-conn socket for reception if it is allocated. For
this, the socket is inserted in the fdtab. This will call the new
handler quic_conn_io_cb() which is responsible to process the recv()
system call. It will reuse datagram dispatch for simplicity. However,
this is guaranteed to be called on the quic-conn thread, so it will be
more efficient to use a dedicated buffer. This will be implemented in
another commit.

This patch should improve performance by reducing contention on the
receiver socket. However, more gain can be obtained when the datagram
dispatch operation will be skipped.

Older quic_sock_fd_iocb() is renamed to quic_lstnr_sock_fd_iocb() to
emphasize its usage for the receiver socket.

This change is part of quic-conn owned socket implementation.
It may be backported to 2.7 after a period of observation.

2 years agoMINOR: quic: use connection socket for emission
Amaury Denoyelle [Mon, 21 Nov 2022 13:48:57 +0000 (14:48 +0100)] 
MINOR: quic: use connection socket for emission

If quic-conn has a dedicated socket, use it for sending over the
listener socket. This should improve performance by reducing contention
over the shared listener socket.

This change is part of quic-conn owned socket implementation.
It may be backported to 2.7 after a period of observation.

2 years agoMINOR: quic: allocate a socket per quic-conn
Amaury Denoyelle [Mon, 24 Oct 2022 15:08:43 +0000 (17:08 +0200)] 
MINOR: quic: allocate a socket per quic-conn

Allocate quic-conn owned socket if possible. This requires that this is
activated in haproxy configuration. Also, this is done only if local
address is known so it depends on the support of IP_PKTINFO.

For the moment this socket is not used. This causes QUIC support to be
broken as received datagram are not read. This commit will be completed
by a following patch to support recv operation on the newly allocated
socket.

This change is part of quic-conn owned socket implementation.
It may be backported to 2.7 after a period of observation.

2 years agoMINOR: quic: define config option for socket per conn
Amaury Denoyelle [Fri, 18 Nov 2022 16:42:16 +0000 (17:42 +0100)] 
MINOR: quic: define config option for socket per conn

Define global configuration option "tune.quic.socket-owner". This option
can be used to activate or not socket per QUIC connection mode. The
default value is "listener" which disable this feature. It can be
activated with the option "connection".

This change is part of quic-conn owned socket implementation.
It may be backported to 2.7 after a period of observation.

2 years agoMINOR: quic: test IP_PKTINFO support for quic-conn owned socket
Amaury Denoyelle [Thu, 1 Dec 2022 13:51:16 +0000 (14:51 +0100)] 
MINOR: quic: test IP_PKTINFO support for quic-conn owned socket

Extend the startup platform detection support test for quic-conn owned
socket. It is required to be able to retrieve destination address on a
recvfrom() system call so check if IP_PKTINFO or IP_RECVDSTADDR flags
are supported.

This change is part of quic-conn owned socket implementation.
It may be backported to 2.7 after a period of observation.

2 years agoMINOR: quic: startup detect for quic-conn owned socket support
Amaury Denoyelle [Mon, 21 Nov 2022 09:04:14 +0000 (10:04 +0100)] 
MINOR: quic: startup detect for quic-conn owned socket support

To be able to use individual sockets for QUIC connections, we rely on
the OS network stack which must support UDP sockets binding on the same
local address.

Add a detection code for this feature executed on startup. When the
first QUIC listener socket is binded, a test socket is created and
binded on the same address. If the bind call fails, we consider that
it's impossible to use individual socket for QUIC connections.

A new global option GTUNE_QUIC_SOCK_PER_CONN is defined. If startup
detect fails, this value is resetted from global options. For the
moment, there is no code to activate the option : this will be in a
follow-up patch with the introduction of a new configuration option.

This change is part of quic-conn owned socket implementation.
It may be backported to 2.7 after a period of observation.

2 years agoMINOR: quic: ignore address migration during handshake
Amaury Denoyelle [Mon, 21 Nov 2022 10:14:45 +0000 (11:14 +0100)] 
MINOR: quic: ignore address migration during handshake

QUIC protocol support address migration which allows to maintain the
connection even if client has changed its network address. This is done
through address migration.

RFC 9000 stipulates that address migration is forbidden before handshake
has been completed. Add a check for this : drop silently every datagram
if client network address has changed until handshake completion.

This commit is one of the first steps towards QUIC connection migration
support.

This should be backported up to 2.7.

2 years agoMINOR: quic: detect connection migration
Amaury Denoyelle [Fri, 2 Dec 2022 08:57:32 +0000 (09:57 +0100)] 
MINOR: quic: detect connection migration

Detect connection migration attempted by the client. This is done by
comparing addresses stored in quic-conn with src/dest addresses of the
UDP datagram.

A new function qc_handle_conn_migration() has been added. For the
moment, no operation is conducted and the function will be completed
during connection migration implementation. The only notable things is
the increment of a new counter "quic_conn_migration_done".

This should be backported up to 2.7.

2 years agoMINOR: tools: add port for ipcmp as optional criteria
Amaury Denoyelle [Thu, 1 Dec 2022 16:46:45 +0000 (17:46 +0100)] 
MINOR: tools: add port for ipcmp as optional criteria

Complete ipcmp() function with a new argument <check_port>. If this
argument is true, the function will compare port values besides IP
addresses and return true only if both are identical.

This commit will simplify QUIC connection migration detection. As such,
it should be backported to 2.7.

2 years agoMINOR: quic: extract datagram parsing code
Amaury Denoyelle [Tue, 27 Sep 2022 12:22:09 +0000 (14:22 +0200)] 
MINOR: quic: extract datagram parsing code

Extract individual datagram parsing code outside of datagrams list loop
in quic_lstnr_dghdlr(). This is moved in a new function named
quic_dgram_parse().

To complete this change, quic_lstnr_dghdlr() has been moved into
quic_sock source file : it belongs to QUIC socket lower layer and is
directly called by quic_sock_fd_iocb().

This commit will ease implementation of quic-conn owned socket.
New function quic_dgram_parse() will be easily usable after a receive
operation done on quic-conn IO-cb.

This should be backported up to 2.7.

2 years agoMINOR: quic: complete traces in qc_rx_pkt_handle()
Amaury Denoyelle [Thu, 24 Nov 2022 16:15:08 +0000 (17:15 +0100)] 
MINOR: quic: complete traces in qc_rx_pkt_handle()

Add missing ENTER trace for qc_rx_pkt_handle() function. LEAVE traces
are already present.

This should be backported up to 2.7.

2 years agoMINOR: quic: remove qc from quic_rx_packet
Amaury Denoyelle [Thu, 24 Nov 2022 16:12:25 +0000 (17:12 +0100)] 
MINOR: quic: remove qc from quic_rx_packet

quic_rx_packet struct had a reference to the quic_conn instance. This is
useless as qc instance is always passed through function argument. In
fact, pkt.qc is used only in qc_pkt_decrypt() on key update, even though
qc is also passed as argument.

Simplify this by removing qc field from quic_rx_packet structure
definition. Also clean up qc_pkt_decrypt() documentation and interface
to align it with other quic-conn related functions.

This should be backported up to 2.7.

2 years agoMEDIUM: ssl: rename the struct "cert_key_and_chain" to "ckch_data"
William Lallemand [Tue, 22 Nov 2022 10:51:53 +0000 (11:51 +0100)] 
MEDIUM: ssl: rename the struct "cert_key_and_chain" to "ckch_data"

Rename the structure "cert_key_and_chain" to "ckch_data" in order to
avoid confusion with the store whcih often called "ckchs".

The "cert_key_and_chain *ckch" were renamed "ckch_data *data", so we now
have store->data instead of ckchs->ckch.

Marked medium because it changes the API.

2 years agoDOC/MINOR: api: add documentation for event_hdl feature
Aurelien DARRAGON [Wed, 16 Nov 2022 17:06:34 +0000 (18:06 +0100)] 
DOC/MINOR: api: add documentation for event_hdl feature

This is an initial work for the dedicated
event handler API internal documentation.

The file is located at doc/internals/api/event_hdl.txt

event_hdl feature has been introduced with:
MINOR: event_hdl: add event handler base api

2 years agoMINOR: event_hdl: add event handler base api
Aurelien DARRAGON [Wed, 16 Nov 2022 17:06:28 +0000 (18:06 +0100)] 
MINOR: event_hdl: add event handler base api

Adding base code to provide subscribe/publish API for internal
events processing.

event_hdl provides two complementary APIs, both are implemented
in src/event_hdl.c and include/haproxy/event_hdl{-t.h,.h}:

One API targeting developers that want to register event handlers
that will be notified on specific events.
(SUBSCRIBE)

One API targeting developers that want to notify registered handlers
about an event.
(PUBLISH)

This feature is being considered to address the following scenarios:
- mailers code refactoring (getting rid of deprecated
tcp-check ruleset implementation)
- server events from lua code (registering user defined
lua function that is executed with relevant data when a
server is dynamically added/removed or on server state change)
- providing a stable and easy to use API for upcoming
developments that rely on specific events to perform actions.
(e.g: ressource cleanup when a server is deleted from haproxy)

At this time though, we don't have much use cases in mind in addition to
server events handling, but the API is aimed at being multipurpose
so that new event families, with their own particularities, can be
easily implemented afterwards (and hopefully) without requiring breaking
changes to the API.

Moreover, you should know that the API was not designed to cope well
with high rate event publishing.
Mostly because publishing means iterating over unsorted subscriber list.
So it won't scale well as subscriber list increases, but it is intended in
order to keep the code simple and versatile.

Instead, it is assumed that events implemented using this API
should be periodic events, and that events related to critical
io/networking processing should be handled using
dedicated facilities anyway.
(After all, this is meant to be a general purpose event API)

Apart from being easily extensible, one of the main goals of this API is
to make subscriber code as simple and safe as possible.

This is done by offering multiple event handling modes:
- SYNC mode:
publishing code directly
leverages handler code (callback function)
and handler code has a direct access to "live" event data
(pointers mostly, alongside with lock hints/context
so that accessing data pointers can be done properly)
- normal ASYNC mode:
handler is executed in a backward compatible way with sync mode,
so that it is easy to switch from and to SYNC/ASYNC mode.
Only here the handler has access to "offline" event data, and
not "live" data (ptrs) so that data consistency is guaranteed.
By offline, you should understand "snapshot" of relevant data
at the time of the event, so that the handler can consume it
later (even if associated ressource is not valid anymore)
- advanced ASYNC mode
same as normal ASYNC mode, but here handler is not a function
that is executed with event data passed as argument: handler is a
user defined tasklet that is notified when event occurs.
The tasklet may consume pending events and associated data
through its own message queue.

ASYNC mode should be considered first if you don't rely on live event
data and you wan't to make sure that your code has the lowest impact
possible on publisher code. (ie: you don't want to break stuff)

Internal API documentation will follow:
You will find more details about the notions we roughly approached here.

2 years agoLICENSE: wurfl: clarify the dummy library license.
scientiamobile [Thu, 1 Dec 2022 16:21:10 +0000 (17:21 +0100)] 
LICENSE: wurfl: clarify the dummy library license.

This clarifies that LGPL is also permitted for the wurfl.h dummy file.
Should be backported where relevant.

Signed-off-by: Luca Passani <luca.passani@scientiamobile.com>
2 years agoMINOR: debug: add a balance of alloc - free at the end of the memstats dump
Willy Tarreau [Wed, 30 Nov 2022 16:16:51 +0000 (17:16 +0100)] 
MINOR: debug: add a balance of alloc - free at the end of the memstats dump

When digging into suspected memory leaks, it's cumbersome to count the
number of allocations and free calls. Here we're adding a summary at the
end of the sum of allocs minus the sum of frees, excluding realloc since
we can't know how much it releases upon each call. This means that when
doing many realloc+free the count may be negative but in practice there
are very few reallocs so that's not a problem. Also the size/call is signed
and corresponds to the average size allocated (e.g. leaked) per call.

It seems to work reasonably well for now:

  > debug dev memstats match buf
  quic_conn.c:2978       P_FREE  size:   1239547904  calls:     75656  size/call:  16384 buffer
  quic_conn.c:2960      P_ALLOC  size:   1239547904  calls:     75656  size/call:  16384 buffer
  mux_quic.c:393        P_ALLOC  size:   9112780800  calls:    556200  size/call:  16384 buffer
  mux_quic.c:383        P_ALLOC  size:  17783193600  calls:   1085400  size/call:  16384 buffer
  mux_quic.c:159         P_FREE  size:   8935833600  calls:    545400  size/call:  16384 buffer
  mux_quic.c:142         P_FREE  size:   9112780800  calls:    556200  size/call:  16384 buffer
  h3.c:776              P_ALLOC  size:   8935833600  calls:    545400  size/call:  16384 buffer
  quic_stream.c:166      P_FREE  size:    975241216  calls:     59524  size/call:  16384 buffer
  quic_stream.c:127      P_FREE  size:   7960592384  calls:    485876  size/call:  16384 buffer
  stream.c:772           P_FREE  size:      8798208  calls:       537  size/call:  16384 buffer
  stream.c:768           P_FREE  size:      2424832  calls:       148  size/call:  16384 buffer
  stream.c:751          P_ALLOC  size:   8852062208  calls:    540287  size/call:  16384 buffer
  stream.c:641           P_FREE  size:   8849162240  calls:    540110  size/call:  16384 buffer
  stream.c:640           P_FREE  size:   8847360000  calls:    540000  size/call:  16384 buffer
  channel.h:850         P_ALLOC  size:      2441216  calls:       149  size/call:  16384 buffer
  channel.h:850         P_ALLOC  size:      5914624  calls:       361  size/call:  16384 buffer
  dynbuf.c:55            P_FREE  size:        32768  calls:         2  size/call:  16384 buffer
  Total                 BALANCE  size:            0  calls:   5606906  size/call:      0 (excl. realloc)

Let's see how useful this becomes over time.

2 years agoMINOR: debug: support pool filtering on "debug dev memstats"
Willy Tarreau [Wed, 30 Nov 2022 15:42:54 +0000 (16:42 +0100)] 
MINOR: debug: support pool filtering on "debug dev memstats"

Sometimes when debugging it's convenient to be able to focus only on
certain pools. Just like we did for "show pools", let's add a filter
based on a prefix on "debug dev memstats match <prefix>".