]> git.ipfire.org Git - thirdparty/haproxy.git/log
thirdparty/haproxy.git
2 years agoMINOR: hlua_fcn/mailers: handle timeout mail from mailers section
Aurelien DARRAGON [Fri, 7 Jul 2023 14:55:43 +0000 (16:55 +0200)] 
MINOR: hlua_fcn/mailers: handle timeout mail from mailers section

As the example/lua/mailers.lua script does its best to mimic the c-mailer
implementation, it should support the "timeout mail" directive as well.

This could be backported in 2.8.

2 years agoBUG/MINOR: server: set rid default value in new_server()
Aurelien DARRAGON [Fri, 7 Jul 2023 13:19:36 +0000 (15:19 +0200)] 
BUG/MINOR: server: set rid default value in new_server()

srv->rid default value is set in _srv_parse_init() after the server is
succesfully allocated using new_server().

This is wrong because new_server() can be used independently so rid value
assignment would be skipped in this case.

Hopefully new_server() allocates server data using calloc() so srv->rid
is already set to 0 in practise. But if calloc() is replaced by malloc()
or other memory allocating function that doesn't zero-initialize srv
members, this could lead to rid being uninitialized in some cases.

This should be backported in 2.8 with 61e3894dfe ("MINOR: server: add
srv->rid (revision id) value")

2 years agoBUG/MINOR: sink: fix errors handling in cfg_post_parse_ring()
Aurelien DARRAGON [Mon, 10 Jul 2023 14:26:08 +0000 (16:26 +0200)] 
BUG/MINOR: sink: fix errors handling in cfg_post_parse_ring()

Multiple error paths (memory,IO related) in cfg_post_parse_ring() were
not implemented correcly and could result in memory leak or undefined
behavior.

Fixing them all at once.

This can be backported in 2.4

2 years agoBUG/MINOR: sink: invalid sft free in sink_deinit()
Aurelien DARRAGON [Mon, 10 Jul 2023 13:17:12 +0000 (15:17 +0200)] 
BUG/MINOR: sink: invalid sft free in sink_deinit()

sft freeing attempt made in a575421 ("BUG/MINOR: sink: missing sft free in
sink_deinit()") is incomplete, because sink->sft is meant to be used as a
list and not a single sft entry.

Because of that, the previous fix only frees the first sft entry, which
fixes memory leaks for single-server forwarders (this is the case for
implicit rings), but could still result in memory leaks when multiple
servers are configured in a explicit ring sections.

What this patch does: instead of directly freeing sink->sft, it iterates
over every list members to free them.

It must be backported up to 2.4 with a575421.

2 years agoBUG/MINOR: log: free errmsg on error in cfg_parse_log_forward()
Aurelien DARRAGON [Tue, 4 Jul 2023 13:36:45 +0000 (15:36 +0200)] 
BUG/MINOR: log: free errmsg on error in cfg_parse_log_forward()

When leaving cfg_parse_log_forward() on error paths, errmsg which is local
to the function could still point to valid data, and it's our
responsibility to free it.

Instead of freeing it everywhere it is invoved, we free it prior to
leaving the function.

This should be backported as far as 2.4.

2 years agoBUG/MINOR: log: fix multiple error paths in cfg_parse_log_forward()
Aurelien DARRAGON [Mon, 3 Jul 2023 16:33:18 +0000 (18:33 +0200)] 
BUG/MINOR: log: fix multiple error paths in cfg_parse_log_forward()

Multiple error paths were badly handled in cfg_parse_log_forward():
some errors were raised without interrupting the function execution,
resulting in undefined behavior.

Instead of fixing issues separately, let's fix the whole function at once.
This should be backported as far as 2.4.

2 years agoBUG/MINOR: log: fix missing name error message in cfg_parse_log_forward()
Aurelien DARRAGON [Mon, 3 Jul 2023 15:35:54 +0000 (17:35 +0200)] 
BUG/MINOR: log: fix missing name error message in cfg_parse_log_forward()

"missing name for ip-forward section" is generated instead of "missing
name name for log-forward section" in cfg_parse_log_forward().

This may be backported up to 2.4.

2 years agoBUG/MEDIUM: log: improper use of logsrv->maxlen for buffer targets
Aurelien DARRAGON [Mon, 26 Jun 2023 15:15:48 +0000 (17:15 +0200)] 
BUG/MEDIUM: log: improper use of logsrv->maxlen for buffer targets

In e709e1e ("MEDIUM: logs: buffer targets now rely on new sink_write")
we started using the sink API instead of using the ring_write function
directly.

But as indicated in the commit message, the maxlen parameter of the log
directive now only applies to the message part and not the complete
payload. I don't know what the original intent was (maybe minimizing code
changes) but it seems wrong, because the doc doesn't mention this special
case, and the result is that the ring->buffer output can differ from all
other log output types, making it very confusing.

One last issue with this is that log messages can end up being dropped at
runtime, only for the buffer target, and even if logsrv->maxlen is
correctly set (including default: 1024) because depending on the generated
header size the payload can grow bigger than the accepted sink size (sink
maxlen is not mandatory) and we have no simple way to detect this at
configuration time.

First, we partially revert e709e1e:

  TARGET_BUFFER still leverages the proper sink API, but thanks to
  "MINOR: sink: pass explicit maxlen parameter to sink_write()" we now
  explicitly pass the logsrv->maxlen to the sink_write function in order
  to stop writing as soon as either sink->maxlen or logsrv->maxlen is
  reached.

This restores pre-e709e1e behavior with the added benefit from using the
high-level API, which includes automatically announcing dropped message
events.

Then, we also need to take the ending '\n' into account: it is not
explicitly set when generating the logline for TARGET_BUFFER, but it will
be forcefully added by the sink_forward_io_handler function from the tcp
handler applet when log messages from the buffer are forwarded to tcp
endpoints.

In current form, because the '\n' is added later in the chain, maxlen is
not being considered anymore, so the final log message could exceed maxlen
by 1 byte, which could make receiving servers unhappy in logging context.

To prevent this, we sacrifice 1 byte from the logsrv->maxlen to ensure
that the final message will never exceed log->maxlen, even if the '\n'
char is automatically appended later by the forwarding applet.

Thanks to this change TCP (over RING/BUFFER) target now behaves like
FD and UDP targets.

This commit depends on:
 - "MINOR: sink: pass explicit maxlen parameter to sink_write()"

It may be backported as far as 2.2

[For 2.2 and 2.4 the patch does not apply automatically, the sink_write()
call must be updated by hand]

2 years agoMINOR: sink/api: pass explicit maxlen parameter to sink_write()
Aurelien DARRAGON [Mon, 26 Jun 2023 14:44:41 +0000 (16:44 +0200)] 
MINOR: sink/api: pass explicit maxlen parameter to sink_write()

sink_write() currently relies on sink->maxlen to know when to stop
writing a given payload.

But it could be useful to pass a smaller, explicit value to sink_write()
to stop before the ring maxlen, for instance if the ring is shared between
multiple feeders.

sink_write() now takes an optional maxlen parameter:
  if maxlen is > 0, then sink_write will stop writing at maxlen if maxlen
  is smaller than ring->maxlen, else only ring->maxlen will be considered.

[for haproxy <= 2.7, patch must be applied by hand: that is:
__sink_write() and sink_write() should be patched to take maxlen into
account and function calls to sink_write() should use 0 as second argument
to keep original behavior]

2 years agoBUG/MINOR: log: LF upsets maxlen for UDP targets
Aurelien DARRAGON [Tue, 27 Jun 2023 09:32:06 +0000 (11:32 +0200)] 
BUG/MINOR: log: LF upsets maxlen for UDP targets

A regression was introduced with 5464885 ("MEDIUM: log/sink: re-work
and merge of build message API.").

For UDP targets, a final '\n' is systematically inserted, but with the
rework of the build message API, it is inserted after the maxlen
limitation has been enforced, so this can lead to the final message
becoming maxlen+1. For strict syslog servers that only accept up to
maxlen characters, this could be a problem.

To fix the regression, we take the final '\n' into account prior to
building the message, like it was done before the rework of the API.

This should be backported up to 2.4.

2 years agoBUG/MINOR: ring: maxlen warning reported as alert
Aurelien DARRAGON [Mon, 26 Jun 2023 12:22:12 +0000 (14:22 +0200)] 
BUG/MINOR: ring: maxlen warning reported as alert

When maxlen parameter exceeds sink size, a warning is generated and maxlen
is enforced to sink size. But the err_code is incorrectly set to ERR_ALERT

Indeed, being a "warning", ERR_WARN should be used here.

This may be backported as far as 2.2

2 years agoBUG/MINOR: ring: size warning incorrectly reported as fatal error
Aurelien DARRAGON [Thu, 22 Jun 2023 14:57:29 +0000 (16:57 +0200)] 
BUG/MINOR: ring: size warning incorrectly reported as fatal error

When a ring section defines its size using the "size" directive with a
smaller size than the default one or smaller than the previous one,
a warning is generated to inform the user that the new size will be
ignored.

However the err_code is returned as FATAL, so this cause haproxy to
incorrectly abort the init sequence.

Changing the err_code to ERR_WARN so that this warning doesn't refrain
from successfully starting the process.

This should be backported as far as 2.4

2 years agoBUG/MINOR: sink: missing sft free in sink_deinit()
Aurelien DARRAGON [Thu, 6 Jul 2023 13:19:34 +0000 (15:19 +0200)] 
BUG/MINOR: sink: missing sft free in sink_deinit()

Adding missing free for sft (string_forward_target) in sink_deinit(),
which resulted in minor leak for each declared ring target at deinit().
(either explicit and implicit rings are affected)

This may be backported up to 2.4.

2 years agoBUG/MINOR: http_ext: unhandled ERR_ABORT in proxy_http_parse_7239()
Aurelien DARRAGON [Tue, 4 Jul 2023 08:33:33 +0000 (10:33 +0200)] 
BUG/MINOR: http_ext: unhandled ERR_ABORT in proxy_http_parse_7239()

_proxy_http_parse_7239_expr() helper used in proxy_http_parse_7239()
function may return ERR_ABORT in case of memory error. But the error check
used below is insufficient to catch ERR_ABORT so the function could keep
executing prior to returning ERR_ABORT, which may cause undefined
behavior. Hopefully no sensitive handling is performed in this case so
this bug has very limited impact, but let's fix it anyway.

We now use ERR_CODE mask instead of ERR_FATAL to check if err_code is set
to any kind of error combination that should prevent the function from
further executing.

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

2 years agoBUG/MEDIUM: sink: invalid server list in sink_new_from_logsrv()
Aurelien DARRAGON [Thu, 6 Jul 2023 12:57:32 +0000 (14:57 +0200)] 
BUG/MEDIUM: sink: invalid server list in sink_new_from_logsrv()

forward proxy server list created from sink_new_from_logsrv() is invalid

Indeed, srv->next is literally assigned to itself. This did not cause
issues during syslog handling because the sft was properly set, but it
will cause the free_proxy(sink->forward_px) at deinit to go wild since
free_proxy() will try to iterate through the proxy srv list to free
ressources, but because of the improper list initialization, double-free
and infinite-loop will occur.

This bug was revealed by 9b1d15f53a ("BUG/MINOR: sink: free forward_px on deinit()")

It must be backported as far as 2.4.

2 years agoBUG/MINOR: cache: A 'max-age=0' cache-control directive can be overriden by a s-maxage
Remi Tricot-Le Breton [Tue, 4 Jul 2023 15:13:28 +0000 (17:13 +0200)] 
BUG/MINOR: cache: A 'max-age=0' cache-control directive can be overriden by a s-maxage

When a s-maxage cache-control directive is present, it overrides any
other max-age or expires value (see section 5.2.2.9 of RFC7234). So if
we have a max-age=0 alongside a strictly positive s-maxage, the response
should be cached.

This bug was raised in GitHub issue #2203.
The fix can be backported to all stable branches.

2 years agoBUG/MINOR: quic: Possible crash in "show quic" dumping packet number spaces
Frédéric Lécaille [Mon, 3 Jul 2023 15:16:31 +0000 (17:16 +0200)] 
BUG/MINOR: quic: Possible crash in "show quic" dumping packet number spaces

This bug was introduced by this commit:

    MEDIUM: quic: Release encryption levels and packet number spaces asap

Add some checks before derefencing pointers to packet number spaces objects
to dump them from "show quic" command.

No backport needed.

2 years agoMEDIUM: sample: introduce 'same' output type
Aurelien DARRAGON [Tue, 30 May 2023 14:34:39 +0000 (16:34 +0200)] 
MEDIUM: sample: introduce 'same' output type

Thierry Fournier reported an annoying side-effect when using the debug()
converter.

Consider the following examples:

[1]  http-request set-var(txn.test) bool(true),ipmask(24)
[2]  http-request redirect location /match if { bool(true),ipmask(32) }

When starting haproxy with [1] example we get:

   config : parsing [test.conf:XX] : error detected in frontend 'fe' while parsing 'http-request set-var(txn.test)' rule : converter 'ipmask' cannot be applied.

With [2], we get:

  config : parsing [test.conf:XX] : error detected in frontend 'fe' while parsing 'http-request redirect' rule : error in condition: converter 'ipmask' cannot be applied in ACL expression 'bool(true),ipmask(32)'.

Now consider the following examples which are based on [1] and [2]
but with the debug() sample conv inserted in-between those incompatible
sample types:

[1*] http-request set-var(txn.test) bool(true),debug,ipmask(24)
[2*] http-request redirect location /match if { bool(true),debug,ipmask(32) }

According to the documentation, "it is safe to insert the debug converter
anywhere in a chain, even with non-printable sample types".
Thus we don't expect any side-effect from using it within a chain.

However in current implementation, because of debug() returning SMP_T_ANY
type which is a pseudo type (only resolved at runtime), the sample
compatibility checks performed at parsing time are completely uneffective.
(haproxy will start and no warning will be emitted)

The indesirable effect of this is that debug() prevents haproxy from
warning you about impossible type conversions, hiding potential errors
in the configuration that could result to unexpected evaluation or logic
while serving live traffic. We better let haproxy warn you about this kind
of errors when it has the chance.

With our previous examples, this could cause some inconveniences. Let's
say for example that you are testing a configuration prior to deploying
it. When testing the config you might want to use debug() converter from
time to time to check how the conversion chain behaves.

Now after deploying the exact same conf, you might want to remove those
testing debug() statements since they are no longer relevant.. but
removing them could "break" the config and suddenly prevent haproxy from
starting upon reload/restart. (this is the expected behavior, but it
comes a bit too late because of debug() hiding errors during tests..)

To fix this, we introduce a new output type for sample expressions:
  SMP_T_SAME - may only be used as "expected" out_type (parsing time)
               for sample converters.

As it name implies, it is a way for the developpers to indicate that the
resulting converter's output type is guaranteed to match the type of the
sample that is presented on the converter's input side.
(converter may alter data content, but data type must not be changed)

What it does is that it tells haproxy that if switching to the converter
(by looking at the converter's input only, since outype is SAME) is
conversion-free, then the converter type can safely be ignored for type
compatibility checks within the chain.

debug()'s out_type is thus set to SMP_T_SAME instead of ANY, which allows
it to fully comply with the doc in the sense that it does not impact the
conversion chain when inserted between sample items.

Co-authored-by: Thierry Fournier <thierry.f.78@gmail.com>
2 years agoMEDIUM: tree-wide: fetches that may return IPV4+IPV6 now return ADDR
Aurelien DARRAGON [Wed, 7 Jun 2023 13:55:13 +0000 (15:55 +0200)] 
MEDIUM: tree-wide: fetches that may return IPV4+IPV6 now return ADDR

Historically, the ADDR pseudo-type did not exist. So when IPV6 support
was added to existing IPV4 sample fetches (e.g.: src,dst,hdr_ip...) the
expected out_type in related sample definitions was left on IPV4 because
it was required to declare the out_type as the lowest common denominator
(the type that can be casted into all other ones) to make compatibility
checks at parse time work properly.

However, now that ADDR pseudo-type may safely be used as out_type since
("MEDIUM: sample: add missing ADDR=>? compatibility matrix entries"), we
can use ADDR for fetches that may output both IPV4 and IPV6 at runtime.

One added benefit on top of making the code less confusing is that
'haproxy -dKsmp' output will now show "addr" instead of "ipv4" for such
fetches, so the 'haproxy -dKsmp' output better complies with the fetches
signatures from the documentation.

out_ip fetch, which returns an ip according to the doc, was purposely
left as is (returning IPV4) since the smp_fetch_url_ip() implementation
forces output type to IPV4 anyway, and since this is an historical fetch
I prefer not to touch it to prevent any regression. However if
smp_fetch_url_ip() were to be fixed to also return IPV6 in the future,
then its expected out_type may be changed to ADDR as well.

Multiple notes in the code were updated to mention that the appropriate
pseudo-type may be used instead of the lowest common denominator for
out_type when available.

2 years agoMINOR: sample: fix ipmask sample definition
Aurelien DARRAGON [Fri, 26 May 2023 15:07:40 +0000 (17:07 +0200)] 
MINOR: sample: fix ipmask sample definition

Since 1478aa7 ("MEDIUM: sample: Add IPv6 support to the ipmask converter")
ipmask converter may return IPV6 as well, so the sample definition must
be updated. (the output type is currently explicited to IPV4)

This has no functional impact: one visible effect will be that
converter's visible output type will change from "ipv4" to "addr" when
using 'haproxy -dKcnv'.

2 years agoMEDIUM: sample: add missing ADDR=>? compatibility matrix entries
Aurelien DARRAGON [Tue, 6 Jun 2023 13:58:49 +0000 (15:58 +0200)] 
MEDIUM: sample: add missing ADDR=>? compatibility matrix entries

SMP_T_ADDR support was added in b805f71 ("MEDIUM: sample: let the cast
functions set their output type").

According to the above commit, it is made clear that the ADDR type is
a pseudo/generic type that may be used for compatibility checks but
that cannot be emitted from a fetch or converter.

With that in mind, all conversions from ADDR to other types were
explicitly disabled in the compatibility matrix.

But later, when map_*_ip functions were updated in b2f8f08 ("MINOR: map:
The map can return IPv4 and IPv6"), we started using ADDR as "expected"
output type for converters. This still complies with the original
description from b805f71, because it is used as the theoric output
type, and is never emitted from the converters themselves (only "real"
types such as IPV4 or IPV6 are actually being emitted at runtime).

But this introduced an ambiguity as well as a few bugs, because some
compatibility checks are being performed at config parse time, and thus
rely on the expected output type to check if the conversion from current
element to the next element in the chain is theorically supported.

However, because the compatibility matrix doesn't support ADDR to other
types it is currently impossible to use map_*_ip converters in the middle
of a chain (the only supported usage is when map_*_ip converters are
at the very end of the chain).

To illustrate this, consider the following examples:

  acl test str(ok),map_str_ip(test.map) -m found                          # this will work
  acl test str(ok),map_str_ip(test.map),ipmask(24) -m found               # this will raise an error

Likewise, stktable_compatible_sample() check for stick tables also relies
on out_type[table_type] compatibility check, so map_*_ip cannot be used
with sticktables at the moment:

  backend st_test
    stick-table type string size 1m expire 10m store http_req_rate(10m)
  frontend fe
    bind localhost:8080
    mode http
    http-request track-sc0 str(test),map_str_ip(test.map) table st_test     # raises an error

To fix this, and prevent future usage of ADDR as expected output type
(for either fetches or converters) from introducing new bugs, the
ADDR=>? part of the matrix should follow the ANY type logic.

That is, ADDR, which is a pseudo-type, must be compatible with itself,
and where IPV4 and IPV6 both support a backward conversion to a given
type, ADDR must support it as well. It is done by setting the relevant
ADDR entries to c_pseudo() in the compatibility matrix to indicate that
the operation is theorically supported (c_pseudo() will never be executed
because ADDR should not be emitted: this only serves as a hint for
compatibility checks at parse time).

This is what's being done in this commit, thanks to this the broken
examples documented above should work as expected now, and future
usage of ADDR as out_type should not cause any issue.

2 years agoMINOR: sample: introduce c_pseudo() conv function
Aurelien DARRAGON [Tue, 6 Jun 2023 17:03:45 +0000 (19:03 +0200)] 
MINOR: sample: introduce c_pseudo() conv function

This function is used for ANY=>!ANY conversions in the compatibility
matrix to help differentiate between real NOOP (c_none) and pseudo
conversions that are theorically supported at config parse time but can
never occur at runtime,. That is, to explicit the fact that actual related
runtime operations (e.g.: ANY->IPV4) are not NOOP since they might require
some conversion to be performed depending on the input type.

When checking the conf we don't know the effective out types so
cast[pseudo type][pseudo type] is allowed in the compatibility matrix,
but at runtime we only expect cast[real type][(real type || pseudo type)]
because fetches and converters may not emit pseudo types, thus using
c_none() everywhere was too ambiguous.

The process will crash if c_pseudo() is invoked to help catch bugs:
crashing here means that a pseudo type has been encountered on a
converter's input at runtime (because it was emitted earlier in the
chain), which is not supported and results from a broken sample fetch
or converter implementation. (pseudo types may only be used as out_type
in sample definitions for compatibility checks at parsing time)

2 years agoMEDIUM: acl/sample: unify sample conv parsing in a single function
Aurelien DARRAGON [Mon, 5 Jun 2023 12:30:45 +0000 (14:30 +0200)] 
MEDIUM: acl/sample: unify sample conv parsing in a single function

Both sample_parse_expr() and parse_acl_expr() implement some code
logic to parse sample conv list after respective fetch or acl keyword.

(Seems like the acl one was inspired by the sample one historically)

But there is clearly code duplication between the two functions, making
them hard to maintain.
Hopefully, the parsing logic between them has stayed pretty much the
same, thus the sample conv parsing part may be moved in a dedicated
helper parsing function.

This is what's being done in this commit, we're adding the new function
sample_parse_expr_cnv() which does a single thing: parse the converters
that are listed right after a sample fetch keyword and inject them into
an already existing sample expression.

Both sample_parse_expr() and parse_acl_expr() were adapted to now make
use of this specific parsing function and duplicated code parts were
cleaned up.

Although sample_parse_expr() remains quite complicated (numerous function
arguments due to contextual parsing data) the first goal was to get rid of
code duplication without impacting the current behavior, with the added
benefit that it may allow further code cleanups / simplification in the
future.

2 years agoBUG/MINOR: tcp_sample: bc_{dst,src} return IP not INT
Aurelien DARRAGON [Wed, 7 Jun 2023 13:12:06 +0000 (15:12 +0200)] 
BUG/MINOR: tcp_sample: bc_{dst,src} return IP not INT

bc_{dst,src} sample fetches were introduced in 7d081f0 ("MINOR:
tcp_samples: Add samples to get src/dst info of the backend connection")

However a copy-pasting error was probably made here because they both
return IP addresses (not integers) like their fc_{src,dst} or src,dst
analogs.

Hopefully, this had no functional impact because integer can be converted
to both IPV4 and IPV6 types so the compatibility checks were not affected.

Better fix this to prevent confusion in code and "haproxy -dKsmp" output.

This should be backported up to 2.4 with 7d081f0.

2 years agoDOC: ssl: Add ocsp-update troubleshooting clues and emphasize on crt-list only aspect
Remi Tricot-Le Breton [Fri, 23 Jun 2023 15:01:09 +0000 (17:01 +0200)] 
DOC: ssl: Add ocsp-update troubleshooting clues and emphasize on crt-list only aspect

The current limitation of the 'ocsp-update' option and the fact that it
can only be used in crt-lists was puzzling for some people so the doc
was amended to emphasize this specificity. A configuration extract was
added as well.
A few troubleshooting clues were added as well.

Must be backported in 2.8.

2 years agoDOC: ssl: Fix typo in 'ocsp-update' option
Remi Tricot-Le Breton [Fri, 23 Jun 2023 15:01:08 +0000 (17:01 +0200)] 
DOC: ssl: Fix typo in 'ocsp-update' option

This patch fixes a misalignment in the 'ocsp-update' option description
and it splits the example log lines for readability.

Must be backported in 2.8.

2 years agoBUILD: quic: Compilation fixes for some gcc warnings with -O1
Frédéric Lécaille [Mon, 3 Jul 2023 12:31:13 +0000 (14:31 +0200)] 
BUILD: quic: Compilation fixes for some gcc warnings with -O1

This is to prevent the build from these gcc warning when compiling with -O1 option:

  willy@wtap:haproxy$ sh make-native-quic-memstat src/quic_conn.o CPU_CFLAGS="-O1"
    CC      src/quic_conn.o
  src/quic_conn.c: In function 'qc_prep_pkts':
  src/quic_conn.c:3700:44: warning: potential null pointer dereference [-Wnull-dereference]
   3700 |                                 frms = &qel->pktns->tx.frms;
        |                                         ~~~^~~~~~~
  src/quic_conn.c:3626:33: warning: 'end' may be used uninitialized in this function [-Wmaybe-uninitialized]
   3626 |                         if (end - pos < QUIC_INITIAL_PACKET_MINLEN) {
        |                             ~~~~^~~~~

2 years agoBUG/MINOR: quic: Missing QUIC connection path member initialization
Frédéric Lécaille [Mon, 3 Jul 2023 08:40:32 +0000 (10:40 +0200)] 
BUG/MINOR: quic: Missing QUIC connection path member initialization

This bug was introduced by this commit:
  MINOR: quic: Remove pool_zalloc() from qc_new_conn().

If ->path is not initialized to NULL value, and if a QUIC connection object
allocation has failed (from qc_new_conn()), haproxy could crash in
quic_conn_prx_cntrs_update() when dereferencing this QUIC connection member.

No backport needed.

2 years agoBUG/MINOR: quic: Possible leak when allocating an encryption level
Frédéric Lécaille [Mon, 3 Jul 2023 08:28:33 +0000 (10:28 +0200)] 
BUG/MINOR: quic: Possible leak when allocating an encryption level

This bug was reported by GH #2200 (coverity issue) as follows:

*** CID 1516590:  Resource leaks  (RESOURCE_LEAK)
/src/quic_tls.c: 159 in quic_conn_enc_level_init()
153
154             LIST_APPEND(&qc->qel_list, &qel->list);
155             *el = qel;
156             ret = 1;
157      leave:
158             TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
>>>     CID 1516590:  Resource leaks  (RESOURCE_LEAK)
>>>     Variable "qel" going out of scope leaks the storage it points to.
159             return ret;
160     }
161
162     /* Uninitialize <qel> QUIC encryption level. Never fails. */
163     void quic_conn_enc_level_uninit(struct quic_conn *qc, struct quic_enc_level *qel)
164     {

This bug was introduced by this commit which has foolishly assumed the encryption
level memory would be released after quic_conn_enc_level_init() has failed. This
is no more possible because this object is dynamic and no more a static member
of the QUIC connection object.

Anyway, this patch modifies quic_conn_enc_level_init() to ensure this is
no more leak when quic_conn_enc_level_init() fails calling quic_conn_enc_level_uninit()
in case of memory allocation error.

quic_conn_enc_level_uninit() code was moved without modification only to be defined
before quic_conn_enc_level_init()

There is no need to backport this.

2 years ago[RELEASE] Released version 2.9-dev1 v2.9-dev1
Willy Tarreau [Sun, 2 Jul 2023 09:13:42 +0000 (11:13 +0200)] 
[RELEASE] Released version 2.9-dev1

Released version 2.9-dev1 with the following main changes :
    - BUG/MINOR: stats: Fix Lua's `get_stats` function
    - MINOR: stats: protect against future stats fields omissions
    - BUG/MINOR: stream: do not use client-fin/server-fin with HTX
    - BUG/MINOR: quic: Possible crash when SSL session init fails
    - CONTRIB: Add vi file extensions to .gitignore
    - BUG/MINOR: spoe: Only skip sending new frame after a receive attempt
    - BUG/MINOR: peers: Improve detection of config errors in peers sections
    - REG-TESTS: stickiness: Delay haproxys start to properly resolv variables
    - DOC: quic: fix misspelled tune.quic.socket-owner
    - DOC: config: fix jwt_verify() example using var()
    - DOC: config: fix rfc7239 converter examples (again)
    - BUG/MINOR: cfgparse-tcp: leak when re-declaring interface from bind line
    - BUG/MINOR: proxy: add missing interface bind free in free_proxy
    - BUG/MINOR: proxy/server: free default-server on deinit
    - BUG/MEDIUM: hlua: Use front SC to detect EOI in HTTP applets' receive functions
    - BUG/MINOR: ssl: log message non thread safe in SSL Hanshake failure
    - BUG/MINOR: quic: Wrong encryption level flags checking
    - BUG/MINOR: quic: Address inversion in "show quic full"
    - BUG/MINOR: server: inherit from netns in srv_settings_cpy()
    - BUG/MINOR: namespace: missing free in netns_sig_stop()
    - BUG/MINOR: quic: Missing initialization (packet number space probing)
    - BUG/MINOR: quic: Possible crash in quic_conn_prx_cntrs_update()
    - BUG/MINOR: quic: Possible endless loop in quic_lstnr_dghdlr()
    - MINOR: quic: Remove pool_zalloc() from qc_new_conn()
    - MINOR: quic: Remove pool_zalloc() from qc_conn_alloc_ssl_ctx()
    - MINOR: quic: Remove pool_zalloc() from quic_dgram_parse()
    - BUG/MINOR: quic: Missing transport parameters initializations
    - BUG/MEDIUM: mworker: increase maxsock with each new worker
    - BUG/MINOR: quic: ticks comparison without ticks API use
    - BUG/MINOR: quic: Missing TLS secret context initialization
    - DOC: Add tune.h2.be.* and tune.h2.fe.* options to table of contents
    - DOC: Add tune.h2.max-frame-size option to table of contents
    - DOC: Attempt to fix dconv parsing error for tune.h2.fe.initial-window-size
    - REGTESTS: h1_host_normalization : Add a barrier to not mix up log messages
    - MEDIUM: mux-h1: Split h1_process_mux() to make code more readable
    - REORG: mux-h1: Rename functions to emit chunk size/crlf in the output buffer
    - MINOR: mux-h1: Add function to append the chunk size to the output buffer
    - MINOR: mux-h1: Add function to prepend the chunk crlf to the output buffer
    - MEDIUM: filters/htx: Don't rely on HTX extra field if payload is filtered
    - MEDIIM: mux-h1: Add splicing support for chunked messages
    - REGTESTS: Add a script to test the kernel splicing with chunked messages
    - CLEANUP: mux-h1: Remove useless __maybe_unused statement
    - BUG/MINOR: http_ext: fix if-none regression in forwardfor option
    - REGTEST: add an extra testcase for ifnone-forwardfor
    - BUG/MINOR: mworker: leak of a socketpair during startup failure
    - BUG/MINOR: quic: Prevent deadlock with CID tree lock
    - MEDIUM: ssl: handle the SSL_ERROR_ZERO_RETURN during the handshake
    - BUG/MINOR: ssl: SSL_ERROR_ZERO_RETURN returns CO_ER_SSL_EMPTY
    - BUILD: mux-h1: silence a harmless fallthrough warning
    - BUG/MEDIUM: quic: error checking buffer large enought to receive the retry tag
    - MINOR: ssl: allow to change the server signature algorithm on server lines
    - MINOR: ssl: allow to change the client-sigalgs on server lines
    - BUG/MINOR: config: fix stick table duplicate name check
    - BUG/MINOR: quic: Missing random bits in Retry packet header
    - BUG/MINOR: quic: Wrong Retry paquet version field endianess
    - BUG/MINOR: quic: Wrong endianess for version field in Retry token
    - IMPORT: slz: implement a synchronous flush() operation
    - MINOR: compression/slz: add support for a pure flush of pending bytes
    - MINOR: quic: Move QUIC TLS encryption level related code (quic_conn_enc_level_init())
    - MINOR: quic: Move QUIC encryption level structure definition
    - MINOR: quic: Implement a packet number space identification function
    - MINOR: quic: Move packet number space related functions
    - MEDIUM: quic: Dynamic allocations of packet number spaces
    - CLEANUP: quic: Remove qc_list_all_rx_pkts() defined but not used
    - MINOR: quic: Add a pool for the QUIC TLS encryption levels
    - MEDIUM: quic: Dynamic allocations of QUIC TLS encryption levels
    - MINOR: quic: Reduce the maximum length of TLS secrets
    - CLEANUP: quic: Remove two useless pools a low QUIC connection level
    - MEDIUM: quic: Handle the RX in one pass
    - MINOR: quic: Remove call to qc_rm_hp_pkts() from I/O callback
    - CLEANUP: quic: Remove server specific about Initial packet number space
    - MEDIUM: quic: Release encryption levels and packet number spaces asap
    - CLEANUP: quic: Remove a useless test about discarded pktns (qc_handle_crypto_frm())
    - MINOR: quic: Move the packet number space status at quic_conn level
    - MINOR: quic: Drop packet with type for discarded packet number space.
    - BUILD: quic: Add a DISGUISE() to please some compiler to qc_prep_hpkts() 1st parameter
    - BUILD: debug: avoid a build warning related to epoll_wait() in debug code

2 years agoBUILD: debug: avoid a build warning related to epoll_wait() in debug code
Willy Tarreau [Sun, 2 Jul 2023 08:49:49 +0000 (10:49 +0200)] 
BUILD: debug: avoid a build warning related to epoll_wait() in debug code

Ilya reported in issue #2193 that the latest Fedora complains about us
passing NULL to epoll_wait() in the "debug dev fd" code to try to detect
an epoll FD. That was intentional to get the kernel's verifications and
make sure we're facing a poller, but since such a warning comes from the
libc, it's possible that it plans to replace the syscall with a wrapper
in the near future (e.g. epoll_pwait()), and that just hiding the NULL
(as was confirmed to work) might just postpone the problem.

Let's take another approach, instead we'll create a new dummy FD that
we'll try to remove from the epoll set using epoll_ctl(). Since we
created the FD we're certain it cannot be there.  In this case (and
only in this case) epoll_ctl() will return -ENOENT, otherwise it will
typically return EINVAL or EBADF. It was verified that it works and
doesn't return false positives for other FD types. It should be
backported to the branches that contain a backport of the commit which
introduced the feature, apparently as far as 2.4:

  5be7c198e ("DEBUG: cli: add a new "debug dev fd" expert command")

2 years agoBUILD: quic: Add a DISGUISE() to please some compiler to qc_prep_hpkts() 1st parameter
Frédéric Lécaille [Fri, 30 Jun 2023 16:37:18 +0000 (18:37 +0200)] 
BUILD: quic: Add a DISGUISE() to please some compiler to qc_prep_hpkts() 1st parameter

Some compiler could complain with such a warning:
  src/quic_conn.c:3700:44: warning: potential null pointer dereference [-Wnull-dereference]
   3700 |                                 frms = &qel->pktns->tx.frms;

It could not figure out that <qel> could not be NULL at this location.
This is fixed calling qc_prep_hpkts() with a disguise 1st parameter.

2 years agoMINOR: quic: Drop packet with type for discarded packet number space.
Frédéric Lécaille [Thu, 29 Jun 2023 14:07:17 +0000 (16:07 +0200)] 
MINOR: quic: Drop packet with type for discarded packet number space.

This patch allows the low level packet parser to drop packets with type for discarded
packet number spaces. Furthermore, this prevents it from reallocating new encryption
levels and packet number spaces already released/discarded. When a packet number space
is discarded, it MUST NOT be reallocated.

As the packet number space discarding is done asap the type of packet received is
known, some packet number space discarding check may be safely removed from qc_try_rm_hp()
and qc_qel_may_rm_hp() which are called after having parse the packet header, and
is type.

2 years agoMINOR: quic: Move the packet number space status at quic_conn level
Frédéric Lécaille [Wed, 28 Jun 2023 16:41:42 +0000 (18:41 +0200)] 
MINOR: quic: Move the packet number space status at quic_conn level

As the packet number spaces and encryption level are dynamically allocated,
the information about the packet number space discarded status must be kept
somewhere else than in these objects.

quic_tls_discard_keys() is no more useful.
Modify quic_pktns_discard() to do the same job: flag the quic_conn object
has having discarded packet number space.
Implement quic_tls_pktns_is_disarded() to check if a packet number space is
discarded. Note the Application data packet number space is never discarded.

2 years agoCLEANUP: quic: Remove a useless test about discarded pktns (qc_handle_crypto_frm())
Frédéric Lécaille [Wed, 28 Jun 2023 16:28:51 +0000 (18:28 +0200)] 
CLEANUP: quic: Remove a useless test about discarded pktns (qc_handle_crypto_frm())

There is no need to check that the packet number space associated to the encryption
level to handle the CRYPTO frames is available when entering qc_handle_crypto_frm().
This has already been done by the caller: qc_treat_rx_pkts().

2 years agoMEDIUM: quic: Release encryption levels and packet number spaces asap
Frédéric Lécaille [Tue, 27 Jun 2023 17:24:50 +0000 (19:24 +0200)] 
MEDIUM: quic: Release encryption levels and packet number spaces asap

Release the memory allocated for the Initial and Handshake encryption level
under packet number spaces as soon as possible.

qc_treat_rx_pkts() has been modified to do that for the Initial case. This must
be done after all the Initial packets have been parsed and the underlying TLS
secrets have been flagged as to be discarded. As the Initial encryption level is
removed from the list attached to the quic_conn object inside a list_for_each_entry()
loop, this latter had to be converted into a list_for_each_entry_safe() loop.

The memory allocated by the Handshake encryption level and packet number spaces
is released just before leaving the handshake I/O callback (qc_conn_io_cb()).

As ->iel and ->hel pointer to Initial and Handshake encryption are reset to null
value when releasing the encryption levels memory, some check have been added
at several place before dereferencing them. Same thing for the ->ipktns and ->htpktns
pointer to packet number spaces.

Also take the opportunity of this patch to modify qc_dgrams_retransmit() to
use packet number space variables in place of encryption level variables to shorten
some statements. Furthermore this reflects the jobs it has to do: retransmit
UDP datagrams from packet number spaces.

2 years agoCLEANUP: quic: Remove server specific about Initial packet number space
Frédéric Lécaille [Mon, 26 Jun 2023 13:57:39 +0000 (15:57 +0200)] 
CLEANUP: quic: Remove server specific about Initial packet number space

Remove a code section about the QUIC client Initial packet number space
dropping.

Should be backported as far as 2.6 to ease future backports to come.

2 years agoMINOR: quic: Remove call to qc_rm_hp_pkts() from I/O callback
Frédéric Lécaille [Mon, 26 Jun 2023 13:11:04 +0000 (15:11 +0200)] 
MINOR: quic: Remove call to qc_rm_hp_pkts() from I/O callback

quic_conn_io_cb() is the I/O handler callback used during the handshakes.
quic_conn_app_io_cb() is used after the handshakes. Both call qc_rm_hp_pkts()
before parsing the RX packets ordered by their packet numbers calling qc_treat_rx_pkts().
qc_rm_hp_pkts() is there to remove the header protection to reveal the packet
numbers, then reorder the packets by their packet numbers.

qc_rm_hp_pkts() may be safely directly called by qc_treat_rx_pkts(), which is
itself called by the I/O handlers.

2 years agoMEDIUM: quic: Handle the RX in one pass
Frédéric Lécaille [Thu, 22 Jun 2023 16:54:21 +0000 (18:54 +0200)] 
MEDIUM: quic: Handle the RX in one pass

Insert a loop around the existing code of qc_treat_rx_pkts() to handle all
the RX packets by encryption level for all the encryption levels allocated
for the connection, i.e. for all the encryption levels with secrets derived
from the ones provided by the TLS stack through ->set_encryption_secrets().

2 years agoCLEANUP: quic: Remove two useless pools a low QUIC connection level
Frédéric Lécaille [Thu, 22 Jun 2023 13:02:38 +0000 (15:02 +0200)] 
CLEANUP: quic: Remove two useless pools a low QUIC connection level

Both "quic_tx_ring" and "quic_rx_crypto_frm" pool are no more used.

Should be backported as far as 2.6.

2 years agoMINOR: quic: Reduce the maximum length of TLS secrets
Frédéric Lécaille [Thu, 22 Jun 2023 12:51:28 +0000 (14:51 +0200)] 
MINOR: quic: Reduce the maximum length of TLS secrets

The maximum length of the secrets derived by the TLS stack is 384 bits.
This reduces the size of the objects provided by the "quic_tls_secret" pool by
16 bytes.

Should be backported as far as 2.6

2 years agoMEDIUM: quic: Dynamic allocations of QUIC TLS encryption levels
Frédéric Lécaille [Thu, 22 Jun 2023 05:19:03 +0000 (07:19 +0200)] 
MEDIUM: quic: Dynamic allocations of QUIC TLS encryption levels

Replace ->els static array of encryption levels by 4 pointers into the QUIC
connection object, quic_conn struct.
    ->iel denotes the Initial encryption level,
    ->eel the Early-Data encryption level,
    ->hel the Handshaske encryption level and
    ->ael the Application Data encryption level.

Add ->qel_list to this structure to list the encryption levels after having been
allocated. Modify consequently the encryption level object itself (quic_enc_level
struct) so that it might be added to ->qel_list QUIC connection list of
encryption levels.

Implement qc_enc_level_alloc() to initialize the value of a pointer to an encryption
level object. It is used to initialized the pointer newly added to the quic_conn
structure. It also takes a packet number space pointer address as argument to
initialize it if not already initialized.

Modify quic_tls_ctx_reset() to call it from quic_conn_enc_level_init() which is
called by qc_enc_level_alloc() to allocate an encryption level object.

Implement 2 new helper functions:
  - ssl_to_qel_addr() to match and pointer address to a quic_encryption level
    attached to a quic_conn object with a TLS encryption level enum value;
  - qc_quic_enc_level() to match a pointer to a quic_encryption level attached
    to a quic_conn object with an internal encryption level enum value.
This functions are useful to be called from ->set_encryption_secrets() and
->add_handshake_data() TLS stack called which takes a TLS encryption enum
as argument (enum ssl_encryption_level_t).

Replace all the use of the qc->els[] array element values by one of the newly
added ->[ieha]el quic_conn struct member values.

2 years agoMINOR: quic: Add a pool for the QUIC TLS encryption levels
Frédéric Lécaille [Wed, 21 Jun 2023 14:50:33 +0000 (16:50 +0200)] 
MINOR: quic: Add a pool for the QUIC TLS encryption levels

Very simple patch to define and declare a pool for the QUIC TLS encryptions levels.
It will be used to dynamically allocate such objects to be attached to the
QUIC connection object (quic_conn struct) and to remove from quic_conn struct the
static array of encryption levels (see ->els[]).

2 years agoCLEANUP: quic: Remove qc_list_all_rx_pkts() defined but not used
Frédéric Lécaille [Tue, 20 Jun 2023 13:13:12 +0000 (15:13 +0200)] 
CLEANUP: quic: Remove qc_list_all_rx_pkts() defined but not used

This function is not used. May be safely removed.

2 years agoMEDIUM: quic: Dynamic allocations of packet number spaces
Frédéric Lécaille [Tue, 20 Jun 2023 09:21:43 +0000 (11:21 +0200)] 
MEDIUM: quic: Dynamic allocations of packet number spaces

Add a pool to dynamically handle the memory used for the QUIC TLS packet number spaces.
Remove the static array of packet number spaces at QUIC connection level (struct
quic_conn) and add three new members to quic_conn struc as pointers to quic_pktns
struct, one by packet number space as follows:
     ->ipktns for Initial packet number space,
     ->hpktns for Handshake packet number space and
     ->apktns for Application packet number space.
Also add a ->pktns_list new member (struct list) to quic_conn struct to attach
the list of the packet number spaces allocated for the QUIC connection.
Implement ssl_to_quic_pktns() to map and retrieve the addresses of these pointers
from TLS stack encryption levels.
Modify quic_pktns_init() to initialize these members.
Modify ha_quic_set_encryption_secrets() and ha_quic_add_handshake_data()  to
allocate the packet numbers and initialize the encryption level.
Implement quic_pktns_release() which takes pointers to pointers to packet number
space objects to release the memory allocated for a packet number space attached
to a QUIC connection and reset their address values.

Modify qc_new_conn() to allocation only the Initial packet number space and
Initial encryption level.

Modify QUIC loss detection API (quic_loss.c) to use the new ->pktns_list
list attached to a QUIC connection in place of a static array of packet number
spaces.

Replace at several locations the use of elements of an array of packet number
spaces by one of the three pointers to packet number spaces

2 years agoMINOR: quic: Move packet number space related functions
Frédéric Lécaille [Tue, 13 Jun 2023 06:17:23 +0000 (08:17 +0200)] 
MINOR: quic: Move packet number space related functions

Move packet number space related functions from quic_conn.h to quic_tls.h.

Should be backported as far as 2.6 to ease future backports to come.

2 years agoMINOR: quic: Implement a packet number space identification function
Frédéric Lécaille [Mon, 12 Jun 2023 16:54:29 +0000 (18:54 +0200)] 
MINOR: quic: Implement a packet number space identification function

Implement quic_pktns_char() to identify a packet number space from a
quic_conn object. Usefull only for traces.

2 years agoMINOR: quic: Move QUIC encryption level structure definition
Frédéric Lécaille [Mon, 12 Jun 2023 16:19:17 +0000 (18:19 +0200)] 
MINOR: quic: Move QUIC encryption level structure definition

haproxy/quic_tls-t.h is the correct place to quic_enc_level structure
definition.

Should be backported as far as 2.6 to ease any further backport to come.

2 years agoMINOR: quic: Move QUIC TLS encryption level related code (quic_conn_enc_level_init())
Frédéric Lécaille [Thu, 22 Jun 2023 05:35:10 +0000 (07:35 +0200)] 
MINOR: quic: Move QUIC TLS encryption level related code (quic_conn_enc_level_init())

quic_conn_enc_level_init() location is definitively in QUIC TLS API source file:
src/quic_tls.c.

2 years agoMINOR: compression/slz: add support for a pure flush of pending bytes
Willy Tarreau [Mon, 26 Jun 2023 17:34:39 +0000 (19:34 +0200)] 
MINOR: compression/slz: add support for a pure flush of pending bytes

While HTTP makes no promises of sub-message delivery, haproxy tries to
make reasonable efforts to be friendly to applications relying on this,
particularly though the "option http-no-delay" statement. However, it
was reported that when slz compression is being used, a few bytes can
remain pending for more data to complete them in the SLZ queue when
built on a 64-bit little endian architecture. This is because aligning
blocks on byte boundary is costly (requires to switch to literals and
to send 4 bytes of block size), so incomplete bytes are left pending
there until they reach at least 32 bits. On other architecture, the
queue is only 8 bits long.

Robert Newson from Apache's CouchDB project explained that the heartbeat
used by CouchDB periodically delivers a single LF character, that it used
to work fine before the change enlarging the queue for 64-bit platforms,
but only forwards once every 3 LF after the change. This was definitely
caused by this incomplete byte sequence queuing. Zlib is not affected,
and the code shows that ->flush() is always called. In the case of SLZ,
the called function is rfc195x_flush_or_finish() and when its "finish"
argument is zero, no flush is performed because there was no such flush()
operation.

The previous patch implemented a flush() operation in SLZ, and this one
makes rfc195x_flush_or_finish() call it when finish==0. This way each
delivered data block will now provoke a flush of the queue as is done
with zlib.

This may very slightly degrade the compression ratio, but another change
is needed to condition this on "option http-no-delay" only in order to
be consistent with other parts of the code.

This patch (and the preceeding slz one) should be backported at least to
2.6, but any further change to depend on http-no-delay should not.

2 years agoIMPORT: slz: implement a synchronous flush() operation
Willy Tarreau [Mon, 26 Jun 2023 17:24:55 +0000 (19:24 +0200)] 
IMPORT: slz: implement a synchronous flush() operation

In some cases it may be desirable for latency reasons to forcefully
flush the queue even if it results in suboptimal compression. In our
case the queue might contain up to almost 4 bytes, which need an EOB
and a switch to literal mode, followed by 4 bytes to encode an empty
message. This means that each call can add 5 extra bytes in the ouput
stream. And the flush may also result in the header being produced for
the first time, which can amount to 2 or 10 bytes (zlib or gzip). In
the worst case, a total of 19 bytes may be emitted at once upon a flush
with 31 pending bits and a gzip header.

This is libslz upstream commit cf8c4668e4b4216e930b56338847d8d46a6bfda9.

2 years agoBUG/MINOR: quic: Wrong endianess for version field in Retry token
Frédéric Lécaille [Fri, 30 Jun 2023 12:57:30 +0000 (14:57 +0200)] 
BUG/MINOR: quic: Wrong endianess for version field in Retry token

This field must be sent in network byte order.

Must be backported as far as 2.6.

2 years agoBUG/MINOR: quic: Wrong Retry paquet version field endianess
Frédéric Lécaille [Fri, 30 Jun 2023 12:41:31 +0000 (14:41 +0200)] 
BUG/MINOR: quic: Wrong Retry paquet version field endianess

The 32-bits version field of the Retry paquet was inversed by the code. As this
field must be in the network byte order on the wire, this code has supposed that
the sender of the Retry packet will always be little endian. Hopefully this is
often the case on our Intel machines ;)

Must be backported as far as 2.6.

2 years agoBUG/MINOR: quic: Missing random bits in Retry packet header
Frédéric Lécaille [Fri, 30 Jun 2023 10:17:36 +0000 (12:17 +0200)] 
BUG/MINOR: quic: Missing random bits in Retry packet header

The 4 bits least significant bits of the first byte in a Retry packet must be
random. There are generated calling statistical_prng_range() with 16 as argument.

Must be backported as far as 2.6.

2 years agoBUG/MINOR: config: fix stick table duplicate name check
Patrick Hemmer [Mon, 26 Jun 2023 18:14:47 +0000 (14:14 -0400)] 
BUG/MINOR: config: fix stick table duplicate name check

When a stick-table is defined within a peers section, the name is
prefixed with the peers section name. However when checking for
duplicate table names, the check was using the table name without
the prefix, and would thus never match.

Must be backported as far as 2.6.

2 years agoMINOR: ssl: allow to change the client-sigalgs on server lines
William Lallemand [Thu, 29 Jun 2023 12:11:46 +0000 (14:11 +0200)] 
MINOR: ssl: allow to change the client-sigalgs on server lines

This patch introduces the "client-sigalgs" keyword for the server line,
which allows to configure the list of server signature algorithms
negociated during the handshake. Also available as
"ssl-default-server-client-sigalgs" in the global section.

2 years agoMINOR: ssl: allow to change the server signature algorithm on server lines
William Lallemand [Thu, 29 Jun 2023 11:29:59 +0000 (13:29 +0200)] 
MINOR: ssl: allow to change the server signature algorithm on server lines

This patch introduces the "sigalgs" keyword for the server line, which
allows to configure the list of server signature algorithms negociated
during the handshake. Also available as "ssl-default-server-sigalgs" in
the global section.

2 years agoBUG/MEDIUM: quic: error checking buffer large enought to receive the retry tag
Emeric Brun [Tue, 27 Jun 2023 13:24:05 +0000 (15:24 +0200)] 
BUG/MEDIUM: quic: error checking buffer large enought to receive the retry tag

Building a retry message, the offset of the tag was checked instead of the
remaining length into the buffer.

Must be backported as far as 2.6.

2 years agoBUILD: mux-h1: silence a harmless fallthrough warning
Willy Tarreau [Tue, 27 Jun 2023 14:06:25 +0000 (16:06 +0200)] 
BUILD: mux-h1: silence a harmless fallthrough warning

This warning happened in 2.9-dev with commit 723c73f8a ("MEDIUM: mux-h1:
Split h1_process_mux() to make code more readable"). It's the usual gcc
crap that relies on comments to disable the warning but which drops these
comments between the preprocessor and the compiler, so using any split
build system (distcc, ccache etc) reintroduces the warning. Use the more
reliable and portable __fallthrough instead. No backport needed.

2 years agoBUG/MINOR: ssl: SSL_ERROR_ZERO_RETURN returns CO_ER_SSL_EMPTY
William Lallemand [Mon, 26 Jun 2023 17:08:00 +0000 (19:08 +0200)] 
BUG/MINOR: ssl: SSL_ERROR_ZERO_RETURN returns CO_ER_SSL_EMPTY

Return a more acurate error than the previous patch, CO_ER_SSL_EMPTY is
the code for "Connection closed during SSL handshake" which is more
precise than CO_ER_SSL_ABORT ("Connection error during SSL handshake").

No backport needed.

2 years agoMEDIUM: ssl: handle the SSL_ERROR_ZERO_RETURN during the handshake
William Lallemand [Mon, 26 Jun 2023 15:42:09 +0000 (17:42 +0200)] 
MEDIUM: ssl: handle the SSL_ERROR_ZERO_RETURN during the handshake

During a SSL_do_handshake(), SSL_ERROR_ZERO_RETURN can be returned in case
the remote peer sent a close_notify alert. Previously this would set the
connection error to CO_ER_SSL_HANDSHAKE, this patch sets it to
CO_ER_SSL_ABORT to have a more acurate error.

2 years agoBUG/MINOR: quic: Prevent deadlock with CID tree lock
Frédéric Lécaille [Mon, 26 Jun 2023 08:39:56 +0000 (10:39 +0200)] 
BUG/MINOR: quic: Prevent deadlock with CID tree lock

This bug was introduced by this commit which was not sufficient:
      BUG/MINOR: quic: Possible endless loop in quic_lstnr_dghdlr()

It was revealed by the blackhole interop runner test with neqo as client.

qc_conn_release() could be called after having locke the CID tree when two different
threads was creating the same connection at the same time. Indeed in this case
the last thread which tried to create a new connection for the same an already existing
CID could not manage to insert an already inserted CID in the connection CID tree.
This was expected. It had to destroy the newly created for nothing connection calling
qc_conn_release(). But this function also locks this tree calling free_quic_conn_cids() leading to a deadlock.
A solution would have been to delete the new CID created from its tree before
calling qc_conn_release().

A better solution is to stop inserting the first CID from qc_new_conn(), and to
insert it into the CID tree only if there was not an already created connection.
This is whas is implemented by this patch.

Must be backported as far as 2.7.

2 years agoBUG/MINOR: mworker: leak of a socketpair during startup failure
William Lallemand [Wed, 21 Jun 2023 07:44:18 +0000 (09:44 +0200)] 
BUG/MINOR: mworker: leak of a socketpair during startup failure

Aurelien Darragon found a case of leak when working on ticket #2184.

When a reexec_on_failure() happens *BEFORE* protocol_bind_all(), the
worker is not fork and the mworker_proc struct is still there with
its 2 socketpairs.

The socketpair that is supposed to be in the master is already closed in
mworker_cleanup_proc(), the one for the worker was suppposed to
be cleaned up in mworker_cleanlisteners().

However, since the fd is not bound during this failure, the fd is never
closed.

This patch fixes the problem by setting the fd to -1 in the mworker_proc
after the fork, so we ensure that this it won't be close if everything
was done right, and then we try to close it in mworker_cleanup_proc()
when it's not set to -1.

This could be triggered with the script in ticket #2184 and a `ulimit -H
-n 300`. This will fail before the protocol_bind_all() when trying to
increase the nofile setrlimit.

In recent version of haproxy, there is a BUG_ON() in fd_insert() that
could be triggered by this bug because of the global.maxsock check.

Must be backported as far as 2.6.

The problem could exist in previous version but the code is different
and this won't be triggered easily without other consequences in the
master.

2 years agoREGTEST: add an extra testcase for ifnone-forwardfor
Aurelien DARRAGON [Tue, 20 Jun 2023 13:02:11 +0000 (15:02 +0200)] 
REGTEST: add an extra testcase for ifnone-forwardfor

In GH #2187 it was mentioned that the ifnone-forwardfor regtest
did not cover the case where forwardfor ifnone is explicitly set in
the frontend but forwardfor option is not used in the backend.

Expected behavior in this case is that the frontend takes the precedence
because the backend did not specify the option.

Adding this missing case to prevent regressions in the future.

2 years agoBUG/MINOR: http_ext: fix if-none regression in forwardfor option
Aurelien DARRAGON [Tue, 20 Jun 2023 12:55:11 +0000 (14:55 +0200)] 
BUG/MINOR: http_ext: fix if-none regression in forwardfor option

A regression was introduced in 730b983 ("MINOR: proxy: move 'forwardfor'
option to http_ext")

Indeed, when the forwardfor if-none option is specified on the frontend
but forwardfor is not specified at all on the backend: if-none from the
frontend is ignored.

But this behavior conflicts with the historical one, if-none should only
be ignored if forwardfor is also enabled on the backend and if-none is
not set there.

It should fix GH #2187.

This should be backported in 2.8 with 730b983 ("MINOR: proxy: move
'forwardfor' option to http_ext")

2 years agoCLEANUP: mux-h1: Remove useless __maybe_unused statement
Christopher Faulet [Tue, 20 Jun 2023 11:59:23 +0000 (13:59 +0200)] 
CLEANUP: mux-h1: Remove useless __maybe_unused statement

h1_append_chunk_size() and h1_prepend_chunk_crlf() functions were marked as
possibly unused to be able to add them in standalone commits. Now these
functions are used, the __maybe_unused statement can be removed.

2 years agoREGTESTS: Add a script to test the kernel splicing with chunked messages
Christopher Faulet [Tue, 20 Jun 2023 11:34:50 +0000 (13:34 +0200)] 
REGTESTS: Add a script to test the kernel splicing with chunked messages

Support of the kernel splicing for chunked messages was re-introduced. This
script should validate it properly works.

2 years agoMEDIIM: mux-h1: Add splicing support for chunked messages
Christopher Faulet [Tue, 20 Jun 2023 11:34:49 +0000 (13:34 +0200)] 
MEDIIM: mux-h1: Add splicing support for chunked messages

When the HTX was introduced, we have lost the support for the kernel
splicing for chunked messages. Thanks to this patch set, it is possible
again. Of course, we still need to keep the H1 parser synchronized. Thus
only the chunk content can be spliced. We still need to read the chunk
envelope using a buffer.

There is no reason to backport this feature. But, just in case, this patch
depends on following patches:

  * "MEDIUM: filters/htx: Don't rely on HTX extra field if payload is filtered"
  * "MINOR: mux-h1: Add function to prepend the chunk crlf to the output buffer"
  * "MINOR: mux-h1: Add function to append the chunk size to the output buffer"
  * "REORG: mux-h1: Rename functions to emit chunk size/crlf in the output buffer"
  * "MEDIUM: mux-h1: Split h1_process_mux() to make code more readable"

2 years agoMEDIUM: filters/htx: Don't rely on HTX extra field if payload is filtered
Christopher Faulet [Tue, 20 Jun 2023 11:34:46 +0000 (13:34 +0200)] 
MEDIUM: filters/htx: Don't rely on HTX extra field if payload is filtered

If an HTTP data filter is registered on a channel, we must not rely on the
HTX extra field because the payload may be changed and we cannot predict if
this value will change or not. It is too errorprone to let filters deal with
this reponsibility. So we set it to 0 when payload filtering is performed,
but only if the payload length can be determined. It is important because
this field may be used when data are forwarded. In fact, it will be used by
the H1 multiplexer to be able to splice chunk-encoded payload.

2 years agoMINOR: mux-h1: Add function to prepend the chunk crlf to the output buffer
Christopher Faulet [Tue, 20 Jun 2023 11:33:59 +0000 (13:33 +0200)] 
MINOR: mux-h1: Add function to prepend the chunk crlf to the output buffer

h1_prepend_chunk_crlf() function does the opposite of
h1_append_chunk_crlf(). It emit the chunk size in front of the output
buffer.

2 years agoMINOR: mux-h1: Add function to append the chunk size to the output buffer
Christopher Faulet [Tue, 20 Jun 2023 11:33:53 +0000 (13:33 +0200)] 
MINOR: mux-h1: Add function to append the chunk size to the output buffer

h1_append_chunk_size() function does the opposite of
h1_prepend_chunk_size(). It emit the chunk size at the end of the output
buffer.

2 years agoREORG: mux-h1: Rename functions to emit chunk size/crlf in the output buffer
Christopher Faulet [Tue, 20 Jun 2023 11:33:23 +0000 (13:33 +0200)] 
REORG: mux-h1: Rename functions to emit chunk size/crlf in the output buffer

h1_emit_chunk_size() and h1_emit_chunk_crlf() functions were renamed,
respectively, h1_prepend_chunk_size() and h1_append_chunk_crlf().

2 years agoMEDIUM: mux-h1: Split h1_process_mux() to make code more readable
Christopher Faulet [Tue, 20 Jun 2023 11:33:01 +0000 (13:33 +0200)] 
MEDIUM: mux-h1: Split h1_process_mux() to make code more readable

h1_process_mux() function was pretty huge a quite hard to debug. So, the
funcion is split in sub-functions. Each sub-function is responsible to a
part of the message (start-line, headers, payload, trailers...). We are
still relying on a HTTP parser to format the message to be sure to detect
errors.  Functionnaly speaking, there is no change. But the code is now more
readable.

2 years agoREGTESTS: h1_host_normalization : Add a barrier to not mix up log messages
Christopher Faulet [Mon, 19 Jun 2023 17:00:52 +0000 (19:00 +0200)] 
REGTESTS: h1_host_normalization : Add a barrier to not mix up log messages

Depending on the timing, time to time, the log messages can be mixed. A
client can start and be fully handled by HAProxy (including its log message)
before the log message of the previous client was emitted or received.  To
fix the issue, a barrier was added to be sure to eval the "expect" rule on
logs before starting the next client.

2 years agoDOC: Attempt to fix dconv parsing error for tune.h2.fe.initial-window-size
Tim Duesterhus [Tue, 13 Jun 2023 13:15:47 +0000 (15:15 +0200)] 
DOC: Attempt to fix dconv parsing error for tune.h2.fe.initial-window-size

It appears that dconv dislikes the "see also" part being on the same line as
the regular paragraph. The beginning of the line does not show up in the
rendered version.

Attempt to fix this by inserting an additional newline which is consistent with
other options.

2 years agoDOC: Add tune.h2.max-frame-size option to table of contents
Tim Duesterhus [Tue, 13 Jun 2023 13:08:47 +0000 (15:08 +0200)] 
DOC: Add tune.h2.max-frame-size option to table of contents

This option was introduced in a24b35ca18885809001454699b4e44b49abccde6, which
is 2.0+. It should be backported as far as it easily applies.

2 years agoDOC: Add tune.h2.be.* and tune.h2.fe.* options to table of contents
Tim Duesterhus [Tue, 13 Jun 2023 13:07:34 +0000 (15:07 +0200)] 
DOC: Add tune.h2.be.* and tune.h2.fe.* options to table of contents

These new options were introduced in commits
9d7abda787ac76c04a7e68363d7a322918ce28a7 and
ca1027c22fda9d993cbce716163d28b1e4e8aa0f, both of which at in HAProxy 2.8+.
This patch should be backported there.

2 years agoBUG/MINOR: quic: Missing TLS secret context initialization
Frédéric Lécaille [Mon, 19 Jun 2023 09:56:19 +0000 (11:56 +0200)] 
BUG/MINOR: quic: Missing TLS secret context initialization

This bug arrived with this commit:

     MINOR: quic: Remove pool_zalloc() from qc_new_conn()

Missing initialization of largest packet number received during a keyupdate phase.
This prevented the keyupdate feature from working and made the keyupdate interop
tests to fail for all the clients.

Furthermore, ->flags from quic_tls_ctx was also not initialized. This could
also impact the keyupdate feature at least.

No backport needed.

2 years agoBUG/MINOR: quic: ticks comparison without ticks API use
Frédéric Lécaille [Mon, 19 Jun 2023 08:47:24 +0000 (10:47 +0200)] 
BUG/MINOR: quic: ticks comparison without ticks API use

Replace a "less than" comparison between two tick variable by a call to tick_is_lt()
in quic_loss_pktns(). This bug could lead to a wrong packet loss detection
when the loss time computed values could wrap. This is the case 20 seconds after
haproxy has started.

Must be backported as far as 2.6.

2 years agoBUG/MEDIUM: mworker: increase maxsock with each new worker
William Lallemand [Mon, 19 Jun 2023 15:12:58 +0000 (17:12 +0200)] 
BUG/MEDIUM: mworker: increase maxsock with each new worker

In ticket #2184, HAProxy is crashing in a BUG_ON() after a lot of reload
when the previous processes did not exit.

Each worker has a socketpair which is a FD in the master, when reloading
this FD still exists until the process leaves. But the global.maxconn
value is not incremented for each of these FD. So when there is too much
workers and the number of FD reaches maxsock, the next FD inserted in
the poller will crash the process.

This patch fixes the issue by increasing the maxsock for each remaining
worker.

Must be backported in every maintained version.

2 years agoBUG/MINOR: quic: Missing transport parameters initializations
Frédéric Lécaille [Sat, 17 Jun 2023 11:23:16 +0000 (13:23 +0200)] 
BUG/MINOR: quic: Missing transport parameters initializations

This bug was introduced by this commit:

     MINOR: quic: Remove pool_zalloc() from qc_new_conn()

The transport parameters was not initialized. This leaded to a crash when
dumping the received ones from TRACE()s.

Also reset the lengths of the CIDs attached to a quic_conn struct to 0 value
to prevent them from being dumped from traces when not already initialized.

No backport needed.

2 years agoMINOR: quic: Remove pool_zalloc() from quic_dgram_parse()
Frédéric Lécaille [Thu, 15 Jun 2023 11:43:47 +0000 (13:43 +0200)] 
MINOR: quic: Remove pool_zalloc() from quic_dgram_parse()

Replace a call to pool_zalloc() by a call to pool_malloc() into quic_dgram_parse
to allocate quic_rx_packet struct objects.
Initialize almost all the members of quic_rx_packet struct.
->saddr is initialized by quic_rx_pkt_retrieve_conn().
->pnl and ->pn are initialized by qc_do_rm_hp().
->dcid and ->scid are initialized by quic_rx_pkt_parse() which calls
quic_packet_read_long_header() for a long packet. For a short packet,
only ->dcid will be initialized.

2 years agoMINOR: quic: Remove pool_zalloc() from qc_conn_alloc_ssl_ctx()
Frédéric Lécaille [Thu, 15 Jun 2023 09:02:53 +0000 (11:02 +0200)] 
MINOR: quic: Remove pool_zalloc() from qc_conn_alloc_ssl_ctx()

pool_zalloc() is replaced by pool_alloc() into qc_conn_alloc_ssl_ctx() to allocate
a ssl_sock_ctx struct. ssl_sock_ctx struct member are all initiliazed to null values
excepted ->ssl which is initialized by the next statement: a call to qc_ssl_sess_init().

2 years agoMINOR: quic: Remove pool_zalloc() from qc_new_conn()
Frédéric Lécaille [Thu, 15 Jun 2023 05:53:42 +0000 (07:53 +0200)] 
MINOR: quic: Remove pool_zalloc() from qc_new_conn()

qc_new_conn() is ued to initialize QUIC connections with quic_conn struct objects.
This function calls quic_conn_release() when it fails to initialize a connection.
quic_conn_release() is also called to release the memory allocated by a QUIC
connection.

Replace pool_zalloc() by pool_alloc() in this function and initialize
all quic_conn struct members which are referenced by quic_conn_release() to
prevent use of non initialized variables in this fonction.
The ebtrees, the lists attached to quic_conn struct must be initialized.
The tasks must be reset to their NULL default values to be safely destroyed
by task_destroy(). This is all the case for all the TLS cipher contexts
of the encryption levels (struct quic_enc_level) and those for the keyupdate.
The packet number spaces (struct quic_pktns) must also be initialized.
->prx_counters pointer must be initialized to prevent quic_conn_prx_cntrs_update()
from dereferencing this pointer.
->latest_rtt member of quic_loss struct must also be initialized. This is done
by quic_loss_init() called by quic_path_init().

2 years agoBUG/MINOR: quic: Possible endless loop in quic_lstnr_dghdlr()
Frédéric Lécaille [Fri, 16 Jun 2023 14:10:58 +0000 (16:10 +0200)] 
BUG/MINOR: quic: Possible endless loop in quic_lstnr_dghdlr()

This may happen when the initilization of a new QUIC conn fails with qc_new_conn()
when receiving an Initial paquet. This is done after having allocated a CID with
new_quic_cid() called by quic_rx_pkt_retrieve_conn() which stays in the listener
connections tree without a QUIC connection attached to. Then when the listener
receives another Initial packet for the same CID, quic_rx_pkt_retrieve_conn()
returns NULL again (no QUIC connection) but with an thread ID already bound to the
connection, leading the datagram to be requeued in the same datagram handler thread
queue. And so on.

To fix this, the connection is created after having created the connection ID.
If this fails, the connection is deallocated.

During the race condition, when two different threads handle two datagrams for
the same connection, in addition to releasing the newer created connection ID,
the newer QUIC connection must also be released.

Must be backported as far as 2.7.

2 years agoBUG/MINOR: quic: Possible crash in quic_conn_prx_cntrs_update()
Frédéric Lécaille [Wed, 14 Jun 2023 16:09:54 +0000 (18:09 +0200)] 
BUG/MINOR: quic: Possible crash in quic_conn_prx_cntrs_update()

quic_conn_prx_cntrs_update() may be called from quic_conn_release() with
NULL as value for ->prx_counters member. This is the case when qc_new_conn() fails
when allocating <buf_area>. In this case quic_conn_prx_cntrs_update() BUG_ON().

Must be backported as far as 2.7.

2 years agoBUG/MINOR: quic: Missing initialization (packet number space probing)
Frédéric Lécaille [Wed, 14 Jun 2023 09:34:47 +0000 (11:34 +0200)] 
BUG/MINOR: quic: Missing initialization (packet number space probing)

->tx.pto_probe member of quic_pktns struct was not initialized by quic_pktns_init().
This bug never occured because all quic_pktns structs are attached to quic_conn
structs which are always pool_zalloc()'ed.

Must be backported as far as 2.6.

2 years agoBUG/MINOR: namespace: missing free in netns_sig_stop()
Aurelien DARRAGON [Wed, 14 Jun 2023 08:11:13 +0000 (10:11 +0200)] 
BUG/MINOR: namespace: missing free in netns_sig_stop()

On soft-stop, netns_sig_stop() function is called to purge the shared
namespace tree by iterating over each entries to free them.

However, once an entry is cleaned up and removed from the tree, the entry
itself isn't freed and this results into a minor leak when soft-stopping
because entry was allocated using calloc() in netns_store_insert() when
parsing the configuration.

This could be backported in every stable versions.

2 years agoBUG/MINOR: server: inherit from netns in srv_settings_cpy()
Aurelien DARRAGON [Wed, 14 Jun 2023 07:53:32 +0000 (09:53 +0200)] 
BUG/MINOR: server: inherit from netns in srv_settings_cpy()

When support for 'namespace' keyword was added for the 'default-server'
directive in 22f41a2 ("MINOR: server: Make 'default-server' support
'namespace' keyword."), we forgot to copy the attribute from the parent
to the newly created server.

This resulted in the 'namespace' keyword being parsed without errors when
used from a 'default-server' directive, but in practise the option was
simply ignored.

There's no need to duplicate the netns struct because it is stored in
a shared list, so copying the pointer does the job.

This patch partially fixes GH #2038 and should be backported to all
stable versions.

2 years agoBUG/MINOR: quic: Address inversion in "show quic full"
Frédéric Lécaille [Wed, 14 Jun 2023 07:17:20 +0000 (09:17 +0200)] 
BUG/MINOR: quic: Address inversion in "show quic full"

The local address was dumped as "from" address by dump_quic_full() and
the peer address as "to" address. This patch fixes this issue.

Furthermore, to support the server side (QUIC client) to come, it is preferable
to stop using "from" and "to" labels to dump the local and peer addresses which
is confusing for a QUIC client which uses its local address as "from" address.

To mimic netstat, this is "Local Address" and "Foreign Address" which will
be displayed by "show quic" CLI command and "local_addr" and "foreign_addr"
for "show quic full" command to mention the local addresses and the peer
addresses.

Must be backported as far as 2.7.

2 years agoBUG/MINOR: quic: Wrong encryption level flags checking
Frédéric Lécaille [Wed, 14 Jun 2023 06:54:51 +0000 (08:54 +0200)] 
BUG/MINOR: quic: Wrong encryption level flags checking

This bug arrived with this commit which was supposed to fix another one:

     BUG/MINOR: quic: Wrong Application encryption level selection when probing

The aim of this patch was to prevent the Application encryption to be selected
when probing leading to ACK only packets to be sent if the ack delay timer
had fired in the meantime, leading to crashes when no 01-RTT had been sent
because the ack range tree is empty in this case.

This statement is not correct (qc->pktns->flags & QUIC_FL_PKTNS_PROBE_NEEDED)
because qc->pktns is an array of packet number space. But it is equivalent
to (qc->pktns[QUIC_TLS_PKTNS_INITIAL].flags & QUIC_FL_PKTNS_PROBE_NEEDED).

That said, the patch mentionned above is not more useful since this following
which disable the ack time during the handshakes:

    BUG/MINOR: quic: Do not use ack delay during the handshakes

This commit revert the first patch mentionned above.

Must be backported as far as 2.6.

2 years agoBUG/MINOR: ssl: log message non thread safe in SSL Hanshake failure
William Lallemand [Mon, 12 Jun 2023 14:23:29 +0000 (16:23 +0200)] 
BUG/MINOR: ssl: log message non thread safe in SSL Hanshake failure

It was reported in issue #2181, strange behavior during the new SSL
hanshake failure logs.

Errors were logged with the code 0, which is unknown to OpenSSL.

This patch mades 2 changes:

- It stops using ERR_error_string() when the SSL error code is 0
- It uses ERR_error_string_n() to be thread-safe

Must be backported to 2.8.

2 years agoBUG/MEDIUM: hlua: Use front SC to detect EOI in HTTP applets' receive functions
Christopher Faulet [Mon, 12 Jun 2023 07:16:27 +0000 (09:16 +0200)] 
BUG/MEDIUM: hlua: Use front SC to detect EOI in HTTP applets' receive functions

When an HTTP applet tries to get request data, we must take care to properly
detect the end of the message. It an empty HTX message with the SC_FL_EOI
flag set on the front SC. However, an issue was introduced during the SC
refactoring performed in the 2.8. The backend SC is tested instead of the
frontend one.

Because of this bug, the receive functions hang because the test on
SC_FL_EOI flag never succeeds. Of course, by checking the frontend SC (the
opposite SC to the one attached to the appctx), it works.

This patch should fix the issue #2180. It must be backported to the 2.8.

2 years agoBUG/MINOR: proxy/server: free default-server on deinit
Aurelien DARRAGON [Thu, 1 Jun 2023 10:07:43 +0000 (12:07 +0200)] 
BUG/MINOR: proxy/server: free default-server on deinit

proxy default-server is a specific type of server that is not allocated
using new_server(): it is directly stored within the parent proxy
structure. However, since it may contain some default config options that
may be inherited by regular servers, it is also subject to dynamic members
(strings, structures..) that needs to be deallocated when the parent proxy
is cleaned up.

Unfortunately, srv_drop() may not be used directly from p->defsrv since
this function is meant to be used on regular servers only (those created
using new_server()).

To circumvent this, we're splitting srv_drop() to make a new function
called srv_free_params() that takes care of the member cleaning which
originally takes place in srv_drop(). This function is exposed through
server.h, so it may be called from outside server.c.

Thanks to this, calling srv_free_params(&p->defsrv) from free_proxy()
prevents any memory leaks due to dynamic parameters allocated when
parsing a default-server line from a proxy section.

This partially fixes GH #2173 and may be backported to 2.8.

[While it could also be relevant for other stable versions, the patch
won't apply due to architectural changes / name changes between 2.4 => 2.6
and then 2.6 => 2.8. Considering this is a minor fix that only makes
memory analyzers happy during deinit paths (at least for <= 2.8), it might
not be worth the trouble to backport them any further?]

2 years agoBUG/MINOR: proxy: add missing interface bind free in free_proxy
Aurelien DARRAGON [Thu, 1 Jun 2023 08:58:44 +0000 (10:58 +0200)] 
BUG/MINOR: proxy: add missing interface bind free in free_proxy

bind->settings.interface hint is allocated when "interface" keyword
is specified on a bind line, but the string isn't explicitly freed in
proxy_free, resulting in minor memory leak on deinit paths when the
keyword is being used.

It partially fixes GH #2173 and may be backported to all stable versions.

[in 2.2 free_proxy did not exist so the patch must be applied directly
in deinit() function from haproxy.c]

2 years agoBUG/MINOR: cfgparse-tcp: leak when re-declaring interface from bind line
Aurelien DARRAGON [Thu, 1 Jun 2023 07:57:15 +0000 (09:57 +0200)] 
BUG/MINOR: cfgparse-tcp: leak when re-declaring interface from bind line

When interface keyword is used multiple times within the same bind line,
the previous value isn't checked and is rewritten as-is, resulting in a
small memory leak.

Ensuring the interface name is first freed before assigning it to a new
value.

This may be backported to every stable versions.

[Note for 2.2, the fix must be performed in bind_parse_interface() from
proto_tcp.c, directly within the listener's loop, also ha_free() was
not available so free() must be used instead]

2 years agoDOC: config: fix rfc7239 converter examples (again)
Aurelien DARRAGON [Fri, 2 Jun 2023 13:29:17 +0000 (15:29 +0200)] 
DOC: config: fix rfc7239 converter examples (again)

Complementary fix to ac456ab ("DOC: config: fix rfc7239 converter examples")
since somehow I managed to overlook one example..

This needs to be backported in 2.8 with ac456ab.

2 years agoDOC: config: fix jwt_verify() example using var()
Aurelien DARRAGON [Fri, 26 May 2023 12:29:58 +0000 (14:29 +0200)] 
DOC: config: fix jwt_verify() example using var()

To prevent bogus matches, var() does not default to string type anymore
since 44c5ff6 ("MEDIUM: vars: make the var() sample fetch function really
return type ANY).

Thanks to the above fix, haproxy now returns an error if var() is used
within an ACL or IF condition and the matching type is not explicitly
set.

However, the documentation was not updated to reflect this change.

This partially fixes GH #2087 and must be backported up to 2.6.

2 years agoDOC: quic: fix misspelled tune.quic.socket-owner
Artur Pydo [Tue, 6 Jun 2023 09:49:59 +0000 (11:49 +0200)] 
DOC: quic: fix misspelled tune.quic.socket-owner

Commit 511ddd5 introduced tune.quic.socket-owner parameter related to
QUIC socket behaviour. However it was misspelled in configuration.txt in
'bind' section as tune.quic.conn-owner.

2 years agoREG-TESTS: stickiness: Delay haproxys start to properly resolv variables
Christopher Faulet [Mon, 5 Jun 2023 06:09:40 +0000 (08:09 +0200)] 
REG-TESTS: stickiness: Delay haproxys start to properly resolv variables

Because of the commit 5cb8d7b8f ("BUG/MINOR: peers: Improve detection of
config errors in peers sections"), 2 scripts now report errors during
startup because some variables are not set and the remote peer server is
thus malformed. To perform a peer synchro between 2 haproxys in these
scripts, the startup must be delayed to properly resolve addresses.

In addidiotn, we must wait (2s) to be sure the connection between peers is
properly established. These scripts are now flagged as slow.