Hello community, here is the log from the commit of package haproxy for openSUSE:Factory checked in at 2016-06-14 23:07:07 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/haproxy (Old) and /work/SRC/openSUSE:Factory/.haproxy.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "haproxy" Changes: -------- --- /work/SRC/openSUSE:Factory/haproxy/haproxy.changes 2016-05-19 12:15:08.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.haproxy.new/haproxy.changes 2016-06-14 23:07:09.000000000 +0200 @@ -1,0 +2,19 @@ +Thu Jun 9 12:48:27 UTC 2016 - mrueck...@suse.de + +- pull patches from git to fix some important issues (bsc#983972) (bsc#983974): + 0001-BUG-MAJOR-fix-listening-IP-address-storage-for-front.patch + 0002-BUG-MINOR-fix-listening-IP-address-storage-for-front.patch + 0003-DOC-Fix-typo-so-fetch-is-properly-parsed-by-Cyril-s-.patch + 0004-BUG-MAJOR-http-fix-breakage-of-reqdeny-causing-rando.patch + 0005-BUG-MEDIUM-stick-tables-fix-breakage-in-table-conver.patch + 0006-BUG-MEDIUM-dns-unbreak-DNS-resolver-after-header-fix.patch + 0007-BUILD-fix-build-on-Solaris-11.patch + 0008-CLEANUP-connection-fix-double-negation-on-memcmp.patch + 0009-BUG-MEDIUM-stats-show-servers-state-may-show-an-serv.patch + 0010-BUG-MEDIUM-fix-risk-of-segfault-with-show-tls-keys.patch + 0011-BUG-MEDIUM-sticktables-segfault-in-some-configuratio.patch + 0012-BUG-MEDIUM-lua-converters-doesn-t-work.patch + 0013-BUG-MINOR-http-add-header-header-name-copied-twice.patch + 0014-BUG-MEDIUM-http-add-header-buffer-overwritten.patch + +------------------------------------------------------------------- New: ---- 0001-BUG-MAJOR-fix-listening-IP-address-storage-for-front.patch 0002-BUG-MINOR-fix-listening-IP-address-storage-for-front.patch 0003-DOC-Fix-typo-so-fetch-is-properly-parsed-by-Cyril-s-.patch 0004-BUG-MAJOR-http-fix-breakage-of-reqdeny-causing-rando.patch 0005-BUG-MEDIUM-stick-tables-fix-breakage-in-table-conver.patch 0006-BUG-MEDIUM-dns-unbreak-DNS-resolver-after-header-fix.patch 0007-BUILD-fix-build-on-Solaris-11.patch 0008-CLEANUP-connection-fix-double-negation-on-memcmp.patch 0009-BUG-MEDIUM-stats-show-servers-state-may-show-an-serv.patch 0010-BUG-MEDIUM-fix-risk-of-segfault-with-show-tls-keys.patch 0011-BUG-MEDIUM-sticktables-segfault-in-some-configuratio.patch 0012-BUG-MEDIUM-lua-converters-doesn-t-work.patch 0013-BUG-MINOR-http-add-header-header-name-copied-twice.patch 0014-BUG-MEDIUM-http-add-header-buffer-overwritten.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ haproxy.spec ++++++ --- /var/tmp/diff_new_pack.qUmh2P/_old 2016-06-14 23:07:10.000000000 +0200 +++ /var/tmp/diff_new_pack.qUmh2P/_new 2016-06-14 23:07:10.000000000 +0200 @@ -74,6 +74,20 @@ Patch1: haproxy-1.6.0_config_haproxy_user.patch Patch2: haproxy-1.6.0-makefile_lib.patch Patch3: haproxy-1.6.0-sec-options.patch +Patch11: 0001-BUG-MAJOR-fix-listening-IP-address-storage-for-front.patch +Patch12: 0002-BUG-MINOR-fix-listening-IP-address-storage-for-front.patch +Patch13: 0003-DOC-Fix-typo-so-fetch-is-properly-parsed-by-Cyril-s-.patch +Patch14: 0004-BUG-MAJOR-http-fix-breakage-of-reqdeny-causing-rando.patch +Patch15: 0005-BUG-MEDIUM-stick-tables-fix-breakage-in-table-conver.patch +Patch16: 0006-BUG-MEDIUM-dns-unbreak-DNS-resolver-after-header-fix.patch +Patch17: 0007-BUILD-fix-build-on-Solaris-11.patch +Patch18: 0008-CLEANUP-connection-fix-double-negation-on-memcmp.patch +Patch19: 0009-BUG-MEDIUM-stats-show-servers-state-may-show-an-serv.patch +Patch20: 0010-BUG-MEDIUM-fix-risk-of-segfault-with-show-tls-keys.patch +Patch21: 0011-BUG-MEDIUM-sticktables-segfault-in-some-configuratio.patch +Patch22: 0012-BUG-MEDIUM-lua-converters-doesn-t-work.patch +Patch23: 0013-BUG-MINOR-http-add-header-header-name-copied-twice.patch +Patch24: 0014-BUG-MEDIUM-http-add-header-buffer-overwritten.patch # Source99: haproxy-rpmlintrc # @@ -107,6 +121,20 @@ %patch1 -p1 %patch2 %patch3 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 +%patch17 -p1 +%patch18 -p1 +%patch19 -p1 +%patch20 -p1 +%patch21 -p1 +%patch22 -p1 +%patch23 -p1 +%patch24 -p1 %build %{__make} \ ++++++ 0001-BUG-MAJOR-fix-listening-IP-address-storage-for-front.patch ++++++ >From 66dd99c4c9d828c2c2f7295b7db66f7ff6f2fa8e Mon Sep 17 00:00:00 2001 From: Vincent Bernat <vinc...@bernat.im> Date: Wed, 18 May 2016 16:17:44 +0200 Subject: [PATCH 01/14] BUG/MAJOR: fix listening IP address storage for frontends When compiled with GCC 6, the IP address specified for a frontend was ignored and HAProxy was listening on all addresses instead. This is caused by an incomplete copy of a "struct sockaddr_storage". With the GNU Libc, "struct sockaddr_storage" is defined as this: struct sockaddr_storage { sa_family_t ss_family; unsigned long int __ss_align; char __ss_padding[(128 - (2 * sizeof (unsigned long int)))]; }; Doing an aggregate copy (ss1 = ss2) is different than using memcpy(): only members of the aggregate have to be copied. Notably, padding can be or not be copied. In GCC 6, some optimizations use this fact and if a "struct sockaddr_storage" contains a "struct sockaddr_in", the port and the address are part of the padding (between sa_family and __ss_align) and can be not copied over. Therefore, we replace any aggregate copy by a memcpy(). There is another place using the same pattern. We also fix a function receiving a "struct sockaddr_storage" by copy instead of by reference. Since it only needs a read-only copy, the function is converted to request a reference. (cherry picked from commit 6e61589573f49b20a7184c9d297af1fc7d9184d8) --- include/proto/proto_http.h | 2 +- src/cfgparse.c | 2 +- src/connection.c | 2 +- src/hlua.c | 2 +- src/proto_http.c | 12 ++++++------ src/proto_tcp.c | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/proto/proto_http.h b/include/proto/proto_http.h index a1b0cb3..4ed96e3 100644 --- a/include/proto/proto_http.h +++ b/include/proto/proto_http.h @@ -110,7 +110,7 @@ void http_set_status(unsigned int status, struct stream *s); int http_transform_header_str(struct stream* s, struct http_msg *msg, const char* name, unsigned int name_len, const char *str, struct my_regex *re, int action); -void inet_set_tos(int fd, struct sockaddr_storage from, int tos); +void inet_set_tos(int fd, const struct sockaddr_storage *from, int tos); void http_perform_server_redirect(struct stream *s, struct stream_interface *si); void http_return_srv_error(struct stream *s, struct stream_interface *si); void http_capture_bad_message(struct error_snapshot *es, struct stream *s, diff --git a/src/cfgparse.c b/src/cfgparse.c index 97ec2e1..c118bd4 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -285,7 +285,7 @@ int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, } /* OK the address looks correct */ - ss = *ss2; + memcpy(&ss, ss2, sizeof(ss)); for (; port <= end; port++) { l = (struct listener *)calloc(1, sizeof(struct listener)); diff --git a/src/connection.c b/src/connection.c index b926e9f..991cae3 100644 --- a/src/connection.c +++ b/src/connection.c @@ -744,7 +744,7 @@ int make_proxy_line_v2(char *buf, int buf_len, struct server *srv, struct connec const char pp2_signature[] = PP2_SIGNATURE; int ret = 0; struct proxy_hdr_v2 *hdr = (struct proxy_hdr_v2 *)buf; - struct sockaddr_storage null_addr = {0}; + struct sockaddr_storage null_addr = { .ss_family = 0 }; struct sockaddr_storage *src = &null_addr; struct sockaddr_storage *dst = &null_addr; diff --git a/src/hlua.c b/src/hlua.c index 5ea3a83..edd288d 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -4790,7 +4790,7 @@ __LJMP static int hlua_txn_set_tos(lua_State *L) tos = MAY_LJMP(luaL_checkinteger(L, 2)); if ((cli_conn = objt_conn(htxn->s->sess->origin)) && conn_ctrl_ready(cli_conn)) - inet_set_tos(cli_conn->t.sock.fd, cli_conn->addr.from, tos); + inet_set_tos(cli_conn->t.sock.fd, &cli_conn->addr.from, tos); return 0; } diff --git a/src/proto_http.c b/src/proto_http.c index 9de1a17..59cd5d2 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -3403,15 +3403,15 @@ int http_handle_stats(struct stream *s, struct channel *req) /* Sets the TOS header in IPv4 and the traffic class header in IPv6 packets * (as per RFC3260 #4 and BCP37 #4.2 and #5.2). */ -void inet_set_tos(int fd, struct sockaddr_storage from, int tos) +void inet_set_tos(int fd, const struct sockaddr_storage *from, int tos) { #ifdef IP_TOS - if (from.ss_family == AF_INET) + if (from->ss_family == AF_INET) setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); #endif #ifdef IPV6_TCLASS - if (from.ss_family == AF_INET6) { - if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&from)->sin6_addr)) + if (from->ss_family == AF_INET6) { + if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)from)->sin6_addr)) /* v4-mapped addresses need IP_TOS */ setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); else @@ -3577,7 +3577,7 @@ resume_execution: case ACT_HTTP_SET_TOS: if ((cli_conn = objt_conn(sess->origin)) && conn_ctrl_ready(cli_conn)) - inet_set_tos(cli_conn->t.sock.fd, cli_conn->addr.from, rule->arg.tos); + inet_set_tos(cli_conn->t.sock.fd, &cli_conn->addr.from, rule->arg.tos); break; case ACT_HTTP_SET_MARK: @@ -3860,7 +3860,7 @@ resume_execution: case ACT_HTTP_SET_TOS: if ((cli_conn = objt_conn(sess->origin)) && conn_ctrl_ready(cli_conn)) - inet_set_tos(cli_conn->t.sock.fd, cli_conn->addr.from, rule->arg.tos); + inet_set_tos(cli_conn->t.sock.fd, &cli_conn->addr.from, rule->arg.tos); break; case ACT_HTTP_SET_MARK: diff --git a/src/proto_tcp.c b/src/proto_tcp.c index cce0acb..59cfea2 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -435,7 +435,7 @@ int tcp_connect_server(struct connection *conn, int data, int delack) struct sockaddr_storage sa; ret = 1; - sa = src->source_addr; + memcpy(&sa, &src->source_addr, sizeof(sa)); do { /* note: in case of retry, we may have to release a previously -- 2.6.6 ++++++ 0002-BUG-MINOR-fix-listening-IP-address-storage-for-front.patch ++++++ >From 254646083703fba5cc86cba31118e20f45784ce6 Mon Sep 17 00:00:00 2001 From: Vincent Bernat <vinc...@bernat.im> Date: Thu, 19 May 2016 11:29:43 +0200 Subject: [PATCH 02/14] BUG/MINOR: fix listening IP address storage for frontends (cont) Commit 6e6158 was incomplete. There was an additional aggregate copy that may trigger a similar case in the future. (cherry picked from commit 6e46ff11e9c0d0b9266226ad911362c8a62ee458) --- src/cfgparse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cfgparse.c b/src/cfgparse.c index c118bd4..b0f837e 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -296,7 +296,7 @@ int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, l->bind_conf = bind_conf; l->fd = fd; - l->addr = ss; + memcpy(&l->addr, &ss, sizeof(ss)); l->xprt = &raw_sock; l->state = LI_INIT; -- 2.6.6 ++++++ 0003-DOC-Fix-typo-so-fetch-is-properly-parsed-by-Cyril-s-.patch ++++++ >From 0c60f3790d6f177f123d4ae63d5f17868c789d12 Mon Sep 17 00:00:00 2001 From: Nenad Merdanovic <nmer...@anine.io> Date: Tue, 17 May 2016 03:31:21 +0200 Subject: [PATCH 03/14] DOC: Fix typo so fetch is properly parsed by Cyril's converter Signed-off-by: Nenad Merdanovic <nmer...@anine.io> (cherry picked from commit 1516fe31dddc9f50a8783db496072ea67db0adde) --- doc/configuration.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index 38bde30..d51d741 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -13043,7 +13043,7 @@ ssl_fc_has_sni : boolean that the SSL library is build with support for TLS extensions enabled (check haproxy -vv). -ssl_fc_is_resumed: boolean +ssl_fc_is_resumed : boolean Returns true if the SSL/TLS session has been resumed through the use of SSL session cache or TLS tickets. -- 2.6.6 ++++++ 0004-BUG-MAJOR-http-fix-breakage-of-reqdeny-causing-rando.patch ++++++ >From 60f01f8c89e4fb2723d5a9f2046286e699567e0b Mon Sep 17 00:00:00 2001 From: Willy Tarreau <w...@1wt.eu> Date: Wed, 25 May 2016 16:23:59 +0200 Subject: [PATCH 04/14] BUG/MAJOR: http: fix breakage of "reqdeny" causing random crashes Commit 108b1dd ("MEDIUM: http: configurable http result codes for http-request deny") introduced in 1.6-dev2 was incomplete. It introduced a new field "rule_deny_status" into struct http_txn, which is filled only by actions "http-request deny" and "http-request tarpit". It's then used in the deny code path to emit the proper error message, but is used uninitialized when the deny comes from a "reqdeny" rule, causing random behaviours ranging from returning a 200, an empty response, or crashing the process. Often upon startup only 200 was returned but after the fields are used the crash happens. This can be sped up using -dM. There's no need at all for storing this status in the http_txn struct anyway since it's used immediately after being set. Let's store it in a temporary variable instead which is passed as an argument to function http_req_get_intercept_rule(). As an extra benefit, removing it from struct http_txn reduced the size of this struct by 8 bytes. This fix must be backported to 1.6 where the bug was detected. Special thanks to Falco Schmutz for his detailed report including an exploitable core and a reproducer. (cherry picked from commit 58727ec088e55f739b146cff3baa955f8d1b2a3e) --- include/types/proto_http.h | 1 - src/proto_http.c | 21 +++++++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/include/types/proto_http.h b/include/types/proto_http.h index e5e9667..c3a73ef 100644 --- a/include/types/proto_http.h +++ b/include/types/proto_http.h @@ -362,7 +362,6 @@ struct http_txn { unsigned int flags; /* transaction flags */ enum http_meth_t meth; /* HTTP method */ /* 1 unused byte here */ - short rule_deny_status; /* HTTP status from rule when denying */ short status; /* HTTP status from the server, negative if from proxy */ char *uri; /* first line if log needed, NULL otherwise */ diff --git a/src/proto_http.c b/src/proto_http.c index 59cd5d2..6eac62b 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -3490,10 +3490,12 @@ static int http_transform_header(struct stream* s, struct http_msg *msg, * further processing of the request (auth, deny, ...), and defaults to * HTTP_RULE_RES_STOP if it executed all rules or stopped on an allow, or * HTTP_RULE_RES_CONT if the last rule was reached. It may set the TX_CLTARPIT - * on txn->flags if it encounters a tarpit rule. + * on txn->flags if it encounters a tarpit rule. If <deny_status> is not NULL + * and a deny/tarpit rule is matched, it will be filled with this rule's deny + * status. */ enum rule_result -http_req_get_intercept_rule(struct proxy *px, struct list *rules, struct stream *s) +http_req_get_intercept_rule(struct proxy *px, struct list *rules, struct stream *s, int *deny_status) { struct session *sess = strm_sess(s); struct http_txn *txn = s->txn; @@ -3539,12 +3541,14 @@ resume_execution: return HTTP_RULE_RES_STOP; case ACT_ACTION_DENY: - txn->rule_deny_status = rule->deny_status; + if (deny_status) + *deny_status = rule->deny_status; return HTTP_RULE_RES_DENY; case ACT_HTTP_REQ_TARPIT: txn->flags |= TX_CLTARPIT; - txn->rule_deny_status = rule->deny_status; + if (deny_status) + *deny_status = rule->deny_status; return HTTP_RULE_RES_DENY; case ACT_HTTP_REQ_AUTH: @@ -4303,6 +4307,7 @@ int http_process_req_common(struct stream *s, struct channel *req, int an_bit, s struct redirect_rule *rule; struct cond_wordlist *wl; enum rule_result verdict; + int deny_status = HTTP_ERR_403; if (unlikely(msg->msg_state < HTTP_MSG_BODY)) { /* we need more data */ @@ -4323,7 +4328,7 @@ int http_process_req_common(struct stream *s, struct channel *req, int an_bit, s /* evaluate http-request rules */ if (!LIST_ISEMPTY(&px->http_req_rules)) { - verdict = http_req_get_intercept_rule(px, &px->http_req_rules, s); + verdict = http_req_get_intercept_rule(px, &px->http_req_rules, s, &deny_status); switch (verdict) { case HTTP_RULE_RES_YIELD: /* some data miss, call the function later. */ @@ -4369,7 +4374,7 @@ int http_process_req_common(struct stream *s, struct channel *req, int an_bit, s /* parse the whole stats request and extract the relevant information */ http_handle_stats(s, req); - verdict = http_req_get_intercept_rule(px, &px->uri_auth->http_req_rules, s); + verdict = http_req_get_intercept_rule(px, &px->uri_auth->http_req_rules, s, &deny_status); /* not all actions implemented: deny, allow, auth */ if (verdict == HTTP_RULE_RES_DENY) /* stats http-request deny */ @@ -4500,9 +4505,9 @@ int http_process_req_common(struct stream *s, struct channel *req, int an_bit, s manage_client_side_cookies(s, req); txn->flags |= TX_CLDENY; - txn->status = http_err_codes[txn->rule_deny_status]; + txn->status = http_err_codes[deny_status]; s->logs.tv_request = now; - stream_int_retnclose(&s->si[0], http_error_message(s, txn->rule_deny_status)); + stream_int_retnclose(&s->si[0], http_error_message(s, deny_status)); stream_inc_http_err_ctr(s); sess->fe->fe_counters.denied_req++; if (sess->fe != s->be) -- 2.6.6 ++++++ 0005-BUG-MEDIUM-stick-tables-fix-breakage-in-table-conver.patch ++++++ >From 5a009af68013ac3f08fd08dad27b5d8ad038724c Mon Sep 17 00:00:00 2001 From: Willy Tarreau <w...@1wt.eu> Date: Wed, 25 May 2016 17:07:56 +0200 Subject: [PATCH 05/14] BUG/MEDIUM: stick-tables: fix breakage in table converters Baptiste reported that the table_conn_rate() converter would always return zero in 1.6.5. In fact, commit bc8c404 ("MAJOR: stick-tables: use sample types in place of dedicated types") broke all stick-table converters because smp_to_stkey() now returns a pointer to the sample instead of holding a copy of the key, and the converters used to reinitialize the sample prior to performing the lookup. Only "in_table()" continued to work. The construct is still fragile, so some comments were added to a few function to clarify their impacts. It's also worth noting that there is no point anymore in forcing these converters to take a string on input, but that will be changed in another commit. The bug was introduced in 1.6-dev4, this fix must be backported to 1.6. (cherry picked from commit f0c730a0ac21a64af666ffa32a336db2c6f56d1b) --- src/stick_table.c | 56 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/src/stick_table.c b/src/stick_table.c index e5bb168..3e816b2 100644 --- a/src/stick_table.c +++ b/src/stick_table.c @@ -461,6 +461,8 @@ int stktable_parse_type(char **args, int *myidx, unsigned long *type, size_t *ke } /* Prepares a stktable_key from a sample <smp> to search into table <t>. + * Note that the sample *is* modified and that the returned key may point + * to it, so the sample must not be modified afterwards before the lookup. * Returns NULL if the sample could not be converted (eg: no matching type), * otherwise a pointer to the static stktable_key filled with what is needed * for the lookup. @@ -700,11 +702,12 @@ static int sample_conv_table_bytes_in_rate(const struct arg *arg_p, struct sampl if (!key) return 0; + ts = stktable_lookup_key(t, key); + smp->flags = SMP_F_VOL_TEST; smp->data.type = SMP_T_SINT; smp->data.u.sint = 0; - ts = stktable_lookup_key(t, key); if (!ts) /* key not present */ return 1; @@ -736,11 +739,12 @@ static int sample_conv_table_conn_cnt(const struct arg *arg_p, struct sample *sm if (!key) return 0; + ts = stktable_lookup_key(t, key); + smp->flags = SMP_F_VOL_TEST; smp->data.type = SMP_T_SINT; smp->data.u.sint = 0; - ts = stktable_lookup_key(t, key); if (!ts) /* key not present */ return 1; @@ -771,11 +775,12 @@ static int sample_conv_table_conn_cur(const struct arg *arg_p, struct sample *sm if (!key) return 0; + ts = stktable_lookup_key(t, key); + smp->flags = SMP_F_VOL_TEST; smp->data.type = SMP_T_SINT; smp->data.u.sint = 0; - ts = stktable_lookup_key(t, key); if (!ts) /* key not present */ return 1; @@ -806,11 +811,12 @@ static int sample_conv_table_conn_rate(const struct arg *arg_p, struct sample *s if (!key) return 0; + ts = stktable_lookup_key(t, key); + smp->flags = SMP_F_VOL_TEST; smp->data.type = SMP_T_SINT; smp->data.u.sint = 0; - ts = stktable_lookup_key(t, key); if (!ts) /* key not present */ return 1; @@ -842,11 +848,12 @@ static int sample_conv_table_bytes_out_rate(const struct arg *arg_p, struct samp if (!key) return 0; + ts = stktable_lookup_key(t, key); + smp->flags = SMP_F_VOL_TEST; smp->data.type = SMP_T_SINT; smp->data.u.sint = 0; - ts = stktable_lookup_key(t, key); if (!ts) /* key not present */ return 1; @@ -878,11 +885,12 @@ static int sample_conv_table_gpt0(const struct arg *arg_p, struct sample *smp, v if (!key) return 0; + ts = stktable_lookup_key(t, key); + smp->flags = SMP_F_VOL_TEST; smp->data.type = SMP_T_SINT; smp->data.u.sint = 0; - ts = stktable_lookup_key(t, key); if (!ts) /* key not present */ return 1; @@ -913,11 +921,12 @@ static int sample_conv_table_gpc0(const struct arg *arg_p, struct sample *smp, v if (!key) return 0; + ts = stktable_lookup_key(t, key); + smp->flags = SMP_F_VOL_TEST; smp->data.type = SMP_T_SINT; smp->data.u.sint = 0; - ts = stktable_lookup_key(t, key); if (!ts) /* key not present */ return 1; @@ -948,11 +957,12 @@ static int sample_conv_table_gpc0_rate(const struct arg *arg_p, struct sample *s if (!key) return 0; + ts = stktable_lookup_key(t, key); + smp->flags = SMP_F_VOL_TEST; smp->data.type = SMP_T_SINT; smp->data.u.sint = 0; - ts = stktable_lookup_key(t, key); if (!ts) /* key not present */ return 1; @@ -984,11 +994,12 @@ static int sample_conv_table_http_err_cnt(const struct arg *arg_p, struct sample if (!key) return 0; + ts = stktable_lookup_key(t, key); + smp->flags = SMP_F_VOL_TEST; smp->data.type = SMP_T_SINT; smp->data.u.sint = 0; - ts = stktable_lookup_key(t, key); if (!ts) /* key not present */ return 1; @@ -1019,11 +1030,12 @@ static int sample_conv_table_http_err_rate(const struct arg *arg_p, struct sampl if (!key) return 0; + ts = stktable_lookup_key(t, key); + smp->flags = SMP_F_VOL_TEST; smp->data.type = SMP_T_SINT; smp->data.u.sint = 0; - ts = stktable_lookup_key(t, key); if (!ts) /* key not present */ return 1; @@ -1055,11 +1067,12 @@ static int sample_conv_table_http_req_cnt(const struct arg *arg_p, struct sample if (!key) return 0; + ts = stktable_lookup_key(t, key); + smp->flags = SMP_F_VOL_TEST; smp->data.type = SMP_T_SINT; smp->data.u.sint = 0; - ts = stktable_lookup_key(t, key); if (!ts) /* key not present */ return 1; @@ -1090,11 +1103,12 @@ static int sample_conv_table_http_req_rate(const struct arg *arg_p, struct sampl if (!key) return 0; + ts = stktable_lookup_key(t, key); + smp->flags = SMP_F_VOL_TEST; smp->data.type = SMP_T_SINT; smp->data.u.sint = 0; - ts = stktable_lookup_key(t, key); if (!ts) /* key not present */ return 1; @@ -1126,11 +1140,12 @@ static int sample_conv_table_kbytes_in(const struct arg *arg_p, struct sample *s if (!key) return 0; + ts = stktable_lookup_key(t, key); + smp->flags = SMP_F_VOL_TEST; smp->data.type = SMP_T_SINT; smp->data.u.sint = 0; - ts = stktable_lookup_key(t, key); if (!ts) /* key not present */ return 1; @@ -1161,11 +1176,12 @@ static int sample_conv_table_kbytes_out(const struct arg *arg_p, struct sample * if (!key) return 0; + ts = stktable_lookup_key(t, key); + smp->flags = SMP_F_VOL_TEST; smp->data.type = SMP_T_SINT; smp->data.u.sint = 0; - ts = stktable_lookup_key(t, key); if (!ts) /* key not present */ return 1; @@ -1196,11 +1212,12 @@ static int sample_conv_table_server_id(const struct arg *arg_p, struct sample *s if (!key) return 0; + ts = stktable_lookup_key(t, key); + smp->flags = SMP_F_VOL_TEST; smp->data.type = SMP_T_SINT; smp->data.u.sint = 0; - ts = stktable_lookup_key(t, key); if (!ts) /* key not present */ return 1; @@ -1231,11 +1248,12 @@ static int sample_conv_table_sess_cnt(const struct arg *arg_p, struct sample *sm if (!key) return 0; + ts = stktable_lookup_key(t, key); + smp->flags = SMP_F_VOL_TEST; smp->data.type = SMP_T_SINT; smp->data.u.sint = 0; - ts = stktable_lookup_key(t, key); if (!ts) /* key not present */ return 1; @@ -1266,11 +1284,12 @@ static int sample_conv_table_sess_rate(const struct arg *arg_p, struct sample *s if (!key) return 0; + ts = stktable_lookup_key(t, key); + smp->flags = SMP_F_VOL_TEST; smp->data.type = SMP_T_SINT; smp->data.u.sint = 0; - ts = stktable_lookup_key(t, key); if (!ts) /* key not present */ return 1; @@ -1301,11 +1320,12 @@ static int sample_conv_table_trackers(const struct arg *arg_p, struct sample *sm if (!key) return 0; + ts = stktable_lookup_key(t, key); + smp->flags = SMP_F_VOL_TEST; smp->data.type = SMP_T_SINT; smp->data.u.sint = 0; - ts = stktable_lookup_key(t, key); if (ts) smp->data.u.sint = ts->ref_cnt; -- 2.6.6 ++++++ 0006-BUG-MEDIUM-dns-unbreak-DNS-resolver-after-header-fix.patch ++++++ >From 5f60de08667c3472d95cc20b87753e9fd8520057 Mon Sep 17 00:00:00 2001 From: Lukas Tribus <luky...@hotmail.com> Date: Wed, 25 May 2016 22:15:11 +0200 Subject: [PATCH 06/14] BUG/MEDIUM: dns: unbreak DNS resolver after header fix DNS requests (using the internal resolver) are corrupted since commit e2f84977165a ("BUG/MINOR: dns: fix DNS header definition"). Fix it by defining the struct in network byte order, while complying with RFC 2535, section 6.1. First reported by Eduard Vopicka on discourse. This must be backported to 1.6 (1.6.5 is affected). (cherry picked from commit f2ebcb47cbf2af36236fde807c0c21a22d7c1e79) --- include/types/dns.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/types/dns.h b/include/types/dns.h index e3d2f6b..15fc01b 100644 --- a/include/types/dns.h +++ b/include/types/dns.h @@ -58,16 +58,16 @@ /* DNS request or response header structure */ struct dns_header { unsigned short id:16; /* identifier */ - unsigned char qr :1; /* query/response 0: query, 1: response */ - unsigned char opcode :4; /* operation code */ - unsigned char aa :1; /* authoritative answer 0: no, 1: yes */ - unsigned char tc :1; /* truncation 0:no, 1: yes */ unsigned char rd :1; /* recursion desired 0: no, 1: yes */ - unsigned char ra :1; /* recursion available 0: no, 1: yes */ - unsigned char z :1; /* not used */ - unsigned char ad :1; /* authentic data */ - unsigned char cd :1; /* checking disabled */ + unsigned char tc :1; /* truncation 0:no, 1: yes */ + unsigned char aa :1; /* authoritative answer 0: no, 1: yes */ + unsigned char opcode :4; /* operation code */ + unsigned char qr :1; /* query/response 0: query, 1: response */ unsigned char rcode :4; /* response code */ + unsigned char cd :1; /* checking disabled */ + unsigned char ad :1; /* authentic data */ + unsigned char z :1; /* not used */ + unsigned char ra :1; /* recursion available 0: no, 1: yes */ unsigned short qdcount :16; /* question count */ unsigned short ancount :16; /* answer count */ unsigned short nscount :16; /* authority count */ -- 2.6.6 ++++++ 0007-BUILD-fix-build-on-Solaris-11.patch ++++++ >From a71fda4bf6c3e57997a3873a8bdb2b295b2299a2 Mon Sep 17 00:00:00 2001 From: Willy Tarreau <w...@1wt.eu> Date: Fri, 20 May 2016 06:29:59 +0200 Subject: [PATCH 07/14] BUILD: fix build on Solaris 11 htonll()/ntohll() already exist on Solaris 11 with a different declaration, causing a build error as reported by Jonathan Fisher. They used to exist on OSX with a #define which allowed us to detect them. It was a bad idea to give these functions a name subject to conflicts like this. Simply rename them my_htonll()/my_ntohll() to definitely get rid of the conflict. This patch must be backported to 1.6. (cherry picked from commit 5f6e9054b920b9952baa9860c6ead1039c66e940) --- include/common/standard.h | 10 +++------- src/sample.c | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/include/common/standard.h b/include/common/standard.h index 2cc9f45..88776df 100644 --- a/include/common/standard.h +++ b/include/common/standard.h @@ -1009,8 +1009,7 @@ static inline unsigned char utf8_return_length(unsigned char code) * the whole code is optimized out. In little endian, with a decent compiler, * a few bswap and 2 shifts are left, which is the minimum acceptable. */ -#ifndef htonll -static inline unsigned long long htonll(unsigned long long a) +static inline unsigned long long my_htonll(unsigned long long a) { union { struct { @@ -1021,15 +1020,12 @@ static inline unsigned long long htonll(unsigned long long a) } w = { .by64 = a }; return ((unsigned long long)htonl(w.by32.w1) << 32) | htonl(w.by32.w2); } -#endif /* Turns 64-bit value <a> from network byte order to host byte order. */ -#ifndef ntohll -static inline unsigned long long ntohll(unsigned long long a) +static inline unsigned long long my_ntohll(unsigned long long a) { - return htonll(a); + return my_htonll(a); } -#endif /* returns a 64-bit a timestamp with the finest resolution available. The * unit is intentionally not specified. It's mostly used to compare dates. diff --git a/src/sample.c b/src/sample.c index ecea85e..527ff62 100644 --- a/src/sample.c +++ b/src/sample.c @@ -765,7 +765,7 @@ static int c_int2bin(struct sample *smp) { struct chunk *chk = get_trash_chunk(); - *(unsigned long long int *)chk->str = htonll(smp->data.u.sint); + *(unsigned long long int *)chk->str = my_htonll(smp->data.u.sint); chk->len = 8; smp->data.u.str = *chk; -- 2.6.6 ++++++ 0008-CLEANUP-connection-fix-double-negation-on-memcmp.patch ++++++ >From c4809151b4c9ccc312cb451e99fd556e867242fc Mon Sep 17 00:00:00 2001 From: David CARLIER <devne...@gmail.com> Date: Thu, 24 Mar 2016 09:22:36 +0000 Subject: [PATCH 08/14] CLEANUP: connection: fix double negation on memcmp() Nothing harmful in here, just clarify that it applies to the whole expression. (cherry picked from commit 42ff05e2d3d10e8a1e070e66e8883c5eabe196d7) --- src/connection.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/connection.c b/src/connection.c index 991cae3..5515188 100644 --- a/src/connection.c +++ b/src/connection.c @@ -385,7 +385,7 @@ int conn_recv_proxy(struct connection *conn, int flag) if (trash.len < 9) /* shortest possible line */ goto missing; - if (!memcmp(line, "TCP4 ", 5) != 0) { + if (memcmp(line, "TCP4 ", 5) == 0) { u32 src3, dst3, sport, dport; line += 5; @@ -426,7 +426,7 @@ int conn_recv_proxy(struct connection *conn, int flag) ((struct sockaddr_in *)&conn->addr.to)->sin_port = htons(dport); conn->flags |= CO_FL_ADDR_FROM_SET | CO_FL_ADDR_TO_SET; } - else if (!memcmp(line, "TCP6 ", 5) != 0) { + else if (memcmp(line, "TCP6 ", 5) == 0) { u32 sport, dport; char *src_s; char *dst_s, *sport_s, *dport_s; -- 2.6.6 ++++++ 0009-BUG-MEDIUM-stats-show-servers-state-may-show-an-serv.patch ++++++ >From 4cb6ccc835ce0c2c874e9868a62a981278b510f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cyril=20Bont=C3=A9?= <cyril.bo...@free.fr> Date: Fri, 27 May 2016 00:06:45 +0200 Subject: [PATCH 09/14] BUG/MEDIUM: stats: show servers state may show an servers from another backend Olivier Doucet reported that "show servers state" was producing an invalid output with some configurations where nbproc > 1. Indeed, commit 76a99784f4 fixed some issues but unfortunately introduced a regression when a backend bound to the same process as the stats socket and a previous backend is bound to another one. For example : global daemon nbproc 2 stats socket /var/run/haproxy-1.sock process 1 stats socket /var/run/haproxy-2.sock process 2 listen proc1 bind 127.0.0.1:9001 bind-process 1 server WRONG 127.0.0.1:80 listen proc2 bind 127.0.0.1:9002 bind-process 2 server RIGHT 127.0.0.1:80 Requesting "show servers state" on /var/run/haproxy-2.sock was producing a line like : 3 proc2 1 WRONG 127.0.0.1 2 0 1 1 4 1 0 2 0 0 0 0 whereas the line below was awaited : 3 proc2 1 RIGHT 127.0.0.1 2 0 1 1 5 1 0 2 0 0 0 0 This was caused by the initialization of the server loop too early, before the bind_proc filtering whereas it should be done after. This fix should be backported to 1.6, where the regression has unfortunately been backported. (cherry picked from commit d55bd7a6a934387cdc5df7ad3fbc2718dc3a724e) --- src/dumpstats.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/dumpstats.c b/src/dumpstats.c index b9f5719..4614cf2 100644 --- a/src/dumpstats.c +++ b/src/dumpstats.c @@ -2755,6 +2755,9 @@ static int dump_servers_state(struct stream_interface *si, struct chunk *buf) if (appctx->ctx.server_state.px->bind_proc && !(appctx->ctx.server_state.px->bind_proc & (1UL << (relative_pid - 1)))) return 1; + if (!appctx->ctx.server_state.sv) + appctx->ctx.server_state.sv = appctx->ctx.server_state.px->srv; + for (; appctx->ctx.server_state.sv != NULL; appctx->ctx.server_state.sv = srv->next) { srv = appctx->ctx.server_state.sv; srv_addr[0] = '\0'; @@ -2857,8 +2860,6 @@ static int stats_dump_servers_state_to_buffer(struct stream_interface *si) for (; appctx->ctx.server_state.px != NULL; appctx->ctx.server_state.px = curproxy->next) { curproxy = appctx->ctx.server_state.px; - if (!appctx->ctx.server_state.sv) - appctx->ctx.server_state.sv = appctx->ctx.server_state.px->srv; /* servers are only in backends */ if (curproxy->cap & PR_CAP_BE) { if (!dump_servers_state(si, &trash)) -- 2.6.6 ++++++ 0010-BUG-MEDIUM-fix-risk-of-segfault-with-show-tls-keys.patch ++++++ >From ff8957a6f44061594b0e2456de172b7c9f453a3f Mon Sep 17 00:00:00 2001 From: William Lallemand <wlallem...@haproxy.com> Date: Fri, 20 May 2016 17:28:07 +0200 Subject: [PATCH 10/14] BUG/MEDIUM: fix risk of segfault with "show tls-keys" The reference to the tls_keys_ref was not deleted from the tlskeys_reference linked list. When the SSL is malconfigured, it can lead to an access to freed memory during a "show tls-keys" on the admin socked. (cherry picked from commit 7bba4ccfb68b2fc0e76f51bcca7cdcb1388c4023) --- src/cfgparse.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cfgparse.c b/src/cfgparse.c index b0f837e..7025b6a 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -8728,6 +8728,7 @@ out_uri_auth_compat: if(bind_conf->keys_ref) { free(bind_conf->keys_ref->filename); free(bind_conf->keys_ref->tlskeys); + LIST_DEL(&bind_conf->keys_ref->list); free(bind_conf->keys_ref); } #endif /* USE_OPENSSL */ -- 2.6.6 ++++++ 0011-BUG-MEDIUM-sticktables-segfault-in-some-configuratio.patch ++++++ >From 4693e2302271252044038c9be38487fb16218e5b Mon Sep 17 00:00:00 2001 From: Thierry Fournier <thierry.fourn...@ozon.io> Date: Mon, 6 Jun 2016 18:28:05 +0200 Subject: [PATCH 11/14] BUG/MEDIUM: sticktables: segfault in some configuration error cases When a stick table is tracked, and another one is used later on the configuration, a segfault occurs. The function "smp_create_src_stkctr" can return a NULL value, and its value is not tested, so one other function try to dereference a NULL pointer. This patch just add a verification of the NULL pointer. The problem is reproduced with this configuration: listen www mode http bind :12345 tcp-request content track-sc0 src table IPv4 http-request allow if { sc0_inc_gpc0(IPv6) gt 0 } server dummy 127.0.0.1:80 backend IPv4 stick-table type ip size 10 expire 60s store gpc0 backend IPv6 stick-table type ipv6 size 10 expire 60s store gpc0 Thank to kabef...@gmail.com for the bug report. This patch must be backported in the 1.6 and 1.5 version. (cherry picked from commit 6fc340ff07171bb85d11d835fa4158bbdef240a0) --- src/stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stream.c b/src/stream.c index 4ba8010..d80efa5 100644 --- a/src/stream.c +++ b/src/stream.c @@ -2855,7 +2855,7 @@ smp_fetch_sc_inc_gpc0(const struct arg *args, struct sample *smp, const char *kw if (stkctr_entry(stkctr) == NULL) stkctr = smp_create_src_stkctr(smp->sess, smp->strm, args, kw); - if (stkctr_entry(stkctr) != NULL) { + if (stkctr && stkctr_entry(stkctr)) { void *ptr1,*ptr2; /* First, update gpc0_rate if it's tracked. Second, update its -- 2.6.6 ++++++ 0012-BUG-MEDIUM-lua-converters-doesn-t-work.patch ++++++ >From 7e3cfc9e48673314f7b970a054339306cef20928 Mon Sep 17 00:00:00 2001 From: Thierry Fournier <thierry.fourn...@ozon.io> Date: Fri, 27 May 2016 16:35:01 +0200 Subject: [PATCH 12/14] BUG/MEDIUM: lua: converters doesn't work The number of arguments pushed in the stack are false, so we try to execute a function out of the stack. This function is always a nil pointer, so the following message is displayed. Lua converter 'testconv': runtime error: attempt to call a nil value. Thanks Michael Ezzell for the repporting. This patch must be backported in the 1.6 version. (cherry picked from commit 4a53bfdc1de46c78a23eabdefc4b418cff7d0403) --- src/hlua.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hlua.c b/src/hlua.c index edd288d..185c4c1 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -5167,7 +5167,7 @@ static int hlua_sample_conv_wrapper(const struct arg *arg_p, struct sample *smp, return 0; } hlua_smp2lua(stream->hlua.T, smp); - stream->hlua.nargs = 2; + stream->hlua.nargs = 1; /* push keywords in the stack. */ if (arg_p) { -- 2.6.6 ++++++ 0013-BUG-MINOR-http-add-header-header-name-copied-twice.patch ++++++ >From d281d68d3aa010f7e1a635c92ab486f7f2c666b9 Mon Sep 17 00:00:00 2001 From: Thierry Fournier <thierry.fourn...@ozon.io> Date: Wed, 1 Jun 2016 13:36:20 +0200 Subject: [PATCH 13/14] BUG/MINOR: http: add-header: header name copied twice The header name is copied two time in the buffer. The first copy is a printf-like function writing the name and the http separators in the buffer, and the second form is a memcopy. This seems to be inherited from some changes. This patch removes the printf like, format. This patch must be backported in 1.6 and 1.5 versions (cherry picked from commit 53c1a9b7cb8f3fe79b5492218363b6c0ff608fc1) --- src/proto_http.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/proto_http.c b/src/proto_http.c index 6eac62b..0d9dd31 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -3615,7 +3615,6 @@ resume_execution: case ACT_HTTP_SET_HDR: case ACT_HTTP_ADD_HDR: - chunk_printf(&trash, "%s: ", rule->arg.hdr_add.name); memcpy(trash.str, rule->arg.hdr_add.name, rule->arg.hdr_add.name_len); trash.len = rule->arg.hdr_add.name_len; trash.str[trash.len++] = ':'; -- 2.6.6 ++++++ 0014-BUG-MEDIUM-http-add-header-buffer-overwritten.patch ++++++ >From f5cb61d3224df4075e2ce3172733a25a1fab7fca Mon Sep 17 00:00:00 2001 From: Thierry Fournier <thierry.fourn...@ozon.io> Date: Wed, 1 Jun 2016 13:35:36 +0200 Subject: [PATCH 14/14] BUG/MEDIUM: http: add-header: buffer overwritten If we use the action "http-request add-header" with a Lua sample-fetch or converter, and the Lua function calls one of the Lua log function, the header name is corrupted, it contains an extract of the last loggued data. This is due to an overwrite of the trash buffer, because his scope is not respected in the "add-header" function. The scope of the trash buffer must be limited to the function using it. The build_logline() function can execute a lot of other function which can use the trash buffer. This patch fix the usage of the trash buffer. It limits the scope of this global buffer to the local function, we build first the header value using build_logline, and after we store the header name. Thanks Michael Ezzell for the repporting. This patch must be backported in 1.6 version (cherry picked from commit 4b788f7d349ddde3f70f063b7394529eac6ab678) --- src/proto_http.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/proto_http.c b/src/proto_http.c index 0d9dd31..fd1f108 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -3504,6 +3504,7 @@ http_req_get_intercept_rule(struct proxy *px, struct list *rules, struct stream struct hdr_ctx ctx; const char *auth_realm; int act_flags = 0; + int len; /* If "the current_rule_list" match the executed rule list, we are in * resume condition. If a resume is needed it is always in the action @@ -3615,11 +3616,18 @@ resume_execution: case ACT_HTTP_SET_HDR: case ACT_HTTP_ADD_HDR: + /* The scope of the trash buffer must be limited to this function. The + * build_logline() function can execute a lot of other function which + * can use the trash buffer. So for limiting the scope of this global + * buffer, we build first the header value using build_logline, and + * after we store the header name. + */ + len = rule->arg.hdr_add.name_len + 2, + len += build_logline(s, trash.str + len, trash.size - len, &rule->arg.hdr_add.fmt); memcpy(trash.str, rule->arg.hdr_add.name, rule->arg.hdr_add.name_len); - trash.len = rule->arg.hdr_add.name_len; - trash.str[trash.len++] = ':'; - trash.str[trash.len++] = ' '; - trash.len += build_logline(s, trash.str + trash.len, trash.size - trash.len, &rule->arg.hdr_add.fmt); + trash.str[rule->arg.hdr_add.name_len] = ':'; + trash.str[rule->arg.hdr_add.name_len + 1] = ' '; + trash.len = len; if (rule->action == ACT_HTTP_SET_HDR) { /* remove all occurrences of the header */ -- 2.6.6