From 512411108ce28a3cdf36af3abb4b66d41157e7fd Mon Sep 17 00:00:00 2001 From: Christian Lachner Date: Thu, 31 Jan 2019 13:59:35 +0100 Subject: [PATCH] haproxy: Update all patches for HAProxy v1.8.17 - Add new patches (see https://www.haproxy.org/bugs/bugs-1.8.17.html) - Raise PKG_RELEASE to 2 - Prefix patches with 3-digit numbers instead of 4-digit numbers Signed-off-by: Christian Lachner --- net/haproxy/Makefile | 2 +- net/haproxy/get-latest-patches.sh | 2 +- ...ponse-cache-store-expects-cache-name.patch | 38 +++++++ ...een-zero-and-uninitialized-cache-key.patch | 91 ++++++++++++++++ ...rotection-and-set-max-data-with-0RTT.patch | 32 ++++++ ...out-allow-0rtt-security-implications.patch | 32 ++++++ ...-failure-checks-loading-tls-key-file.patch | 77 ++++++++++++++ ...ram_name-as-a-hint-for-BE_LB_ALGO_PH.patch | 37 +++++++ ...ic-options-were-lost-across-defaults.patch | 49 +++++++++ ..._LB_LKUP_CHTREE-is-a-value-not-a-bit.patch | 100 ++++++++++++++++++ ...e-Prevent-conn_cur-from-underflowing.patch | 66 ++++++++++++ ...k_health-when-loading-a-server-state.patch | 67 ++++++++++++ ...he-check-is-finished-in-wake_srv_chk.patch | 43 ++++++++ ...ndling-of-TLS-1-3-KeyUpdate-messages.patch | 58 ++++++++++ ...of-nf_conntrack_tcp_loose-on-src-dst.patch | 50 +++++++++ ...ssl.patch => 013-deprecated-openssl.patch} | 12 +-- 16 files changed, 748 insertions(+), 8 deletions(-) create mode 100644 net/haproxy/patches/000-DOC-http-request-cache-use-http-response-cache-store-expects-cache-name.patch create mode 100644 net/haproxy/patches/001-BUG-MAJOR-cache-fix-confusion-between-zero-and-uninitialized-cache-key.patch create mode 100644 net/haproxy/patches/002-BUG-MEDIUM-ssl-Disable-anti-replay-protection-and-set-max-data-with-0RTT.patch create mode 100644 net/haproxy/patches/003-DOC-Be-a-bit-more-explicit-about-allow-0rtt-security-implications.patch create mode 100644 net/haproxy/patches/004-BUG-MEDIUM-ssl-missing-allocation-failure-checks-loading-tls-key-file.patch create mode 100644 net/haproxy/patches/005-BUG-MINOR-backend-dont-use-url_param_name-as-a-hint-for-BE_LB_ALGO_PH.patch create mode 100644 net/haproxy/patches/006-BUG-MINOR-backend-balance-uri-specific-options-were-lost-across-defaults.patch create mode 100644 net/haproxy/patches/007-BUG-MINOR-backend-BE_LB_LKUP_CHTREE-is-a-value-not-a-bit.patch create mode 100644 net/haproxy/patches/008-BUG-MINOR-stick_table-Prevent-conn_cur-from-underflowing.patch create mode 100644 net/haproxy/patches/009-BUG-MINOR-server-dont-always-trust-srv_check_health-when-loading-a-server-state.patch create mode 100644 net/haproxy/patches/010-BUG-MINOR-check-Wake-the-check-task-if-the-check-is-finished-in-wake_srv_chk.patch create mode 100644 net/haproxy/patches/011-BUG-MEDIUM-ssl-Fix-handling-of-TLS-1-3-KeyUpdate-messages.patch create mode 100644 net/haproxy/patches/012-DOC-mention-the-effect-of-nf_conntrack_tcp_loose-on-src-dst.patch rename net/haproxy/patches/{001-deprecated-openssl.patch => 013-deprecated-openssl.patch} (89%) diff --git a/net/haproxy/Makefile b/net/haproxy/Makefile index 7c61e7f9f..18dd7d46f 100644 --- a/net/haproxy/Makefile +++ b/net/haproxy/Makefile @@ -11,7 +11,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=haproxy PKG_VERSION:=1.8.17 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE:=haproxy-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://www.haproxy.org/download/1.8/src/ diff --git a/net/haproxy/get-latest-patches.sh b/net/haproxy/get-latest-patches.sh index a1aeb00e7..c6ed562cc 100755 --- a/net/haproxy/get-latest-patches.sh +++ b/net/haproxy/get-latest-patches.sh @@ -14,7 +14,7 @@ find ${PATCHESDIR} -type f -name "*.patch" -exec rm -f "{}" \; i=0 for cid in $(git -C "${TMP_REPODIR}" rev-list ${BASE_TAG}..HEAD | tac); do - filename="$(printf "%04d" $i)-$(git -C "${TMP_REPODIR}" log --format=%s -n 1 $cid | sed -e"s/[()']//g" -e's/[^_a-zA-Z0-9+-]\+/-/g' -e's/-$//').patch" + filename="$(printf "%03d" $i)-$(git -C "${TMP_REPODIR}" log --format=%s -n 1 $cid | sed -e"s/[()']//g" -e's/[^_a-zA-Z0-9+-]\+/-/g' -e's/-$//').patch" printf "Creating ${filename}\n" git -C "${TMP_REPODIR}" show $cid > "${PATCHESDIR}/$filename" git add "${PATCHESDIR}/$filename" diff --git a/net/haproxy/patches/000-DOC-http-request-cache-use-http-response-cache-store-expects-cache-name.patch b/net/haproxy/patches/000-DOC-http-request-cache-use-http-response-cache-store-expects-cache-name.patch new file mode 100644 index 000000000..01b9a8975 --- /dev/null +++ b/net/haproxy/patches/000-DOC-http-request-cache-use-http-response-cache-store-expects-cache-name.patch @@ -0,0 +1,38 @@ +commit 6648ff0cccee04a6a0c0e64050151b5d6c5bac51 +Author: Jarno Huuskonen +Date: Fri Jan 4 14:05:02 2019 +0200 + + DOC: http-request cache-use / http-response cache-store expects cache name + + Adds missing cache name option to http-request cache-use and + http-response cache-store documentation. + + Also adds optional if/unless condition to + 10.2.2. Proxy section: http-request cache-use / http-response cache-store + + (cherry picked from commit 251a6b72a8b6f0a4b167f6a2960e422d682aed80) + Signed-off-by: Willy Tarreau + (cherry picked from commit 5376f6af9239fdf8a79b6c912387de12e3c9d6cd) + [wla: no http-request/response section in 1.8] + Signed-off-by: William Lallemand + +diff --git a/doc/configuration.txt b/doc/configuration.txt +index 4f999e25..712e56e2 100644 +--- a/doc/configuration.txt ++++ b/doc/configuration.txt +@@ -17157,13 +17157,13 @@ max-age + 10.2.2. Proxy section + --------------------- + +-http-request cache-use ++http-request cache-use [ { if | unless } ] + Try to deliver a cached object from the cache . This directive is also + mandatory to store the cache as it calculates the cache hash. If you want to + use a condition for both storage and delivering that's a good idea to put it + after this one. + +-http-response cache-store ++http-response cache-store [ { if | unless } ] + Store an http-response within the cache. The storage of the response headers + is done at this step, which means you can use others http-response actions + to modify headers before or after the storage of the response. This action diff --git a/net/haproxy/patches/001-BUG-MAJOR-cache-fix-confusion-between-zero-and-uninitialized-cache-key.patch b/net/haproxy/patches/001-BUG-MAJOR-cache-fix-confusion-between-zero-and-uninitialized-cache-key.patch new file mode 100644 index 000000000..2a185a253 --- /dev/null +++ b/net/haproxy/patches/001-BUG-MAJOR-cache-fix-confusion-between-zero-and-uninitialized-cache-key.patch @@ -0,0 +1,91 @@ +commit a64e5574e40e3e0819c82e35a7e3d2fa65febc73 +Author: Willy Tarreau +Date: Fri Jan 11 19:38:25 2019 +0100 + + BUG/MAJOR: cache: fix confusion between zero and uninitialized cache key + + The cache uses the first 32 bits of the uri's hash as the key to reference + the object in the cache. It makes a special case of the value zero to mean + that the object is not in the cache anymore. The problem is that when an + object hashes as zero, it's still inserted but the eb32_delete() call is + skipped, resulting in the object still being chained in the memory area + while the block has been reclaimed and used for something else. Then when + objects which were chained below it (techically any object since zero is + at the root) are deleted, the walk through the upper object may encounter + corrupted values where valid pointers were expected. + + But while this should only happen statically once on 4 billion, the problem + gets worse when the cache-use conditions don't match the cache-store ones, + because cache-store runs with an uninitialized key, which can create objects + that will never be found by the lookup code, or worse, entries with a zero + key preventing eviction of the tree node and resulting in a crash. It's easy + to accidently end up on such a config because the request rules generally + can't be used to decide on the response : + + http-request cache-use cache if { path_beg /images } + http-response cache-store cache + + In this test, mixing traffic with /images/$RANDOM and /foo/$RANDOM will + result in random keys being inserted, some of them possibly being zero, + and crashes will quickly happen. + + The fix consists in 1) always initializing the transaction's cache_hash + to zero, and 2) never storing a response for which the hash has not been + calculated, as indicated by the value zero. + + It is worth noting that objects hashing as value zero will never be cached, + but given that there's only one chance among 4 billion that this happens, + this is totally harmless. + + This fix must be backported to 1.9 and 1.8. + + (cherry picked from commit c9036c00044a8d81561113886ecec9a9ce71bd3b) + Signed-off-by: Willy Tarreau + (cherry picked from commit 5a6279fcc16da479304bcabc1705e8653f274337) + Signed-off-by: William Lallemand + +diff --git a/src/cache.c b/src/cache.c +index 667cede3..3d8ed241 100644 +--- a/src/cache.c ++++ b/src/cache.c +@@ -400,7 +400,7 @@ enum act_return http_action_store_cache(struct act_rule *rule, struct proxy *px, + struct cache *cache = (struct cache *)rule->arg.act.p[0]; + struct shared_context *shctx = shctx_ptr(cache); + struct cache_entry *object; +- ++ unsigned int key = *(unsigned int *)txn->cache_hash; + + /* Don't cache if the response came from a cache */ + if ((obj_type(s->target) == OBJ_TYPE_APPLET) && +@@ -420,6 +420,10 @@ enum act_return http_action_store_cache(struct act_rule *rule, struct proxy *px, + if (txn->meth != HTTP_METH_GET) + goto out; + ++ /* cache key was not computed */ ++ if (!key) ++ goto out; ++ + /* cache only 200 status code */ + if (txn->status != 200) + goto out; +@@ -478,7 +482,7 @@ enum act_return http_action_store_cache(struct act_rule *rule, struct proxy *px, + + cache_ctx->first_block = first; + +- object->eb.key = (*(unsigned int *)&txn->cache_hash); ++ object->eb.key = key; + memcpy(object->hash, txn->cache_hash, sizeof(object->hash)); + /* Insert the node later on caching success */ + +diff --git a/src/proto_http.c b/src/proto_http.c +index 7e4a8351..29a1083a 100644 +--- a/src/proto_http.c ++++ b/src/proto_http.c +@@ -8210,6 +8210,7 @@ void http_init_txn(struct stream *s) + + txn->flags = 0; + txn->status = -1; ++ *(unsigned int *)txn->cache_hash = 0; + + txn->cookie_first_date = 0; + txn->cookie_last_date = 0; diff --git a/net/haproxy/patches/002-BUG-MEDIUM-ssl-Disable-anti-replay-protection-and-set-max-data-with-0RTT.patch b/net/haproxy/patches/002-BUG-MEDIUM-ssl-Disable-anti-replay-protection-and-set-max-data-with-0RTT.patch new file mode 100644 index 000000000..cd26ede28 --- /dev/null +++ b/net/haproxy/patches/002-BUG-MEDIUM-ssl-Disable-anti-replay-protection-and-set-max-data-with-0RTT.patch @@ -0,0 +1,32 @@ +commit 9f01534cd68de78c74b50d7b8def07a72c2a3b49 +Author: Olivier Houchard +Date: Wed Jan 2 18:46:41 2019 +0100 + + BUG/MEDIUM: ssl: Disable anti-replay protection and set max data with 0RTT. + + When using early data, disable the OpenSSL anti-replay protection, and set + the max amount of early data we're ready to accept, based on the size of + buffers, or early data won't work with the released OpenSSL 1.1.1. + + This should be backported to 1.8. + + (cherry picked from commit 51088ce68fee0bae52118d6823873417046f9efe) + Signed-off-by: Willy Tarreau + (cherry picked from commit 6703b633078b6bae12395ee3e310427b37965d68) + Signed-off-by: William Lallemand + +diff --git a/src/ssl_sock.c b/src/ssl_sock.c +index 24ccc4b1..11655533 100644 +--- a/src/ssl_sock.c ++++ b/src/ssl_sock.c +@@ -3821,6 +3821,10 @@ ssl_sock_initial_ctx(struct bind_conf *bind_conf) + SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk); + SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk); + #elif (OPENSSL_VERSION_NUMBER >= 0x10101000L) ++ if (bind_conf->ssl_conf.early_data) { ++ SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY); ++ SSL_CTX_set_max_early_data(ctx, global.tune.bufsize - global.tune.maxrewrite); ++ } + SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL); + SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk); + #else diff --git a/net/haproxy/patches/003-DOC-Be-a-bit-more-explicit-about-allow-0rtt-security-implications.patch b/net/haproxy/patches/003-DOC-Be-a-bit-more-explicit-about-allow-0rtt-security-implications.patch new file mode 100644 index 000000000..cd86868d0 --- /dev/null +++ b/net/haproxy/patches/003-DOC-Be-a-bit-more-explicit-about-allow-0rtt-security-implications.patch @@ -0,0 +1,32 @@ +commit aca7e5aed7e036489ccc83d925103e94653b8670 +Author: Olivier Houchard +Date: Tue Jan 8 15:35:32 2019 +0100 + + DOC: Be a bit more explicit about allow-0rtt security implications. + + Document a bit better than allow-0rtt can trivially be used for replay attacks, + and so should only be used when it's safe to replay a request. + + This should probably be backported to 1.8 and 1.9. + + (cherry picked from commit 69752964944ef9c8dc03477ee95bc7d149a72089) + Signed-off-by: Willy Tarreau + (cherry picked from commit bb0df71201ad5b2d0cec514773d244275e5240df) + Signed-off-by: William Lallemand + +diff --git a/doc/configuration.txt b/doc/configuration.txt +index 712e56e2..72b769a4 100644 +--- a/doc/configuration.txt ++++ b/doc/configuration.txt +@@ -10483,7 +10483,10 @@ accept-proxy + + allow-0rtt + Allow receiving early data when using TLSv1.3. This is disabled by default, +- due to security considerations. ++ due to security considerations. Because it is vulnerable to replay attacks, ++ you should only allow if for requests that are safe to replay, ie requests ++ that are idempotent. You can use the "wait-for-handshake" action for any ++ request that wouldn't be safe with early data. + + alpn + This enables the TLS ALPN extension and advertises the specified protocol diff --git a/net/haproxy/patches/004-BUG-MEDIUM-ssl-missing-allocation-failure-checks-loading-tls-key-file.patch b/net/haproxy/patches/004-BUG-MEDIUM-ssl-missing-allocation-failure-checks-loading-tls-key-file.patch new file mode 100644 index 000000000..e2cea9e3e --- /dev/null +++ b/net/haproxy/patches/004-BUG-MEDIUM-ssl-missing-allocation-failure-checks-loading-tls-key-file.patch @@ -0,0 +1,77 @@ +commit 30cd01cbfd40201f3abe246216a85c69352aa79c +Author: Emeric Brun +Date: Thu Jan 10 10:51:13 2019 +0100 + + BUG/MEDIUM: ssl: missing allocation failure checks loading tls key file + + This patch fixes missing allocation checks loading tls key file + and avoid memory leak in some error cases. + + This patch should be backport on branches 1.9 and 1.8 + + (cherry picked from commit 09852f70e0ed0f23cf9287b1ce55bb6a60112f32) + Signed-off-by: Willy Tarreau + (cherry picked from commit a1dc55a63cfbc8f440b72b6def3957bf1fad12b2) + Signed-off-by: William Lallemand + +diff --git a/src/ssl_sock.c b/src/ssl_sock.c +index 11655533..7884c411 100644 +--- a/src/ssl_sock.c ++++ b/src/ssl_sock.c +@@ -7627,15 +7627,36 @@ static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px + } + + keys_ref = malloc(sizeof(*keys_ref)); ++ if (!keys_ref) { ++ if (err) ++ memprintf(err, "'%s' : allocation error", args[cur_arg+1]); ++ return ERR_ALERT | ERR_FATAL; ++ } ++ + keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key)); ++ if (!keys_ref->tlskeys) { ++ free(keys_ref); ++ if (err) ++ memprintf(err, "'%s' : allocation error", args[cur_arg+1]); ++ return ERR_ALERT | ERR_FATAL; ++ } + + if ((f = fopen(args[cur_arg + 1], "r")) == NULL) { ++ free(keys_ref->tlskeys); ++ free(keys_ref); + if (err) + memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]); + return ERR_ALERT | ERR_FATAL; + } + + keys_ref->filename = strdup(args[cur_arg + 1]); ++ if (!keys_ref->filename) { ++ free(keys_ref->tlskeys); ++ free(keys_ref); ++ if (err) ++ memprintf(err, "'%s' : allocation error", args[cur_arg+1]); ++ return ERR_ALERT | ERR_FATAL; ++ } + + while (fgets(thisline, sizeof(thisline), f) != NULL) { + int len = strlen(thisline); +@@ -7647,6 +7668,9 @@ static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px + thisline[--len] = 0; + + if (base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(struct tls_sess_key)) != sizeof(struct tls_sess_key)) { ++ free(keys_ref->filename); ++ free(keys_ref->tlskeys); ++ free(keys_ref); + if (err) + memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1); + fclose(f); +@@ -7656,6 +7680,9 @@ static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px + } + + if (i < TLS_TICKETS_NO) { ++ free(keys_ref->filename); ++ free(keys_ref->tlskeys); ++ free(keys_ref); + if (err) + memprintf(err, "'%s' : please supply at least %d keys in the tls-tickets-file", args[cur_arg+1], TLS_TICKETS_NO); + fclose(f); diff --git a/net/haproxy/patches/005-BUG-MINOR-backend-dont-use-url_param_name-as-a-hint-for-BE_LB_ALGO_PH.patch b/net/haproxy/patches/005-BUG-MINOR-backend-dont-use-url_param_name-as-a-hint-for-BE_LB_ALGO_PH.patch new file mode 100644 index 000000000..24ba55c69 --- /dev/null +++ b/net/haproxy/patches/005-BUG-MINOR-backend-dont-use-url_param_name-as-a-hint-for-BE_LB_ALGO_PH.patch @@ -0,0 +1,37 @@ +commit 98f9549fa466e3b73a04f17dbc05fd88427c72f4 +Author: Willy Tarreau +Date: Mon Jan 14 15:17:46 2019 +0100 + + BUG/MINOR: backend: don't use url_param_name as a hint for BE_LB_ALGO_PH + + At a few places in the code we used to rely on this variable to guess + what LB algo was in place. This is wrong because if the defaults section + presets "balance url_param foo" and a backend uses "balance roundrobin", + these locations will still see this url_param_name set and consider it. + The harm is limited, as this only causes the beginning of the request + body to be buffered. And in general this is a bad practice which prevents + us from cleaning the lbprm stuff. Let's explicitly check the LB algo + instead. + + This may be backported to all currently maintained versions. + + (cherry picked from commit 089eaa0ba73913187e93d52c3ea34faa01fd8f9c) + Signed-off-by: Willy Tarreau + (cherry picked from commit 70d1744bb41daab4110071e4855504b6dc47bda9) + [wla: no htx in 1.8] + Signed-off-by: William Lallemand + +diff --git a/src/proto_http.c b/src/proto_http.c +index 29a1083a..5dc562ff 100644 +--- a/src/proto_http.c ++++ b/src/proto_http.c +@@ -3935,7 +3935,8 @@ int http_process_request(struct stream *s, struct channel *req, int an_bit) + * that parameter. This will be done in another analyser. + */ + if (!(s->flags & (SF_ASSIGNED|SF_DIRECT)) && +- s->txn->meth == HTTP_METH_POST && s->be->url_param_name != NULL && ++ s->txn->meth == HTTP_METH_POST && ++ (s->be->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_PH && + (msg->flags & (HTTP_MSGF_CNT_LEN|HTTP_MSGF_TE_CHNK))) { + channel_dont_connect(req); + req->analysers |= AN_REQ_HTTP_BODY; diff --git a/net/haproxy/patches/006-BUG-MINOR-backend-balance-uri-specific-options-were-lost-across-defaults.patch b/net/haproxy/patches/006-BUG-MINOR-backend-balance-uri-specific-options-were-lost-across-defaults.patch new file mode 100644 index 000000000..022998d97 --- /dev/null +++ b/net/haproxy/patches/006-BUG-MINOR-backend-balance-uri-specific-options-were-lost-across-defaults.patch @@ -0,0 +1,49 @@ +commit a5027f804144536f79829443b33e6c19c32b690a +Author: Willy Tarreau +Date: Mon Jan 14 16:29:52 2019 +0100 + + BUG/MINOR: backend: balance uri specific options were lost across defaults + + The "balance uri" options "whole", "len" and "depth" were not properly + inherited from the defaults sections. In addition, "whole" and "len" + were not even reset when parsing "uri", meaning that 2 subsequent + "balance uri" statements would not have the expected effect as the + options from the first one would remain for the second one. + + This may be backported to all maintained versions. + + (cherry picked from commit 602a499da5e81d6b4cfe8410f0fc6d53c1e06745) + Signed-off-by: Willy Tarreau + (cherry picked from commit f00758fde5961e3bebc508852faeee4d9d80b0e0) + [wla: cfg_parse_listen() is still in cfgparse.c in 1.8] + Signed-off-by: William Lallemand + +diff --git a/src/backend.c b/src/backend.c +index 87327f19..4c4044a6 100644 +--- a/src/backend.c ++++ b/src/backend.c +@@ -1516,6 +1516,8 @@ int backend_parse_balance(const char **args, char **err, struct proxy *curproxy) + curproxy->lbprm.algo |= BE_LB_ALGO_UH; + + curproxy->uri_whole = 0; ++ curproxy->uri_len_limit = 0; ++ curproxy->uri_dirs_depth1 = 0; + + while (*args[arg]) { + if (!strcmp(args[arg], "len")) { +diff --git a/src/cfgparse.c b/src/cfgparse.c +index 94f29637..91bb802e 100644 +--- a/src/cfgparse.c ++++ b/src/cfgparse.c +@@ -2844,7 +2844,10 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) + + if (defproxy.url_param_name) + curproxy->url_param_name = strdup(defproxy.url_param_name); +- curproxy->url_param_len = defproxy.url_param_len; ++ curproxy->url_param_len = defproxy.url_param_len; ++ curproxy->uri_whole = defproxy.uri_whole; ++ curproxy->uri_len_limit = defproxy.uri_len_limit; ++ curproxy->uri_dirs_depth1 = defproxy.uri_dirs_depth1; + + if (defproxy.hh_name) + curproxy->hh_name = strdup(defproxy.hh_name); diff --git a/net/haproxy/patches/007-BUG-MINOR-backend-BE_LB_LKUP_CHTREE-is-a-value-not-a-bit.patch b/net/haproxy/patches/007-BUG-MINOR-backend-BE_LB_LKUP_CHTREE-is-a-value-not-a-bit.patch new file mode 100644 index 000000000..96c83d052 --- /dev/null +++ b/net/haproxy/patches/007-BUG-MINOR-backend-BE_LB_LKUP_CHTREE-is-a-value-not-a-bit.patch @@ -0,0 +1,100 @@ +commit 7c6a6149a91d2e240a5a63f981c5d07d681df725 +Author: Willy Tarreau +Date: Mon Jan 14 17:07:39 2019 +0100 + + BUG/MINOR: backend: BE_LB_LKUP_CHTREE is a value, not a bit + + There are a few instances where the lookup algo is tested against + BE_LB_LKUP_CHTREE using a binary "AND" operation while this macro + is a value among a set, and not a bit. The test happens to work + because the value is exactly 4 and no bit overlaps with the other + possible values but this is a latent bug waiting for a new LB algo + to appear to strike. At the moment the only other algo sharing a bit + with it is the "first" algo which is never supported in the same code + places. + + This fix should be backported to maintained versions for safety if it + passes easily, otherwise it's not important as it will not fix any + visible issue. + + (cherry picked from commit 6c30be52da3d949a8dd6fb5e2de7319c031e656e) + Signed-off-by: Willy Tarreau + (cherry picked from commit 48147c424680b7e887fb176662d58d87baa16098) + Signed-off-by: William Lallemand + +diff --git a/src/backend.c b/src/backend.c +index 4c4044a6..0cf14cfd 100644 +--- a/src/backend.c ++++ b/src/backend.c +@@ -183,7 +183,7 @@ static struct server *get_server_sh(struct proxy *px, const char *addr, int len, + if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL) + h = full_hash(h); + hash_done: +- if (px->lbprm.algo & BE_LB_LKUP_CHTREE) ++ if ((px->lbprm.algo & BE_LB_LKUP) == BE_LB_LKUP_CHTREE) + return chash_get_server_hash(px, h, avoid); + else + return map_get_server_hash(px, h); +@@ -236,7 +236,7 @@ static struct server *get_server_uh(struct proxy *px, char *uri, int uri_len, co + if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL) + hash = full_hash(hash); + hash_done: +- if (px->lbprm.algo & BE_LB_LKUP_CHTREE) ++ if ((px->lbprm.algo & BE_LB_LKUP) == BE_LB_LKUP_CHTREE) + return chash_get_server_hash(px, hash, avoid); + else + return map_get_server_hash(px, hash); +@@ -293,7 +293,7 @@ static struct server *get_server_ph(struct proxy *px, const char *uri, int uri_l + if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL) + hash = full_hash(hash); + +- if (px->lbprm.algo & BE_LB_LKUP_CHTREE) ++ if ((px->lbprm.algo & BE_LB_LKUP) == BE_LB_LKUP_CHTREE) + return chash_get_server_hash(px, hash, avoid); + else + return map_get_server_hash(px, hash); +@@ -367,7 +367,7 @@ static struct server *get_server_ph_post(struct stream *s, const struct server * + if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL) + hash = full_hash(hash); + +- if (px->lbprm.algo & BE_LB_LKUP_CHTREE) ++ if ((px->lbprm.algo & BE_LB_LKUP) == BE_LB_LKUP_CHTREE) + return chash_get_server_hash(px, hash, avoid); + else + return map_get_server_hash(px, hash); +@@ -463,7 +463,7 @@ static struct server *get_server_hh(struct stream *s, const struct server *avoid + if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL) + hash = full_hash(hash); + hash_done: +- if (px->lbprm.algo & BE_LB_LKUP_CHTREE) ++ if ((px->lbprm.algo & BE_LB_LKUP) == BE_LB_LKUP_CHTREE) + return chash_get_server_hash(px, hash, avoid); + else + return map_get_server_hash(px, hash); +@@ -507,7 +507,7 @@ static struct server *get_server_rch(struct stream *s, const struct server *avoi + if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL) + hash = full_hash(hash); + hash_done: +- if (px->lbprm.algo & BE_LB_LKUP_CHTREE) ++ if ((px->lbprm.algo & BE_LB_LKUP) == BE_LB_LKUP_CHTREE) + return chash_get_server_hash(px, hash, avoid); + else + return map_get_server_hash(px, hash); +@@ -615,7 +615,7 @@ int assign_server(struct stream *s) + case BE_LB_LKUP_CHTREE: + case BE_LB_LKUP_MAP: + if ((s->be->lbprm.algo & BE_LB_KIND) == BE_LB_KIND_RR) { +- if (s->be->lbprm.algo & BE_LB_LKUP_CHTREE) ++ if ((s->be->lbprm.algo & BE_LB_LKUP) == BE_LB_LKUP_CHTREE) + srv = chash_get_next_server(s->be, prev_srv); + else + srv = map_get_server_rr(s->be, prev_srv); +@@ -691,7 +691,7 @@ int assign_server(struct stream *s) + * back to round robin on the map. + */ + if (!srv) { +- if (s->be->lbprm.algo & BE_LB_LKUP_CHTREE) ++ if ((s->be->lbprm.algo & BE_LB_LKUP) == BE_LB_LKUP_CHTREE) + srv = chash_get_next_server(s->be, prev_srv); + else + srv = map_get_server_rr(s->be, prev_srv); diff --git a/net/haproxy/patches/008-BUG-MINOR-stick_table-Prevent-conn_cur-from-underflowing.patch b/net/haproxy/patches/008-BUG-MINOR-stick_table-Prevent-conn_cur-from-underflowing.patch new file mode 100644 index 000000000..4e0d014b2 --- /dev/null +++ b/net/haproxy/patches/008-BUG-MINOR-stick_table-Prevent-conn_cur-from-underflowing.patch @@ -0,0 +1,66 @@ +commit 93b3994091b5bd17b43c9d91ecae470d33157e25 +Author: Tim Duesterhus +Date: Fri Jan 4 00:11:59 2019 +0100 + + BUG/MINOR: stick_table: Prevent conn_cur from underflowing + + When using the peers feature a race condition could prevent + a connection from being properly counted. When this connection + exits it is being "uncounted" nonetheless, leading to a possible + underflow (-1) of the conn_curr stick table entry in the following + scenario : + + - Connect to peer A (A=1, B=0) + - Peer A sends 1 to B (A=1, B=1) + - Kill connection to A (A=0, B=1) + - Connect to peer B (A=0, B=2) + - Peer A sends 0 to B (A=0, B=0) + - Peer B sends 0/2 to A (A=?, B=0) + - Kill connection to B (A=?, B=-1) + - Peer B sends -1 to A (A=-1, B=-1) + + This fix may be backported to all supported branches. + + (cherry picked from commit 8b87c01c4d59247d9fb51a38cd12d5d94324b6a4) + Signed-off-by: Willy Tarreau + (cherry picked from commit 4ceecc8a4ee6f46f20c7729056e14af5a8757121) + Signed-off-by: William Lallemand + +diff --git a/include/proto/session.h b/include/proto/session.h +index f48c0d4f..7265f5a7 100644 +--- a/include/proto/session.h ++++ b/include/proto/session.h +@@ -59,7 +59,8 @@ static inline void session_store_counters(struct session *sess) + if (ptr) { + HA_RWLOCK_WRLOCK(STK_SESS_LOCK, &ts->lock); + +- stktable_data_cast(ptr, conn_cur)--; ++ if (stktable_data_cast(ptr, conn_cur) > 0) ++ stktable_data_cast(ptr, conn_cur)--; + + HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock); + +diff --git a/include/proto/stream.h b/include/proto/stream.h +index 8521957e..c9bcac37 100644 +--- a/include/proto/stream.h ++++ b/include/proto/stream.h +@@ -104,7 +104,8 @@ static inline void stream_store_counters(struct stream *s) + if (ptr) { + HA_RWLOCK_WRLOCK(STK_SESS_LOCK, &ts->lock); + +- stktable_data_cast(ptr, conn_cur)--; ++ if (stktable_data_cast(ptr, conn_cur) > 0) ++ stktable_data_cast(ptr, conn_cur)--; + + HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock); + +@@ -142,7 +143,8 @@ static inline void stream_stop_content_counters(struct stream *s) + if (ptr) { + HA_RWLOCK_WRLOCK(STK_SESS_LOCK, &ts->lock); + +- stktable_data_cast(ptr, conn_cur)--; ++ if (stktable_data_cast(ptr, conn_cur) > 0) ++ stktable_data_cast(ptr, conn_cur)--; + + HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock); + diff --git a/net/haproxy/patches/009-BUG-MINOR-server-dont-always-trust-srv_check_health-when-loading-a-server-state.patch b/net/haproxy/patches/009-BUG-MINOR-server-dont-always-trust-srv_check_health-when-loading-a-server-state.patch new file mode 100644 index 000000000..f3de085a8 --- /dev/null +++ b/net/haproxy/patches/009-BUG-MINOR-server-dont-always-trust-srv_check_health-when-loading-a-server-state.patch @@ -0,0 +1,67 @@ +commit 1c95076d881b7508a8d0819b1cfd642e364b255c +Author: Jérôme Magnin +Date: Sun Jan 20 11:27:40 2019 +0100 + + BUG/MINOR: server: don't always trust srv_check_health when loading a server state + + When we load health values from a server state file, make sure what we assign + to srv->check.health actually matches the state we restore. + + This should be backported as far as 1.6. + + (cherry picked from commit f57afa453a685cfd92b7a27ef6e6035cb384ff57) + Signed-off-by: Willy Tarreau + (cherry picked from commit 75455a0b78ce4ac723698df26c014b38467843b1) + Signed-off-by: William Lallemand + +diff --git a/src/server.c b/src/server.c +index a86db3db..28414780 100644 +--- a/src/server.c ++++ b/src/server.c +@@ -2843,16 +2843,37 @@ static void srv_update_state(struct server *srv, int version, char **params) + HA_SPIN_LOCK(SERVER_LOCK, &srv->lock); + /* recover operational state and apply it to this server + * and all servers tracking this one */ ++ srv->check.health = srv_check_health; + switch (srv_op_state) { + case SRV_ST_STOPPED: + srv->check.health = 0; + srv_set_stopped(srv, "changed from server-state after a reload", NULL); + break; + case SRV_ST_STARTING: ++ /* If rise == 1 there is no STARTING state, let's switch to ++ * RUNNING ++ */ ++ if (srv->check.rise == 1) { ++ srv->check.health = srv->check.rise + srv->check.fall - 1; ++ srv_set_running(srv, "", NULL); ++ break; ++ } ++ if (srv->check.health < 1 || srv->check.health >= srv->check.rise) ++ srv->check.health = srv->check.rise - 1; + srv->next_state = srv_op_state; + break; + case SRV_ST_STOPPING: +- srv->check.health = srv->check.rise + srv->check.fall - 1; ++ /* If fall == 1 there is no STOPPING state, let's switch to ++ * STOPPED ++ */ ++ if (srv->check.fall == 1) { ++ srv->check.health = 0; ++ srv_set_stopped(srv, "changed from server-state after a reload", NULL); ++ break; ++ } ++ if (srv->check.health < srv->check.rise || ++ srv->check.health > srv->check.rise + srv->check.fall - 2) ++ srv->check.health = srv->check.rise; + srv_set_stopping(srv, "changed from server-state after a reload", NULL); + break; + case SRV_ST_RUNNING: +@@ -2906,7 +2927,6 @@ static void srv_update_state(struct server *srv, int version, char **params) + srv->last_change = date.tv_sec - srv_last_time_change; + srv->check.status = srv_check_status; + srv->check.result = srv_check_result; +- srv->check.health = srv_check_health; + + /* Only case we want to apply is removing ENABLED flag which could have been + * done by the "disable health" command over the stats socket diff --git a/net/haproxy/patches/010-BUG-MINOR-check-Wake-the-check-task-if-the-check-is-finished-in-wake_srv_chk.patch b/net/haproxy/patches/010-BUG-MINOR-check-Wake-the-check-task-if-the-check-is-finished-in-wake_srv_chk.patch new file mode 100644 index 000000000..a4eb897dd --- /dev/null +++ b/net/haproxy/patches/010-BUG-MINOR-check-Wake-the-check-task-if-the-check-is-finished-in-wake_srv_chk.patch @@ -0,0 +1,43 @@ +commit 7a74ffef9f356304b46ab862858cead85d451b5f +Author: Christopher Faulet +Date: Mon Jan 21 14:15:50 2019 +0100 + + BUG/MINOR: check: Wake the check task if the check is finished in wake_srv_chk() + + With tcp-check, the result of the check is set by the function tcpcheck_main() + from the I/O layer. So it is important to wake up the check task to handle the + result and finish the check. Otherwise, we will wait the task timeout to handle + the result of a tcp-check, delaying the next check by as much. + + This patch also fixes a problem about email alerts reported by PiBa-NL (Pieter) + on the ML [1] on all versions since the 1.6. So this patch must be backported + from 1.9 to 1.6. + + [1] https://www.mail-archive.com/haproxy@formilux.org/msg32190.html + + (cherry picked from commit 774c486cece942570b6a9d16afe236a16ee12079) + Signed-off-by: Willy Tarreau + (cherry picked from commit 3722dfbbfadf8f83f82feb3e67fbe482a5c94840) + Signed-off-by: William Lallemand + +diff --git a/src/checks.c b/src/checks.c +index 74958b2d..e04f1146 100644 +--- a/src/checks.c ++++ b/src/checks.c +@@ -1403,12 +1403,13 @@ static int wake_srv_chk(struct conn_stream *cs) + } + + if (check->result != CHK_RES_UNKNOWN) { +- /* We're here because nobody wants to handle the error, so we +- * sure want to abort the hard way. +- */ ++ /* Check complete or aborted. If connection not yet closed do it ++ * now and wake the check task up to be sure the result is ++ * handled ASAP. */ + conn_sock_drain(conn); + cs_close(cs); + ret = -1; ++ task_wakeup(check->task, TASK_WOKEN_IO); + } + + HA_SPIN_UNLOCK(SERVER_LOCK, &check->server->lock); diff --git a/net/haproxy/patches/011-BUG-MEDIUM-ssl-Fix-handling-of-TLS-1-3-KeyUpdate-messages.patch b/net/haproxy/patches/011-BUG-MEDIUM-ssl-Fix-handling-of-TLS-1-3-KeyUpdate-messages.patch new file mode 100644 index 000000000..6d9977881 --- /dev/null +++ b/net/haproxy/patches/011-BUG-MEDIUM-ssl-Fix-handling-of-TLS-1-3-KeyUpdate-messages.patch @@ -0,0 +1,58 @@ +commit b68a427a236e7b9b0cf8b1c4a5360d960cdf9458 +Author: Dirkjan Bussink +Date: Mon Jan 21 09:35:03 2019 -0800 + + BUG/MEDIUM: ssl: Fix handling of TLS 1.3 KeyUpdate messages + + In OpenSSL 1.1.1 TLS 1.3 KeyUpdate messages will trigger the callback + that is used to verify renegotiation is disabled. This means that these + KeyUpdate messages fail. In OpenSSL 1.1.1 a better mechanism is + available with the SSL_OP_NO_RENEGOTIATION flag that disables any TLS + 1.2 and earlier negotiation. + + So if this SSL_OP_NO_RENEGOTIATION flag is available, instead of having + a manual check, trust OpenSSL and disable the check. This means that TLS + 1.3 KeyUpdate messages will work properly. + + Reported-By: Adam Langley + (cherry picked from commit 526894ff3925d272c13e57926aa6b5d9d8ed5ee3) + [wt: gh issue #24; Needs to be backported till 1.8] + Signed-off-by: Willy Tarreau + (cherry picked from commit 062c5a190d50c4aa9c5bde88c8c5c85c5f15fc7b) + Signed-off-by: William Lallemand + +diff --git a/src/ssl_sock.c b/src/ssl_sock.c +index 7884c411..7736c324 100644 +--- a/src/ssl_sock.c ++++ b/src/ssl_sock.c +@@ -1406,6 +1406,10 @@ void ssl_sock_infocbk(const SSL *ssl, int where, int ret) + BIO *write_bio; + (void)ret; /* shut gcc stupid warning */ + ++#ifndef SSL_OP_NO_RENEGOTIATION ++ /* Please note that BoringSSL defines this macro to zero so don't ++ * change this to #if and do not assign a default value to this macro! ++ */ + if (where & SSL_CB_HANDSHAKE_START) { + /* Disable renegotiation (CVE-2009-3555) */ + if ((conn->flags & (CO_FL_CONNECTED | CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_CONNECTED) { +@@ -1413,6 +1417,7 @@ void ssl_sock_infocbk(const SSL *ssl, int where, int ret) + conn->err_code = CO_ER_SSL_RENEG; + } + } ++#endif + + if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) { + if (!(conn->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) { +@@ -3806,6 +3811,11 @@ ssl_sock_initial_ctx(struct bind_conf *bind_conf) + options |= SSL_OP_NO_TICKET; + if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH) + options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE; ++ ++#ifdef SSL_OP_NO_RENEGOTIATION ++ options |= SSL_OP_NO_RENEGOTIATION; ++#endif ++ + SSL_CTX_set_options(ctx, options); + + #if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC) diff --git a/net/haproxy/patches/012-DOC-mention-the-effect-of-nf_conntrack_tcp_loose-on-src-dst.patch b/net/haproxy/patches/012-DOC-mention-the-effect-of-nf_conntrack_tcp_loose-on-src-dst.patch new file mode 100644 index 000000000..9e8bd4513 --- /dev/null +++ b/net/haproxy/patches/012-DOC-mention-the-effect-of-nf_conntrack_tcp_loose-on-src-dst.patch @@ -0,0 +1,50 @@ +commit 2e405726a0c6be6617905522bde9038f75e623c4 +Author: Willy Tarreau +Date: Wed Jan 23 10:02:15 2019 +0100 + + DOC: mention the effect of nf_conntrack_tcp_loose on src/dst + + On rare occasions the logs may report inverted src/dst when using + conntrack with this sysctl. Add a mention for it in the doc. More + info here : + + https://www.spinics.net/lists/netdev/msg544878.html + + (cherry picked from commit 64ded3db2c686bad582cf9bb9fcabf21cb4becb7) + Signed-off-by: Willy Tarreau + (cherry picked from commit 037f9ac4a2cc4b344859af1cff7b30d5ecabe9e0) + Signed-off-by: William Lallemand + +diff --git a/doc/configuration.txt b/doc/configuration.txt +index 72b769a4..bc8ae4f8 100644 +--- a/doc/configuration.txt ++++ b/doc/configuration.txt +@@ -13822,7 +13822,12 @@ dst : ip + which is the address the client connected to. It can be useful when running + in transparent mode. It is of type IP and works on both IPv4 and IPv6 tables. + On IPv6 tables, IPv4 address is mapped to its IPv6 equivalent, according to +- RFC 4291. ++ RFC 4291. When the incoming connection passed through address translation or ++ redirection involving connection tracking, the original destination address ++ before the redirection will be reported. On Linux systems, the source and ++ destination may seldom appear reversed if the nf_conntrack_tcp_loose sysctl ++ is set, because a late response may reopen a timed out connection and switch ++ what is believed to be the source and the destination. + + dst_conn : integer + Returns an integer value corresponding to the number of currently established +@@ -14127,7 +14132,13 @@ src : ip + behind a proxy. However if the "accept-proxy" or "accept-netscaler-cip" bind + directive is used, it can be the address of a client behind another + PROXY-protocol compatible component for all rule sets except +- "tcp-request connection" which sees the real address. ++ "tcp-request connection" which sees the real address. When the incoming ++ connection passed through address translation or redirection involving ++ connection tracking, the original destination address before the redirection ++ will be reported. On Linux systems, the source and destination may seldom ++ appear reversed if the nf_conntrack_tcp_loose sysctl is set, because a late ++ response may reopen a timed out connection and switch what is believed to be ++ the source and the destination. + + Example: + # add an HTTP header in requests with the originating address' country diff --git a/net/haproxy/patches/001-deprecated-openssl.patch b/net/haproxy/patches/013-deprecated-openssl.patch similarity index 89% rename from net/haproxy/patches/001-deprecated-openssl.patch rename to net/haproxy/patches/013-deprecated-openssl.patch index 2a7b1bbc0..8dd011e41 100644 --- a/net/haproxy/patches/001-deprecated-openssl.patch +++ b/net/haproxy/patches/013-deprecated-openssl.patch @@ -35,7 +35,7 @@ static HA_RWLOCK_T *ssl_rwlocks; -@@ -1711,8 +1723,8 @@ ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL +@@ -1716,8 +1728,8 @@ ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL ASN1_INTEGER_set(X509_get_serialNumber(newcrt), HA_ATOMIC_ADD(&ssl_ctx_serial, 1)); /* Set duration for the certificate */ @@ -46,7 +46,7 @@ goto mkcert_error; /* set public key in the certificate */ -@@ -6285,7 +6297,7 @@ smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char +@@ -6299,7 +6311,7 @@ smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char goto out; smp_trash = get_trash_chunk(); @@ -55,7 +55,7 @@ goto out; smp->data.u.str = *smp_trash; -@@ -6385,7 +6397,7 @@ smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char +@@ -6399,7 +6411,7 @@ smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char goto out; smp_trash = get_trash_chunk(); @@ -64,7 +64,7 @@ goto out; smp->data.u.str = *smp_trash; -@@ -8935,10 +8947,12 @@ static void __ssl_sock_init(void) +@@ -8976,10 +8988,12 @@ static void __ssl_sock_init(void) #endif xprt_register(XPRT_SSL, &ssl_sock); @@ -78,7 +78,7 @@ ssl_locking_init(); #endif #if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER) -@@ -8967,8 +8981,8 @@ static void __ssl_sock_init(void) +@@ -9008,8 +9022,8 @@ static void __ssl_sock_init(void) #else /* OPENSSL_IS_BORINGSSL */ OPENSSL_VERSION_TEXT "\nRunning on OpenSSL version : %s%s", @@ -89,7 +89,7 @@ #endif memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : " #if OPENSSL_VERSION_NUMBER < 0x00907000L -@@ -9059,12 +9073,14 @@ static void __ssl_sock_deinit(void) +@@ -9100,12 +9114,14 @@ static void __ssl_sock_deinit(void) } #endif