Hi, HAProxy 2.6.17 was released on 2024/04/05. It added 108 new commits after version 2.6.16.
This maintenance version addresses a few issues discovered after previous release: - an API issue with OpenSSL. The SSL_do_handshake() function returns SSL_ERROR_WANT_READ when it needs more data, but in certain obscure circumstances related to internal error handling, it was found that it may stop trying to read available data and continue to return that status! This results in wakeup loops that prevent the process from sleeping, hence it consumes 100% of the CPU (but it's still working fine). The code does what the doc suggests (but the doc is basically a one-liner), and neither aws-lc nor wolfSSL exhibit this problem. - applets: incompletely initialized client applets (due to setup error for example) could cause a crash due to calling the regular release code that's not meant to be used on such entities. Better deal with stricter low-level freeing code instead. - "option redispatch 0" is documented as disabling redispatch on server connection failure except that it caused it to redispatch at every retry. This was fixed. Note that "no option redispatch" would properly work though. - lua: preparing a socket without ever connecting it would lead to that socket not being garbage-collected when the task leaves, possibly waking it up in a partially initialized state resulting in a leak or a crash. Now the GC takes care of releasing uninitialized applets in this case. This was part of GitHub issue #2451. Another issue related to Lua sockets is if the Lua script does not consume data that arrives on a socket because it's busy doing something else, this could waste CPU cycles in endless wakeups until the data is consumed. A subtle locking issue was addressed around exception handling, where the exception code is called with locks released so that code should not try to access stack information. And similarly some code locations were called without the lock when resuming using hlua_ctx_resume(), possibly accessing the stack without any protection. These locking issues could cause crashes as shown in GitHub issue #2467. An previous attempt at addressing mixed usage of "lua-load" and "lua-load-per-thread" from the same stream overlooked the case of Lua filters which were still not covered. A different approach was taken this time and this fix was revisited. A few other cases of possible crashes in Lua filters were addressed. - dynamic servers: despite the various checks in srv_check_for_deletion(), there remained cases where "del server" could delete a server still referenced in streams (e.g. private connections) thus causing a crash when that stream is released. If the stats applet was aborted while interrupted on a dynamic server, that server's refcount wasn't decremented and the server could no longer be removed. The use of the "enabled" keyword when adding a server is currently forbidden but was silently ignored. - server: the "interface" keyword was ignored from "default-server" directives since "source" was taken from there. - fcgi: empty chunked messages on the request path were not properly handled, the stdin record was missing while an empty one ought to have been sent. This may happen when sending POST requests with no payload. - quic: Some harmless but latent issues were also fixed (e.g. proxy protocol configuration, connection possibly being closed before streams, some invalid QPACK instructions being silently ignored, rejection of some server-only frames received by the server, or unknown frame types). If multiple bind addresses are set on a listener, a warning will be emitted because this setup cannot reliably work (e.g. if reaching the machine via multiple addresses). - h3: a possible crash in the QPACK encoder when encoding HTTP/3 responses carrying status codes above 599. - h1: the HTTP/1 chunk and header parsers were strengthened a bit. Indeed, Ben Kallus kindly reminded us that we would still accept the NUL byte in header values and plain LF in chunks, while we were (wrongly) quite certain that these had long been rejected. Ben is currently not aware of situations where this could help convey an attack to any existing component, but given the surprises he certainly faces in his reviews, it's probably only a matter of time before one implementation shows to be too weak and we fail to properly protect it. So it was better to address both at once. In the extremely unlikely case that anyone would discover such an invalid byte on their network with an application that heavily relies on it, *option accept-invalid-http* will work as usual to bypass the check. We'll backport that to older versions as well, and I think it would be prudent for distros to take that as well. - spoe: in some cases, the expiration date could be reset, leading to a non-expirable stream. There could also be a wakeup loop when receiving too small a frame because it was ignored but not consumed instead of raising an error. Also, upon reload, applets that were waiting for a response would stick to idle mode and postpone the release of the old process. Now it's tested again, as well as on any subsequent attempt to use the idle connection. - listener: in some cases it would be possible to refrain from waking up a listener that was previously subject to a rate limit condition, and if that was the last session on the listener, nothing would later wake it up again, leaving a listener in a state where it no longer accepts any traffic, as reported in GitHub issue 2476. - idle conns: a private backend connections could crash in H2 if a new list head cannot be allocated during session_add_conn() because that would leave a NULL owner that is used later on. In practice it should only be reproducible under extremely low memory condition. - random algo: when "balance random" is used, each thread uses its own pseudo-random generator. But for historical (read: stupid) reasons, that PRNG used to be seeded only by the thread number. Given that at low loads, incoming connections are assigned to threads in round robin mode, it resulted in the first server of the farm always being used first after a reload. Usually that's not an issue, until users restart every second or so while running at low loads. The seeding was fixed so as to properly support this condition as well. - a rare deadlock was found on the pools code, it can be triggered at stopping time and crash the old process. It's been there since 2.5, and is difficult to trigger, but a user faced it and that's how we learned about it (GH issue #2427, thanks to user @JB0925). - an interesting arch-specific bug in the JWT parser: by initializing a 64-bit variable a bit too early, everything was fine on 64-bit platforms, but on 32-bit ones, a pointer located closer to the beginning of the structure got reset by this initialization before it was used, causing a crash! The fact this was only noticed now by running VTest on a 32-bit platform just shows that 32-bit users are less common these days and that their configs are probably simple enough not to use JWT ;) - there was a memroy leak when a proxy was freed if a use_backend rule was based on an expression. - the status of agent checks is returned as-is in the stats CSV output, resulting in mangling the CLI's output if it contains line feeds. It has been there since 2.0. - the previously backported aes_gcm_enc() converter could be subject to a small memory leak. - when deleting a crt-list line from the CLI, a dangling pointer reference could be left, with the possible effect of causing a crash. Apparently it has been the case since 2.4 so it seems that not that many people use "del ssl crt-list" or that the occurrence is quite rare. - Abhijeet Rastogi found that we still didn't recommend to the PCRE2 over PCRE that's no longer maintained. It was just an overlook and the doc was updated. - the diag warnings (enabled using -dD) were not all run when checking a config with "-c"! One would have to explicitly try to start the config to run the last ones. The only missing ones were the duplicate server cookie check. - and other lower importance fixes at various places, such as incorrect line location in certain error messages, etc. - doc updates, namely about the ciphersuite usage, and the CI updates (support for cache API v4, thanks to Tim). And that's about all. ############################################################################################# Please find the usual URLs below : Site index : https://www.haproxy.org/ Documentation : https://docs.haproxy.org/ Wiki : https://github.com/haproxy/wiki/wiki Discourse : https://discourse.haproxy.org/ Slack channel : https://slack.haproxy.org/ Issue tracker : https://github.com/haproxy/haproxy/issues Sources : https://www.haproxy.org/download/2.6/src/ Git repository : https://git.haproxy.org/git/haproxy-2.6.git/ Git Web browsing : https://git.haproxy.org/?p=haproxy-2.6.git Changelog : https://www.haproxy.org/download/2.6/src/CHANGELOG Dataplane API : https://github.com/haproxytech/dataplaneapi/releases/latest Pending bugs : https://www.haproxy.org/l/pending-bugs Reviewed bugs : https://www.haproxy.org/l/reviewed-bugs Code reports : https://www.haproxy.org/l/code-reports Latest builds : https://www.haproxy.org/l/dev-packages --- Complete changelog : Abhijeet Rastogi (1): DOC: install: recommend pcre2 Amaury Denoyelle (25): MINOR: h3: check connection error during sending BUG/MINOR: h3: close connection on header list too big BUG/MINOR: h3: properly handle alloc failure on finalize BUG/MINOR: h3: close connection on sending alloc errors BUG/MEDIUM: h3: fix incorrect snd_buf return value BUG/MEDIUM: h3: fix regression which completely prevents any send BUG/MINOR: mux-quic: do not prevent non-STREAM sending on flow control BUG/MINOR: h3: fix checking on NULL Tx buffer MINOR: quic: extract qc_stream_buf free in a dedicated function MINOR: h3: add traces for stream sending function BUG/MEDIUM: h3: do not crash on invalid response status code BUG/MEDIUM: qpack: allow 6xx..9xx status codes BUG/MEDIUM: quic: fix crash on invalid qc_stream_buf_free() BUG_ON BUG/MAJOR: promex: fix crash on deleted server BUG/MINOR: quic: reject unknown frame type BUG/MINOR: quic: reject HANDSHAKE_DONE as server BUG/MINOR: qpack: reject invalid increment count decoding BUG/MINOR: qpack: reject invalid dynamic table capacity MINOR: quic: warn on bind on multiple addresses if no IP_PKTINFO support BUG/MINOR: ist: allocate nul byte on istdup BUG/MINOR: stats: drop srv refcount on early release BUG/MAJOR: server: fix stream crash due to deleted server BUG/MINOR: session: ensure conn owner is set after insert into session BUG/MINOR: mux-quic: close all QCS before freeing QCC tasklet BUG/MINOR: server: ignore 'enabled' for dynamic servers Aurelien DARRAGON (19): MINOR: stats: store the parent proxy in stats ctx (http) BUG/MEDIUM: stats: unhandled switching rules with TCP frontend DEV: makefile: fix POSIX compatibility for "range" target BUG/MINOR: hlua: fix unsafe lua_tostring() usage with empty stack BUG/MINOR: hlua: don't use lua_tostring() from unprotected contexts BUG/MINOR: hlua: fix possible crash in hlua_filter_new() under load BUG/MINOR: hlua: improper lock usage in hlua_filter_callback() BUG/MINOR: hlua: improper lock usage in hlua_filter_new() BUG/MEDIUM: hlua: improper lock usage with SET_SAFE_LJMP() BUG/MAJOR: hlua: improper lock usage with hlua_ctx_resume() BUG/MINOR: cfgparse: report proper location for log-format-sd errors BUG/MINOR: hlua: segfault when loading the same filter from different contexts BUG/MINOR: hlua: missing lock in hlua_filter_new() BUG/MINOR: hlua: fix missing lock in hlua_filter_delete() BUG/MINOR: server: 'source' interface ignored from 'default-server' directive DEBUG: lua: precisely identify if stream is stuck inside lua or not MINOR: hlua: use accessors for stream hlua ctx BUG/MEDIUM: hlua: streams don't support mixing lua-load with lua-load-per-thread (2nd try) BUG/MINOR: proxy: fix logformat expression leak in use_backend rules Christopher Faulet (18): BUG/MEDIUM: mux-h2: Report too large HEADERS frame only when rxbuf is empty DOC: config: Update documentation about local haproxy response BUG/MEDIUM: stconn: Forward shutdown on write timeout only if it is forwardable BUG/MEDIUM: spoe: Never create new spoe applet if there is no server up BUG/MINOR: h1: Don't support LF only at the end of chunks BUG/MEDIUM: h1: Don't support LF only to mark the end of a chunk size BUG/MEDIUM: applet: Immediately free appctx on early error BUG/MEDIUM: hlua: Be able to garbage collect uninitialized lua sockets BUG/MEDIUM: hlua: Don't loop if a lua socket does not consume received data BUG/MINOR: hlua: Fix log level to the right value when set via TXN:set_loglevel MINOR: hlua: Be able to disable logging from lua BUG/MINOR: listener: Wake proxy's mngmt task up if necessary on session release BUG/MINOR: listener: Don't schedule frontend without task in listener_release() BUG/MEDIUM: spoe: Don't rely on stream's expiration to detect processing timeout BUG/MINOR: spoe: Be sure to be able to quickly close IDLE applets on soft-stop BUG/MEDIUM: spoe: Return an invalid frame on recv if size is too small BUG/MEDIUM: mux-fcgi: Properly handle EOM flag on end-of-trailers HTX block DOC: config: Remove httpclient.timeout.connect parameter Dragan Dosen (1): BUG/MINOR: ssl: fix possible ctx memory leak in sample_conv_aes_gcm() Emeric Brun (1): BUG/MEDIUM: cli: some err/warn msg dumps add LR into CSV output on stat's CLI Frederic Lecaille (9): CLEANUP: quic: Remove unused CUBIC_BETA_SCALE_FACTOR_SHIFT macro. MINOR: quic: Stop hardcoding a scale shifting value (CUBIC_BETA_SCALE_FACTOR_SHIFT) BUG/MINOR: quic: Wrong ack ranges handling when reaching the limit. CLEANUP: quic: Code clarifications for QUIC CUBIC (RFC 9438) BUG/MINOR: quic: fix possible integer wrap around in cubic window calculation MINOR: quic: Stop using 1024th of a second. BUG/MEDIUM: quic: Wrong K CUBIC calculation. MINOR: quic: Update K CUBIC calculation (RFC 9438) MINOR: quic: Dynamic packet reordering threshold Frédéric Lécaille (1): CLEANUP: quic: Remaining useless code into server part Ilia Shipitsin (1): CI: temporarily adjust kernel entropy to work with ASAN/clang Lukas Tribus (1): DOC: httpclient: add dedicated httpclient section Olivier Houchard (1): BUG/MAJOR: ssl_sock: Always clear retry flags in read/write functions Remi Tricot-Le Breton (2): BUG/MINOR: ssl: Clear the ckch instance when deleting a crt-list line REGTESTS: ssl: Fix empty line in cli command input Thayne McCombs (1): DOC: configuration: clarify http-request wait-for-body Tim Duesterhus (1): CI: Update to actions/cache@v4 William Lallemand (8): BUG/MEDIUM: mworker: set the master variable earlier DOC: configuration: typo req.ssl_hello_type BUG/MINOR: mworker/cli: fix set severity-output support BUG/MINOR: resolvers: default resolvers fails when network not configured BUG/MINOR: ssl/cli: duplicate cleaning code in cli_parse_del_crtlist DOC: configuration: clarify ciphersuites usage BUG/MINOR: ssl/cli: typo in new ssl crl-file CLI description DOC: configuration: clarify ciphersuites usage (V2) Willy Tarreau (18): BUG/MEDIUM: connection: report connection errors even when no mux is installed BUG/MEDIUM: proxy: always initialize the default settings after init MINOR: compiler: add a new DO_NOT_FOLD() macro to prevent code folding MINOR: debug: make sure calls to ha_crash_now() are never merged MINOR: debug: make ABORT_NOW() store the caller's line number when using abort MINOR: debug: make BUG_ON() catch build errors even without DEBUG_STRICT BUG/MINOR: vars/cli: fix missing LF after "get var" output BUG/MINOR: jwt: fix jwt_verify crash on 32-bit archs BUG/MEDIUM: pool: fix rare risk of deadlock in pool_flush() BUG/MINOR: h1-htx: properly initialize the err_pos field BUG/MEDIUM: h1: always reject the NUL character in header values BUG/MINOR: diag: run the final diags before quitting when using -c BUILD: address a few remaining calloc(size, n) cases DOC: internal: update missing data types in peers-v2.0.txt DEV: makefile: add a new "range" target to iteratively build all commits BUG/MINOR: ist: only store NUL byte on succeeded alloc BUG/MINOR: tools: seed the statistical PRNG slightly better BUG/MINOR: backend: properly handle redispatch 0 -- Christopher Faulet