From 5cdfacc1226cd3c8bb197e73ae548704107628cc Mon Sep 17 00:00:00 2001 From: Christian Lachner Date: Mon, 1 Apr 2019 10:18:45 +0200 Subject: [PATCH] haproxy: Update all patches for HAProxy v1.8.19 - Add new patches (see https://www.haproxy.org/bugs/bugs-1.8.19.html) - Raise PKG_RELEASE to 3 Signed-off-by: Christian Lachner --- net/haproxy/Makefile | 2 +- ...e-the-listener-exist-before-using-it.patch | 50 ++++++++++++++ ...e-counters-accurate-under-saturation.patch | 67 +++++++++++++++++++ ...ly-attempt-to-free-startup_logs-once.patch | 37 ++++++++++ ...ossible-segfault-on-deinit_51degrees.patch | 35 ++++++++++ ...arning-about-ssl-min-max-ver-support.patch | 34 ++++++++++ ..._CST-when-using-the-newer-atomic-API.patch | 49 ++++++++++++++ ...-to-take-into-account-epoll_fd-pipes.patch | 34 ++++++++++ ...alization-of-thread-dependent-fields.patch | 54 +++++++++++++++ ...ssl.patch => 008-deprecated-openssl.patch} | 0 10 files changed, 361 insertions(+), 1 deletion(-) create mode 100644 net/haproxy/patches/000-BUG-MAJOR-listener-Make-sure-the-listener-exist-before-using-it.patch create mode 100644 net/haproxy/patches/001-BUG-MINOR-listener-keep-accept-rate-counters-accurate-under-saturation.patch create mode 100644 net/haproxy/patches/002-BUG-MEDIUM-logs-Only-attempt-to-free-startup_logs-once.patch create mode 100644 net/haproxy/patches/003-BUG-MEDIUM-51d-fix-possible-segfault-on-deinit_51degrees.patch create mode 100644 net/haproxy/patches/004-BUG-MINOR-ssl-fix-warning-about-ssl-min-max-ver-support.patch create mode 100644 net/haproxy/patches/005-MEDIUM-threads-Use-__ATOMIC_SEQ_CST-when-using-the-newer-atomic-API.patch create mode 100644 net/haproxy/patches/006-BUG-MEDIUM-threads-fd-do-not-forget-to-take-into-account-epoll_fd-pipes.patch create mode 100644 net/haproxy/patches/007-BUG-MAJOR-spoe-Fix-initialization-of-thread-dependent-fields.patch rename net/haproxy/patches/{000-deprecated-openssl.patch => 008-deprecated-openssl.patch} (100%) diff --git a/net/haproxy/Makefile b/net/haproxy/Makefile index 54e34743e..e01785a97 100644 --- a/net/haproxy/Makefile +++ b/net/haproxy/Makefile @@ -11,7 +11,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=haproxy PKG_VERSION:=1.8.19 -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE:=haproxy-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://www.haproxy.org/download/1.8/src/ diff --git a/net/haproxy/patches/000-BUG-MAJOR-listener-Make-sure-the-listener-exist-before-using-it.patch b/net/haproxy/patches/000-BUG-MAJOR-listener-Make-sure-the-listener-exist-before-using-it.patch new file mode 100644 index 000000000..7d9708ed5 --- /dev/null +++ b/net/haproxy/patches/000-BUG-MAJOR-listener-Make-sure-the-listener-exist-before-using-it.patch @@ -0,0 +1,50 @@ +commit 7c3fd37724c58cf09359e0d381a9be305dd7869b +Author: Olivier Houchard +Date: Mon Feb 25 16:18:16 2019 +0100 + + BUG/MAJOR: listener: Make sure the listener exist before using it. + + In listener_accept(), make sure we have a listener before attempting to + use it. + An another thread may have closed the FD meanwhile, and set fdtab[fd].owner + to NULL. + As the listener is not free'd, it is ok to attempt to accept() a new + connection even if the listener was closed. At worst the fd has been + reassigned to another connection, and accept() will fail anyway. + + Many thanks to Richard Russo for reporting the problem, and suggesting the + fix. + + This should be backported to 1.9 and 1.8. + + (cherry picked from commit d16a9dfed80e75d730754b717370515265698cdd) + Signed-off-by: Christopher Faulet + (cherry picked from commit a2511ed1fcdfa8047dbe2268fc0259f9b06cf891) + Signed-off-by: William Lallemand + +diff --git a/src/listener.c b/src/listener.c +index a30efe03..5f6fafbc 100644 +--- a/src/listener.c ++++ b/src/listener.c +@@ -441,8 +441,8 @@ void delete_listener(struct listener *listener) + void listener_accept(int fd) + { + struct listener *l = fdtab[fd].owner; +- struct proxy *p = l->bind_conf->frontend; +- int max_accept = l->maxaccept ? l->maxaccept : 1; ++ struct proxy *p; ++ int max_accept; + int expire; + int cfd; + int ret; +@@ -450,6 +450,10 @@ void listener_accept(int fd) + static int accept4_broken; + #endif + ++ if (!l) ++ return; ++ p = l->bind_conf->frontend; ++ max_accept = l->maxaccept ? l->maxaccept : 1; + if (HA_SPIN_TRYLOCK(LISTENER_LOCK, &l->lock)) + return; + diff --git a/net/haproxy/patches/001-BUG-MINOR-listener-keep-accept-rate-counters-accurate-under-saturation.patch b/net/haproxy/patches/001-BUG-MINOR-listener-keep-accept-rate-counters-accurate-under-saturation.patch new file mode 100644 index 000000000..1edac3a2c --- /dev/null +++ b/net/haproxy/patches/001-BUG-MINOR-listener-keep-accept-rate-counters-accurate-under-saturation.patch @@ -0,0 +1,67 @@ +commit 78714ea673cefa83d3dff5aa9aa5e97726cfb5cd +Author: Willy Tarreau +Date: Mon Feb 25 15:02:04 2019 +0100 + + BUG/MINOR: listener: keep accept rate counters accurate under saturation + + The test on l->nbconn forces to exit the loop before updating the freq + counters, so the last session which reaches a listener's limit will not + be accounted for in the session rate measurement. + + Let's move the test at the beginning of the loop and mark the listener + as saturated on exit. + + This may be backported to 1.9 and 1.8. + + (cherry picked from commit 741b4d6b7aad1e4a66dd8584b5eff729b08fade7) + Signed-off-by: William Lallemand + (cherry picked from commit 5c7c7e447df84a04bda88c40382b652cdb77a079) + Signed-off-by: William Lallemand + +diff --git a/src/listener.c b/src/listener.c +index 5f6fafbc..b94d823c 100644 +--- a/src/listener.c ++++ b/src/listener.c +@@ -457,11 +457,6 @@ void listener_accept(int fd) + if (HA_SPIN_TRYLOCK(LISTENER_LOCK, &l->lock)) + return; + +- if (unlikely(l->nbconn >= l->maxconn)) { +- listener_full(l); +- goto end; +- } +- + if (!(l->options & LI_O_UNLIMITED) && global.sps_lim) { + int max = freq_ctr_remain(&global.sess_per_sec, global.sps_lim, 0); + +@@ -520,7 +515,7 @@ void listener_accept(int fd) + * worst case. If we fail due to system limits or temporary resource + * shortage, we try again 100ms later in the worst case. + */ +- while (max_accept--) { ++ while (l->nbconn < l->maxconn && max_accept--) { + struct sockaddr_storage addr; + socklen_t laddr = sizeof(addr); + unsigned int count; +@@ -627,11 +622,6 @@ void listener_accept(int fd) + goto transient_error; + } + +- if (l->nbconn >= l->maxconn) { +- listener_full(l); +- goto end; +- } +- + /* increase the per-process number of cumulated connections */ + if (!(l->options & LI_O_UNLIMITED)) { + count = update_freq_ctr(&global.sess_per_sec, 1); +@@ -659,6 +649,9 @@ void listener_accept(int fd) + limit_listener(l, &global_listener_queue); + task_schedule(global_listener_queue_task, tick_first(expire, global_listener_queue_task->expire)); + end: ++ if (l->nbconn >= l->maxconn) ++ listener_full(l); ++ + HA_SPIN_UNLOCK(LISTENER_LOCK, &l->lock); + } + diff --git a/net/haproxy/patches/002-BUG-MEDIUM-logs-Only-attempt-to-free-startup_logs-once.patch b/net/haproxy/patches/002-BUG-MEDIUM-logs-Only-attempt-to-free-startup_logs-once.patch new file mode 100644 index 000000000..d72636015 --- /dev/null +++ b/net/haproxy/patches/002-BUG-MEDIUM-logs-Only-attempt-to-free-startup_logs-once.patch @@ -0,0 +1,37 @@ +commit 4c82743abd299f0aa8105e98ec92b76375a7f344 +Author: Olivier Houchard +Date: Thu Mar 7 14:19:24 2019 +0100 + + BUG/MEDIUM: logs: Only attempt to free startup_logs once. + + deinit_log_buffers() can be called once per thread, however startup_logs + is common to all threads. So only attempt to free it once. + + This should be backported to 1.9 and 1.8. + + (cherry picked from commit 7c49711d6041d1afc42d5b310ddfd7d6f6817c3c) + Signed-off-by: William Lallemand + (cherry picked from commit bc3e21b27849275306a0580488613b7dfd4d8eb5) + Signed-off-by: William Lallemand + +diff --git a/src/log.c b/src/log.c +index b3f33662..9c112255 100644 +--- a/src/log.c ++++ b/src/log.c +@@ -1380,11 +1380,15 @@ int init_log_buffers() + /* Deinitialize log buffers used for syslog messages */ + void deinit_log_buffers() + { ++ void *tmp_startup_logs; ++ + free(logheader); + free(logheader_rfc5424); + free(logline); + free(logline_rfc5424); +- free(startup_logs); ++ tmp_startup_logs = HA_ATOMIC_XCHG(&startup_logs, NULL); ++ free(tmp_startup_logs); ++ + logheader = NULL; + logheader_rfc5424 = NULL; + logline = NULL; diff --git a/net/haproxy/patches/003-BUG-MEDIUM-51d-fix-possible-segfault-on-deinit_51degrees.patch b/net/haproxy/patches/003-BUG-MEDIUM-51d-fix-possible-segfault-on-deinit_51degrees.patch new file mode 100644 index 000000000..3c9078f0c --- /dev/null +++ b/net/haproxy/patches/003-BUG-MEDIUM-51d-fix-possible-segfault-on-deinit_51degrees.patch @@ -0,0 +1,35 @@ +commit 63f5dbf1b9fcdc5b10537d733b0e0798905ff1dc +Author: Dragan Dosen +Date: Thu Mar 7 15:24:23 2019 +0100 + + BUG/MEDIUM: 51d: fix possible segfault on deinit_51degrees() + + When haproxy is built with 51Degrees support, but not configured to use + 51Degrees database, a segfault can occur when deinit_51degrees() + function is called, eg. during soft-stop on SIGUSR1 signal. + + Only builds that use Pattern algorithm are affected. + + This fix must be backported to all stable branches where 51Degrees + support is available. Additional adjustments are required for some + branches due to API and naming changes. + + (cherry picked from commit bc6218e1b02860c6cdad0d2bb4dc8874557087f8) + Signed-off-by: William Lallemand + (cherry picked from commit 4e0363e84cb3f6ca341e1f83c6fd490c76c9ae6b) + Signed-off-by: William Lallemand + +diff --git a/src/51d.c b/src/51d.c +index a36333ef..03101136 100644 +--- a/src/51d.c ++++ b/src/51d.c +@@ -639,7 +639,8 @@ static void deinit_51degrees(void) + + free(global_51degrees.header_names); + #ifdef FIFTYONEDEGREES_H_PATTERN_INCLUDED +- fiftyoneDegreesWorksetPoolFree(global_51degrees.pool); ++ if (global_51degrees.pool) ++ fiftyoneDegreesWorksetPoolFree(global_51degrees.pool); + #endif + #ifdef FIFTYONEDEGREES_H_TRIE_INCLUDED + free(global_51degrees.device_offsets.firstOffset); diff --git a/net/haproxy/patches/004-BUG-MINOR-ssl-fix-warning-about-ssl-min-max-ver-support.patch b/net/haproxy/patches/004-BUG-MINOR-ssl-fix-warning-about-ssl-min-max-ver-support.patch new file mode 100644 index 000000000..6c1fac8a8 --- /dev/null +++ b/net/haproxy/patches/004-BUG-MINOR-ssl-fix-warning-about-ssl-min-max-ver-support.patch @@ -0,0 +1,34 @@ +commit 57e2606f70fa8d26fe4b5563ba72a6c7f2a25655 +Author: Lukas Tribus +Date: Tue Mar 5 23:14:32 2019 +0100 + + BUG/MINOR: ssl: fix warning about ssl-min/max-ver support + + In 84e417d8 ("MINOR: ssl: support Openssl 1.1.1 early callback for + switchctx") the code was extended to also support OpenSSL 1.1.1 + (code already supported BoringSSL). A configuration check warning + was updated but with the wrong logic, the #ifdef needs a && instead + of an ||. + + Reported in #54. + + Should be backported to 1.8. + + (cherry picked from commit 1aabc939780d5eab1f88089d01fb077ad9315c65) + Signed-off-by: William Lallemand + (cherry picked from commit f407d16b8f4cf2afb148668a23a1ba1cc4dd942a) + Signed-off-by: William Lallemand + +diff --git a/src/ssl_sock.c b/src/ssl_sock.c +index 7736c324..afdb1fce 100644 +--- a/src/ssl_sock.c ++++ b/src/ssl_sock.c +@@ -7418,7 +7418,7 @@ static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_ + + static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err) + { +-#if (OPENSSL_VERSION_NUMBER < 0x10101000L) || !defined(OPENSSL_IS_BORINGSSL) ++#if (OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL) + ha_warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n"); + #endif + return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err); diff --git a/net/haproxy/patches/005-MEDIUM-threads-Use-__ATOMIC_SEQ_CST-when-using-the-newer-atomic-API.patch b/net/haproxy/patches/005-MEDIUM-threads-Use-__ATOMIC_SEQ_CST-when-using-the-newer-atomic-API.patch new file mode 100644 index 000000000..4acae7d32 --- /dev/null +++ b/net/haproxy/patches/005-MEDIUM-threads-Use-__ATOMIC_SEQ_CST-when-using-the-newer-atomic-API.patch @@ -0,0 +1,49 @@ +commit 62aec002ccd6a7129b4f5e2e88be1957a6b2308b +Author: Olivier Houchard +Date: Thu Mar 7 18:48:22 2019 +0100 + + MEDIUM: threads: Use __ATOMIC_SEQ_CST when using the newer atomic API. + + When using the new __atomic* API, ask the compiler to generate barriers. + A variant of those functions that don't generate barriers will be added later. + Before that, using HA_ATOMIC* would not generate any barrier, and some parts + of the code should be reviewed and missing barriers should be added. + + This should probably be backported to 1.8 and 1.9. + + (cherry picked from commit 113537967c8680f94977473e18c9e14dc09c3356) + [wt: this is in fact a real bug fix : all these atomics do not provide + the slightest sequential consistency by default as the value 0 is + __ATOMIC_RELAXED, which will definitely cause random issues with + threads on non-x86 platforms]. + Signed-off-by: Willy Tarreau + (cherry picked from commit e5d1670f5fa95972fed6391201c0da8982bb9f94) + Signed-off-by: Christopher Faulet + +diff --git a/include/common/hathreads.h b/include/common/hathreads.h +index 24fb1d1a..8a738aaf 100644 +--- a/include/common/hathreads.h ++++ b/include/common/hathreads.h +@@ -213,14 +213,14 @@ static inline unsigned long thread_isolated() + }) + #else + /* gcc >= 4.7 */ +-#define HA_ATOMIC_CAS(val, old, new) __atomic_compare_exchange_n(val, old, new, 0, 0, 0) +-#define HA_ATOMIC_ADD(val, i) __atomic_add_fetch(val, i, 0) +-#define HA_ATOMIC_XADD(val, i) __atomic_fetch_add(val, i, 0) +-#define HA_ATOMIC_SUB(val, i) __atomic_sub_fetch(val, i, 0) +-#define HA_ATOMIC_AND(val, flags) __atomic_and_fetch(val, flags, 0) +-#define HA_ATOMIC_OR(val, flags) __atomic_or_fetch(val, flags, 0) +-#define HA_ATOMIC_XCHG(val, new) __atomic_exchange_n(val, new, 0) +-#define HA_ATOMIC_STORE(val, new) __atomic_store_n(val, new, 0) ++#define HA_ATOMIC_CAS(val, old, new) __atomic_compare_exchange_n(val, old, new, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ++#define HA_ATOMIC_ADD(val, i) __atomic_add_fetch(val, i, __ATOMIC_SEQ_CST) ++#define HA_ATOMIC_XADD(val, i) __atomic_fetch_add(val, i, __ATOMIC_SEQ_CST) ++#define HA_ATOMIC_SUB(val, i) __atomic_sub_fetch(val, i, __ATOMIC_SEQ_CST) ++#define HA_ATOMIC_AND(val, flags) __atomic_and_fetch(val, flags, __ATOMIC_SEQ_CST) ++#define HA_ATOMIC_OR(val, flags) __atomic_or_fetch(val, flags, __ATOMIC_SEQ_CST) ++#define HA_ATOMIC_XCHG(val, new) __atomic_exchange_n(val, new, __ATOMIC_SEQ_CST) ++#define HA_ATOMIC_STORE(val, new) __atomic_store_n(val, new, __ATOMIC_SEQ_CST) + #endif + + #define HA_ATOMIC_UPDATE_MAX(val, new) \ diff --git a/net/haproxy/patches/006-BUG-MEDIUM-threads-fd-do-not-forget-to-take-into-account-epoll_fd-pipes.patch b/net/haproxy/patches/006-BUG-MEDIUM-threads-fd-do-not-forget-to-take-into-account-epoll_fd-pipes.patch new file mode 100644 index 000000000..68cd98a7e --- /dev/null +++ b/net/haproxy/patches/006-BUG-MEDIUM-threads-fd-do-not-forget-to-take-into-account-epoll_fd-pipes.patch @@ -0,0 +1,34 @@ +commit 1dfa4fd4be313a87f2a4861e81d0ad8ea8214223 +Author: Willy Tarreau +Date: Thu Mar 14 19:10:55 2019 +0100 + + BUG/MEDIUM: threads/fd: do not forget to take into account epoll_fd/pipes + + Each thread uses one epoll_fd or kqueue_fd, and a pipe (thus two FDs). + These ones have to be accounted for in the maxsock calculation, otherwise + we can reach maxsock before maxconn. This is difficult to observe but it + in fact happens when a server connects back to the frontend and has checks + enabled : the check uses its FD and serves to fill the loop. In this case + all FDs planed for the datapath are used for this. + + This needs to be backported to 1.9 and 1.8. + + (cherry picked from commit 2c58b41c96e70f567d0f9ae876a80770630c06ee) + Signed-off-by: Willy Tarreau + (cherry picked from commit 26d110ba04cba02b337beff53a83847320e4fcdb) + Signed-off-by: Christopher Faulet + +diff --git a/src/haproxy.c b/src/haproxy.c +index 68367627..5c3febdd 100644 +--- a/src/haproxy.c ++++ b/src/haproxy.c +@@ -1828,6 +1828,9 @@ static void init(int argc, char **argv) + global.hardmaxconn = global.maxconn; /* keep this max value */ + global.maxsock += global.maxconn * 2; /* each connection needs two sockets */ + global.maxsock += global.maxpipes * 2; /* each pipe needs two FDs */ ++ global.maxsock += global.nbthread; /* one epoll_fd/kqueue_fd per thread */ ++ global.maxsock += 2 * global.nbthread; /* one wake-up pipe (2 fd) per thread */ ++ + /* compute fd used by async engines */ + if (global.ssl_used_async_engines) { + int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend; diff --git a/net/haproxy/patches/007-BUG-MAJOR-spoe-Fix-initialization-of-thread-dependent-fields.patch b/net/haproxy/patches/007-BUG-MAJOR-spoe-Fix-initialization-of-thread-dependent-fields.patch new file mode 100644 index 000000000..f4d448c21 --- /dev/null +++ b/net/haproxy/patches/007-BUG-MAJOR-spoe-Fix-initialization-of-thread-dependent-fields.patch @@ -0,0 +1,54 @@ +commit a3cfe8f4bc2ec98fdbe25c49f2c21699b6d09d2b +Author: Christopher Faulet +Date: Mon Mar 18 13:57:42 2019 +0100 + + BUG/MAJOR: spoe: Fix initialization of thread-dependent fields + + A bug was introduced in the commit b0769b ("BUG/MEDIUM: spoe: initialization + depending on nbthread must be done last"). The code depending on global.nbthread + was moved from cfg_parse_spoe_agent() to spoe_check() but the pointer on the + agent configuration was not updated to use the filter's one. The variable + curagent is a global variable only valid during the configuration parsing. In + spoe_check(), conf->agent must be used instead. + + This patch must be backported to 1.9 and 1.8. + + (cherry picked from commit fe261551b9980fe33990eb34d2153bf1de24b20f) + Signed-off-by: Christopher Faulet + (cherry picked from commit 7a93d271d549144a8ed8c816f5694a51ab62b90c) + Signed-off-by: Christopher Faulet + +diff --git a/src/flt_spoe.c b/src/flt_spoe.c +index e4453882..66d26f34 100644 +--- a/src/flt_spoe.c ++++ b/src/flt_spoe.c +@@ -2937,20 +2937,20 @@ spoe_check(struct proxy *px, struct flt_conf *fconf) + if (global.nbthread == 1) + conf->agent->flags |= SPOE_FL_ASYNC; + +- if ((curagent->rt = calloc(global.nbthread, sizeof(*curagent->rt))) == NULL) { ++ if ((conf->agent->rt = calloc(global.nbthread, sizeof(*conf->agent->rt))) == NULL) { + ha_alert("Proxy %s : out of memory initializing SPOE agent '%s' declared at %s:%d.\n", + px->id, conf->agent->id, conf->agent->conf.file, conf->agent->conf.line); + return 1; + } + for (i = 0; i < global.nbthread; ++i) { +- curagent->rt[i].frame_size = curagent->max_frame_size; +- curagent->rt[i].applets_act = 0; +- curagent->rt[i].applets_idle = 0; +- curagent->rt[i].sending_rate = 0; +- LIST_INIT(&curagent->rt[i].applets); +- LIST_INIT(&curagent->rt[i].sending_queue); +- LIST_INIT(&curagent->rt[i].waiting_queue); +- HA_SPIN_INIT(&curagent->rt[i].lock); ++ conf->agent->rt[i].frame_size = conf->agent->max_frame_size; ++ conf->agent->rt[i].applets_act = 0; ++ conf->agent->rt[i].applets_idle = 0; ++ conf->agent->rt[i].sending_rate = 0; ++ LIST_INIT(&conf->agent->rt[i].applets); ++ LIST_INIT(&conf->agent->rt[i].sending_queue); ++ LIST_INIT(&conf->agent->rt[i].waiting_queue); ++ HA_SPIN_INIT(&conf->agent->rt[i].lock); + } + + free(conf->agent->b.name); diff --git a/net/haproxy/patches/000-deprecated-openssl.patch b/net/haproxy/patches/008-deprecated-openssl.patch similarity index 100% rename from net/haproxy/patches/000-deprecated-openssl.patch rename to net/haproxy/patches/008-deprecated-openssl.patch