Debian Patches

Status for haproxy/3.0.11-1+deb13u3

Patch Description Author Forwarded Bugs Origin Last update
haproxy.service-start-after-syslog.patch Start after rsyslog.service
As HAProxy is running chrooted by default, we rely on an additional syslog
socket created by rsyslog inside the chroot for logging. As this socket cannot
trigger syslog activation, we explicitly order HAProxy after rsyslog.service.
Note that we are not using syslog.service here, since the additional socket is
rsyslog-specific.
Apollon Oikonomopoulos <apoikos@debian.org> no 2017-12-01
haproxy.service-add-documentation.patch Add documentation field to the systemd unit Debian HAProxy Maintainers no 2014-01-03
haproxy.service-make-systemd-bind-dev-log-inside-chroot.patch haproxy.service: make systemd bind /dev/log inside chroot
This enables logging to work without rsyslog being present.
Vincent Bernat <bernat@debian.org> no 2021-11-25
reproducible.patch diff --git a/Makefile b/Makefile
index 566bdb26a3e7..8603dea25c21 100644
no
cross.patch no
0001-BUG-CRITICAL-mjson-fix-possible-DoS-when-parsing-num.patch BUG/CRITICAL: mjson: fix possible DoS when parsing numbers
Mjson comes with its own strtod() implementation for portability
reasons and probably also because many generic strtod() versions as
provided by operating systems do not focus on resource preservation
and may call malloc(), which is not welcome in a parser.

The strtod() implementation used here apparently originally comes from
https://gist.github.com/mattn/1890186 and seems to have purposely
omitted a few parts that were considered as not needed in this context
(e.g. skipping white spaces, or setting errno). But when subject to the
relevant test cases of the designated file above, the current function
provides the same results.

The aforementioned implementation uses pow() to calculate exponents,
but mjson authors visibly preferred not to introduce a libm dependency
and replaced it with an iterative loop in O(exp) time. The problem is
that the exponent is not bounded and that this loop can take a huge
amount of time. There's even an issue already opened on mjson about
haproxy, fortunately, the watchdog will quickly stop a runaway process
but this remains a possible denial of service.

A first approach would consist in reintroducing pow() like in the
original implementation, but if haproxy is built without Lua nor
51Degrees, -lm is not used so this will not work everywhere.

Anyway here we're dealing with integer exponents, so an easy alternate
approach consists in simply using shifts and squares, to compute the
exponent in O(log(exp)) time. Not only it doesn't introduce any new
dependency, but it turns out to be even faster than the generic pow()
(85k req/s per core vs 83.5k on the same machine).

This must be backported as far as 2.4, where mjson was introduced.

Many thanks to Oula Kivalo for reporting this issue.
Willy Tarreau <w@1wt.eu> no 2025-09-29
0001-BUG-MAJOR-quic-reject-invalid-token.patch [PATCH 1/2] BUG/MAJOR: quic: reject invalid token
Token parsing code on INITIAL packet for the NEW_TOKEN format is not
robust enough and may even crash on some rare malformed packets.

This patch fixes this by adding a check on the expected length of the
received token. The packet is now rejected if the token does not match
QUIC_TOKEN_LEN. This check is legitimate as haproxy should only parse
tokens emitted by itself.

This issue has been introduced with the implementation of NEW_TOKEN
tokens parsing required for 0-RTT support.

This must be backported up to 3.0.
Amaury Denoyelle <adenoyelle@haproxy.com> no 2026-02-09
0001-BUG-MAJOR-h3-check-body-size-with-content-length-on-.patch BUG/MAJOR: h3: check body size with content-length on empty FIN
In QUIC, a STREAM frame may be received with no data but with FIN bit
set. This situation is tedious to handle and haproxy parsing code has
changed several times to deal with this situation. Now, H3 and H09
layers parsing code are skipped in favor of the shared function
qcs_http_handle_standalone_fin() used to handle the HTX EOM emission.

However, this shortcut bypasses an important HTTP/3 validation check on
the received body size vs the announced content-length header. Under
some conditions, this could cause a desynchronization with the backend
server which could be exploited for request smuggling.

Fix HTTP/3 parsing code by adding a call to h3_check_body_size() prior
to qcs_http_handle_standalone_fin() if content-length header has been
found. If the body size is incorrect, the stream is immediately resetted
with H3_MESSAGE_ERROR code and the error is forwarded to the stream
layer.

Thanks to Martino Spagnuolo for his detailed report on this issue and
for having contacting us about it via the security mailing list.

This must be backported up to 2.6.

(cherry picked from commit 05a295441c621089ffa4318daf0dbca2dd756a84)
(cherry picked from commit 18e450ab412fb9397da36f226db8eed31ab590b6)
(cherry picked from commit 7ab4ae974c434e62896b3c68b7b485b9dceb7a25)
[ad: remove usage of qcs_http_handle_standalone_fin() introduced in 3.2]
(cherry picked from commit ae54ad97c84cd6173f134c1f052a5375cf704f5c)
Amaury Denoyelle <adenoyelle@haproxy.com> no https://git.haproxy.org/?p=haproxy-3.0.git;a=commit;h=425b969d6ea4114f4ae260f57802c65ccafc319c 2026-03-18
0001-BUG-MAJOR-slz-always-make-sure-to-limit-fixed-output.patch BUG/MAJOR: slz: always make sure to limit fixed output to less than worst case literals

Literals are sent in two ways:
- in EOB state, unencoded and prefixed with their length
- in FIXED state, huffman-encoded

And references are only sent in FIXED state.

The API promises that the amount of data will not grow by more than
5 bytes every 65535 input bytes (the comment was adjusted to remind
this last point). This is guaranteed by the literal encoding in EOB
state (BT, LEN, NLEN + bytes), which is supposed to be the worst
case by design.

However, as reported by Greg KH, this is currently not true: the test
that decides whether or not to switch to FIXED state to send references
doesn't properly account for the number of bytes needed to roll back
to the *exact* same state in EOB, which means sending EOB, BT,
alignment, LEN and NLEN in addition to the referenced bytes, versus
sending the encoding for the reference. By not taking into account the
cost of returning to the initial state (BT+LEN+NLEN), it was possible
to stay too long in the FIXED state and to consume the extra bytes that
are needed to return to the EOB state, resulting in producing much more
data in case of multiple switchovers (up to 6.25% increase was measured
in tests, or 1/16, which matches worst case estimates based on the code).

And this check is only valid when starting from EOB (in order to restore
the same state that offers this guarantee). When already in FIXED state,
the encoded reference is always smaller than or same size as the data.
The smallest match length we support is 4 bytes, and when encoded this
is no more than 28 bits, so it is safe to stay in FIXED state as long
as needed while checking the possibility of switching back to EOB.

This very slightly reduces the compression ratio (-0.17% on a linux
kernel source) but makes sure we respect the API promise of no more
than 5 extra bytes per 65535 of input. A side effect of the slightly
simpler check is an ~7.5% performance increase in compression speed.

Many thanks to Greg for the detailed report allowing to reproduce
the issue.

This is libslz upstream commit 002e838935bf298d967f670036efa95822b6c84e.

tune.maxrewrite 1024), this problem cannot be triggered, because the
reserve limits input to 15360 bytes, and the overflow is maximum
960 bytes resulting in 16320 bytes total, which still fits into the
buffer. However, reducing tune.maxrewrite below 964, or tune.bufsize
above 17408 can result in overflows for specially crafted patterns.

A workaround for larger buffers consists in always setting tune.bufsize
to at least 1/16 of tune.bufsize.

(cherry picked from commit 3020fde525896bc863fd2b6f43ac313f13a08dfa)
(cherry picked from commit 5ca993fabc3b8a91c35ab4f0fc8fa0b8e6763a36)
(cherry picked from commit fc11060263761ce4aa9aa9e3ed5036f6e0d7b107)
Willy Tarreau <w@1wt.eu> no 2026-04-08
0001-BUG-MAJOR-mux-h2-detect-incomplete-transfers-on-HEAD.patch BUG/MAJOR: mux-h2: detect incomplete transfers on HEADERS frames as well

Checks are already made on H2 to detect inconsistencies between
advertised content-length and transferred data (excess of data or
premature END_STREAM flag on DATA frame). However, as found by
Martino Spagnuolo (r3verii), a subtle case remains: if the END_STREAM
appears on the HEADERS frame (i.e. a regular request for example),
then the check is not made. In this case it is possible to advertise
more contents than will really be transferred. If the other side uses
HTTP/1.1, and the server responds before the end of the transfer,
this means that the number of advertised bytes that will never be
transferred and that the server will drain will be taken from the
next request, effectively hiding a part of the header.

In practice this can be used to force subsequent requests to fail, or
when running with "http-reuse never" or when running with a totally
idle server, to perform a request smuggling by constructing specially
crafted request pairs where the first one is used to trigger an early
response and hide parts of or all headers of the second one, to
instead use a second embedded one that was not subject to analysis.

The risk remains moderate given the low prevalence of "http-reuse never"
in production environments, and of idle servers.

The fix consists in detecting if advertised content-length remains when
processing an END_STREAM flag on a HEADERS frame. It also does it for
trailers, which turn out to be another way to abuse the bug. However it
takes great care not to break bodyless responses (204, 304 and responses
to HEAD requests) that may present a content-length that doesn't reflect
the presence of a body in the response.

A temporary alternative to the fix is to disable HTTP/2 by specifying
"alpn http/1.1" on "bind" lines, and adding "option disable-h2-upgrade"
in HTTP frontends.

This must be backported to all stable versions.

(cherry picked from commit d12edebe4af20b9cc14a21318d54925edba23b59)
(cherry picked from commit fbcd6382ff39f291125a38031fd95866e53e23f8)
(cherry picked from commit 97efe293bdfe3b8a9ba8beffbf61f22832a3773c)
[wt: drop the description in h2c_report_glitch() for 3.0]
Willy Tarreau <w@1wt.eu> no 2026-04-22
0001-BUG-MEDIUM-mux_h1-fix-stack-buffer-overflow-in-h1_ap.patch BUG/MEDIUM: mux_h1: fix stack buffer overflow in h1_append_chunk_size()

The char tmp[10] buffer can only hold 8 hex digits + CRLF suffix. If chksz
exceeds 4GB (0xFFFFFFFF), the do-while loop writes more than 8 hex digits,
overflowing the stack buffer by 1+ bytes. In practice the buffer is aligned
from the end and leaves a 6-byte hole before it on 64-bit systems, leaving
enough room to be harmless, and 4 on 32-bit platforms which save it from
touching lower variables. So it is safe but just by luck.

Fix by increasing tmp[] to 18 bytes, sufficient for up to 16 hex digits
(2^64 - 1) plus CRLF.

(cherry picked from commit 1ef74fc7cec12eba7daeef0b44f96b1ad4f5e127)
(cherry picked from commit 77f6a286fa18236d754f4986711495f36e0a0547)
(cherry picked from commit 54a4c294a9013620dfa7c5f7dc15bce27e87035d)
Willy Tarreau <w@1wt.eu> no 2026-04-26
0001-BUG-MAJOR-mux-h1-Deal-with-true-64-bits-integer-to-e.patch BUG/MAJOR: mux-h1: Deal with true 64-bits integer to emit chunks size

Functions emitting chunks size are using size_t integer to do so. Depending
on the code path, these functions can be called using an unsigned long long
integer (h1m->curr_len for instance). On 64-bits architectures, there is no
issue. But on the 32-bits architecture, it is a problem. size_t are 32-bits
integer so the 64-bits parameter will be casted to a 32-bits integer. For
chunk size exceeding 4GB, the wrong size will be emitted.

To fix the issue, these functions are now using true 64-bits
integer. h1s_consume_kop() was also modified accordingly.

In addition, when a size_t is compared to a 64-bits integer, an explicit
cast is used to be sure the right type is used.

This patch must be backported as far as 3.0. It must be backported after
1ef74fc7c ("BUG/MEDIUM: mux_h1: fix stack buffer overflow in
h1_append_chunk_size()").

(cherry picked from commit f9c2d476777be2a1cd15658071fb237822bb1699)
(cherry picked from commit 7fb16f949fb32a58ecad1754fcbe85520756df05)
[cf: h1s_consume_kop() does not exist on 3.2]
(cherry picked from commit 965c8430c3c735008240a6264e1b02b8cf65a004)
Christopher Faulet <cfaulet@haproxy.com> no 2026-04-28
0001-BUG-MEDIUM-mux-h2-fix-the-body_len-to-check-when-par.patch BUG/MEDIUM: mux-h2: fix the body_len to check when parsing request trailers

The h2 content-length validation in commit d12edebe4a ("BUG/MAJOR:
mux-h2: detect incomplete transfers on HEADERS frames as well") was
insufficient. The content-length check is still ineffective on request
trailers and it could not work by default due to the fact that the
default body_len is used in h2c_frt_handle_headers() when processing
trailers, instead of passing h2s->body_len, which was necessarily parsed
before reaching trailers. Let's fix this point first, otherwise fixing
the second issue would break trailers.

Many thanks to Pratham Gupta / alchemy1729 for spotting and analyzing
this problem, and for providing a lightweight reproducer to illustrate
the problem!

This fix must be backported to all versions where the fix above was
backported (i.e. all).

(cherry picked from commit b6995d25d1b694f52d1f23463532680b484c775f)
(cherry picked from commit 0f820337af9028b3c6f90d2ddc21f749ed71eb8f)
(cherry picked from commit ccff5a0314027763569c4ae19b53aa8f1a3c06ec)
[wt: ctx adj since no h2s_rxbuf_tail() etc in 3.0]
Willy Tarreau <w@1wt.eu> no 2026-05-04
0001-BUG-MAJOR-mux-h2-preset-MSGF_BODY_CL-on-H2_SF_DATA_C.patch BUG/MAJOR: mux-h2: preset MSGF_BODY_CL on H2_SF_DATA_CLEN in h2c_dec_hdrs()

Commit d12edebe4a ("BUG/MAJOR: mux-h2: detect incomplete transfers on
HEADERS frames as well") tried to enforce strict matching between
advertised content-length and transferred data when dealing with ES on
a headers frame. It purposely arranged the code so that it would cover
both headers and trailers. The problem is, in h2c_dec_hdrs() we preset
message flags (msgf) based on the current state and knowledge related
to the stream being processed, then we pass these flags to the headers
parser and use their final state to perform some extra checks.

MSGF_BODY_CL was set by the parsers themselves when processing a
content-length header, but when parsing a trailers frame, it will not
be set, and due to this the matching between the remaining expected
content-length and the transferred data is not verified, so the fix
above doesn't work for trailers.

This patch sets MSGF_BODY_CL to the same value as H2_SF_DATA_CLEN so
that during headers it remains zero, but it matches what was learned
during headers when processing trailers. It is sufficient to re-enable
the check that was attempted in the commit above.

The impact remains the same as the one indicated in the commit above: in
practice this can be used to force subsequent requests to fail, or when
running with "http-reuse never" or when running with a totally idle server,
to perform a request smuggling by constructing specially crafted request
pairs where the first one is used to trigger an early response and hide
parts of or all headers of the second one, to instead use a second
embedded one that was not subject to analysis. As such, the risk remains
moderate given the low prevalence of "http-reuse never" in production
environments, and of idle servers. Again, a temporary alternative to the
fix is to disable HTTP/2 by specifying "alpn http/1.1" on "bind" lines,
and adding "option disable-h2-upgrade" in HTTP frontends.

Many thanks to Pratham Gupta / alchemy1729 for spotting and analyzing
this problem, and for providing a lightweight reproducer to illustrate
the problem!

This fix must be backported to all versions where the fix above was
backported (i.e. all). Note that it depends on this previous commit
otherwise trailers will always break:

BUG/MEDIUM: mux-h2: fix the body_len to check when parsing request trailers

As a side note, it's worth noting that these temporary message flags have
reached a level of pain and fragility that really warrants a complete
rework. Ideally we should have a pair of such flags in the h2s (one per
direction) and the callers of the parsers should point to them so that
they are always up to date. And by having generic HTTP flags instead of
H2, we could better unify the h1/h2/h3/fcgi processors (and maybe avoid
some HTX conversion). One flag could even indicate that trailers are
being parsed (since they're last) so as to ease this detection down the
chain.

(cherry picked from commit 7e09e2a916af400f8cde8dabf649adf7fc1f6600)
(cherry picked from commit b532e29ae647e119cb10460e8f66e2ce30a0ddf7)
(cherry picked from commit 8c84aaec02e103e3ea3243975c4bca6a7f1b406a)
Willy Tarreau <w@1wt.eu> no 2026-05-04
0001-BUG-MEDIUM-h1-Enforce-the-authority-validation-durin.patch BUG/MEDIUM: h1: Enforce the authority validation during H1 request parsing

When a H1 request was parsed, only a light validation was performed on the
URI, mainly because there was no distinction between the different parts of
the URI. So only characters in the range [0x21, 0x7e], excluding the "#" was
allowed.

To be consistant with the H2 and H3 parser, the authority is now validated,
using http_authority_has_forbidden_char() function.

This patch should be backported as far as 2.8. For previous verions,
http_authority_has_forbidden_char() function does not exist.

(cherry picked from commit a46b0eec72e01dbbf436c8bd6917d9e4097ba8c3)
(cherry picked from commit 1ddde22216499a7d3cff4dcd29f7d72e3f9af9fb)
(cherry picked from commit 5c1a48d0f36d9848d8bf3a4403f08b2951d55e1a)
Christopher Faulet <cfaulet@haproxy.com> no 2026-04-28
0001-MINOR-http-add-a-function-to-validate-characters-of-.patch MINOR: http: add a function to validate characters of :authority

As discussed here:
https://github.com/httpwg/http2-spec/pull/936
https://github.com/haproxy/haproxy/issues/2941

It's important to take care of some special characters in the :authority
pseudo header before reassembling a complete URI, because after assembly
it's too late (e.g. the '/').

This patch adds a specific function which was checks all such characters
and their ranges on an ist, and benefits from modern compilers
optimizations that arrange the comparisons into an evaluation tree for
faster match. That's the version that gave the most consistent performance
across various compilers, though some hand-crafted versions using bitmaps
stored in register could be slightly faster but super sensitive to code
ordering, suggesting that the results might vary with future compilers.
This one takes on average 1.2ns per character at 3 GHz (3.6 cycles per
char on avg). The resulting impact on H2 request processing time (small
requests) was measured around 0.3%, from 6.60 to 6.618us per request,
which is a bit high but remains acceptable given that the test only
focused on req rate.

The code was made usable both for H2 and H3.

(cherry picked from commit ebab479cdf34255cd6162d2e843645f88b95327f)
(cherry picked from commit dcb963f9d777af39926e83f20e0a3c65c54f3bc0)
Willy Tarreau <w@1wt.eu> no 2025-05-12
0001-BUG-MEDIUM-h2-h3-reject-some-forbidden-chars-in-auth.patch BUG/MEDIUM: h2/h3: reject some forbidden chars in :authority before reassembly

As discussed here:
https://github.com/httpwg/http2-spec/pull/936
https://github.com/haproxy/haproxy/issues/2941

It's important to take care of some special characters in the :authority
pseudo header before reassembling a complete URI, because after assembly
it's too late (e.g. the '/'). This patch does this, both for h2 and h3.

The impact on H2 was measured in the worst case at 0.3% of the request
rate, while the impact on H3 is around 1%, but H3 was about 1% faster
than H2 before and is now on par.

It may be backported after a period of observation, and in this case it
relies on this previous commit:

MINOR: http: add a function to validate characters of :authority

Thanks to @DemiMarie for reviving this topic in issue #2941 and bringing
new potential interesting cases.

(cherry picked from commit 9a05c1f57490ba3adb378ad8e6e26830425514e7)
(cherry picked from commit 479befa356966c12a0a0ead74971750de4ac4499)
Willy Tarreau <w@1wt.eu> no 2025-05-12
0001-BUG-MEDIUM-h1-h2-h3-reject-forbidden-chars-in-the-Ho.patch BUG/MEDIUM: h1/h2/h3: reject forbidden chars in the Host header field

In continuation with 9a05c1f574 ("BUG/MEDIUM: h2/h3: reject some
forbidden chars in :authority before reassembly") and the discussion
in issue #2941, @DemiMarie rightfully suggested that Host should also
be sanitized, because it is sometimes used in concatenation, such as
this:

http-request set-url https://%[req.hdr(host)]%[pathq]

which was proposed as a workaround for h2 upstream servers that require
:authority here:

https://www.mail-archive.com/haproxy@formilux.org/msg43261.html

The current patch then adds the same check for forbidden chars in the
Host header, using the same function as for the patch above, since in
both cases we validate the host:port part of the authority. This way
we won't reconstruct ambiguous URIs by concatenating Host and path.

Just like the patch above, this can be backported afer a period of
observation.

(cherry picked from commit df00164fdd98d15e832daad34fb23249083bfb9c)
(cherry picked from commit 38ef948e754e4cab938f219349642c89cf0a79e6)
Willy Tarreau <w@1wt.eu> no 2025-05-16
0001-BUG-MAJOR-http-forbid-comma-character-in-authority-v.patch BUG/MAJOR: http: forbid comma character in authority value
Strictly speaking, the comma character in authority is allowed by RFC3986.
However, it is pretty ambiguous for Host header value because comma is also
the value separator for headers supporting multiple value. It is also very
unlikely to have comma in host header value or authority. So instead of
dealing with this case with all the risks of bugs that this entails, we've
decided to forbid the comma in authority and host header value during the
parsing. Concretely, only http_authority_has_forbidden_char() was updated.

The internal API was not updated to prevent comma to be inserted when the
host header value is updated for instance. But this should be so uncommon
that it is not really a concern.

This patch should be backported as far as 2.8. For previous verions,
http_authority_has_forbidden_char() function does not exist.

(cherry picked from commit b743b566b4215ed49b95d2fc22054ffe66202a0f)
(cherry picked from commit ec5d64fff23b1a10364b353d00f4995661b3a8be)
(cherry picked from commit 9354d90142d3673c1b4d27b9d81124102c3f8aa4)
Christopher Faulet <cfaulet@haproxy.com> no 2026-04-28
0001-BUG-MEDIUM-h1-Skip-all-h2c-values-from-Upgrade-heade.patch commit 8dd49dfabaf60f95da0387d0c0b5d4060dc28a6b

BUG/MEDIUM: h1: Skip all h2c values from Upgrade headers during parsing

During the H1 message parsing, the Upgrade header values are checked to
detect "h2c" and "h2" tokens and skip them. To do so, we rely on
H1_MF_UPG_H2C flag, set during the parsing. And during the request
post-parsing, if this flag was set, all Upgrade headers are removed.

This was fixed by the commit 7b89aa5b1 ("BUG/MINOR: h1: do not forward h2c
upgrade header token").

However, there are two issues here and the commit above must be refined.
First, the flag is reset for each new Upgrade header. So "h2c" or "h2"
tokens will be properly detected if all tokens are set on the same Upgrade
header. But if splitted on several headers, previously detected tokens will
be hidden by a next ones.

Concretly, the following will be properly caught

Connection: upgrade
Upgrade: foo, h2c, bar

But then following not:

Connection: upgrade:
Upgrade: foo, h2c
Upgrade: bar

Then, when a "h2c" or "h2" token is finally reported, all Upgrade headers
are removed, regardless other tokens.

So, to fix the both issues, everything is now handled during the message
parsing by skipping "h2c" and "h2" tokens, rebuilding the Upgrade header
value without then offending tokens. The same was already performed for the
Connection header, to skip "keep-alive" and "close" value. So it is not a so
fancy change.

Thanks to this change, it is no longer necessary to handle H1_MF_UPG_H2C
during the request post-parsing. And in fact, this flag is no longer
necessary. So let's remove it too.

Thanks to Vincent55 for finding and reporting this.

This patch must be backported as far as 2.4.
diff --git a/include/haproxy/h1.h b/include/haproxy/h1.h
index b4e66908e..71579e030 100644
Christopher Faulet <cfaulet@haproxy.com> no 2026-05-18

All known versions for source package 'haproxy'

Links