Hello community, here is the log from the commit of package haproxy for openSUSE:Factory checked in at 2019-01-11 14:04:56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/haproxy (Old) and /work/SRC/openSUSE:Factory/.haproxy.new.28833 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "haproxy" Fri Jan 11 14:04:56 2019 rev:68 rq:664293 version:1.8.17~git0.e89d25b2 Changes: -------- --- /work/SRC/openSUSE:Factory/haproxy/haproxy.changes 2018-12-18 15:00:13.386085808 +0100 +++ /work/SRC/openSUSE:Factory/.haproxy.new.28833/haproxy.changes 2019-01-11 14:05:24.199805224 +0100 @@ -1,0 +2,20 @@ +Thu Jan 10 08:42:33 UTC 2019 - [email protected] + +- Update to version 1.8.17~git0.e89d25b2 (bsc#1121283) (CVE-2018-20615): + * BUG/CRITICAL: mux-h2: re-check the frame length when PRIORITY is used + * BUG/MEDIUM: lua: dead lock when Lua tasks are trigerred + * BUG/MINOR: lua: bad args are returned for Lua actions + * BUG/MINOR: lua: Return an error if a legacy HTTP applet doesn't send anything + * BUG/MEDIUM: cli: make "show sess" really thread-safe + * MINOR: stream/cli: report more info about the HTTP messages on "show sess all" + * MINOR: stream/cli: fix the location of the waiting flag in "show sess all" + * MINOR: lb: allow redispatch when using consistent hash + * BUG/MEDIUM: server: Also copy "check-sni" for server templates. + * BUG/MEDIUM: mux-h2: mark that we have too many CS once we have more than the max + * MINOR: mux-h2: only increase the connection window with the first update + * BUG/MAJOR: stream-int: Update the stream expiration date in stream_int_notify() + * BUG/MEDIUM: dns: overflowed dns name start position causing invalid dns error + * BUG/MEDIUM: dns: Don't prevent reading the last byte of the payload in dns_validate_response() + * BUG/MINOR: logs: leave startup-logs global and not per-thread + +------------------------------------------------------------------- Old: ---- haproxy-1.8.15~git0.6b6a350a.tar.gz New: ---- haproxy-1.8.17~git0.e89d25b2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ haproxy.spec ++++++ --- /var/tmp/diff_new_pack.LbTRLE/_old 2019-01-11 14:05:24.831804588 +0100 +++ /var/tmp/diff_new_pack.LbTRLE/_new 2019-01-11 14:05:24.835804584 +0100 @@ -47,7 +47,7 @@ %endif Name: haproxy -Version: 1.8.15~git0.6b6a350a +Version: 1.8.17~git0.e89d25b2 Release: 0 # # ++++++ _service ++++++ --- /var/tmp/diff_new_pack.LbTRLE/_old 2019-01-11 14:05:24.855804564 +0100 +++ /var/tmp/diff_new_pack.LbTRLE/_new 2019-01-11 14:05:24.855804564 +0100 @@ -6,7 +6,7 @@ <param name="versionformat">@PARENT_TAG@~git@TAG_OFFSET@.%h</param> <param name="versionrewrite-pattern">v(.*)</param> <param name="versionrewrite-replacement">\1</param> - <param name="revision">v1.8.15</param> + <param name="revision">v1.8.17</param> <param name="changesgenerate">enable</param> </service> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.LbTRLE/_old 2019-01-11 14:05:24.871804548 +0100 +++ /var/tmp/diff_new_pack.LbTRLE/_new 2019-01-11 14:05:24.871804548 +0100 @@ -5,4 +5,4 @@ <param name="url">http://git.haproxy.org/git/haproxy-1.7.git</param> <param name="changesrevision">640d526f8cdad00f7f5043b51f6a34f3f6ebb49f</param></service><service name="tar_scm"> <param name="url">http://git.haproxy.org/git/haproxy-1.8.git</param> - <param name="changesrevision">6b6a350afe3b08a1a60c80fe9120a1c9d10448ef</param></service></servicedata> \ No newline at end of file + <param name="changesrevision">e89d25b22da1eefa88ef5aa8ad6fa21e1bd4c801</param></service></servicedata> \ No newline at end of file ++++++ haproxy-1.8.15~git0.6b6a350a.tar.gz -> haproxy-1.8.17~git0.e89d25b2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.15~git0.6b6a350a/CHANGELOG new/haproxy-1.8.17~git0.e89d25b2/CHANGELOG --- old/haproxy-1.8.15~git0.6b6a350a/CHANGELOG 2018-12-13 00:59:21.000000000 +0100 +++ new/haproxy-1.8.17~git0.e89d25b2/CHANGELOG 2019-01-08 14:11:02.000000000 +0100 @@ -1,6 +1,25 @@ ChangeLog : =========== +2019/01/08 : 1.8.17 + - BUG/MAJOR: stream-int: Update the stream expiration date in stream_int_notify() + - MINOR: mux-h2: only increase the connection window with the first update + - BUG/MEDIUM: mux-h2: mark that we have too many CS once we have more than the max + - BUG/MEDIUM: server: Also copy "check-sni" for server templates. + - MINOR: lb: allow redispatch when using consistent hash + - MINOR: stream/cli: fix the location of the waiting flag in "show sess all" + - MINOR: stream/cli: report more info about the HTTP messages on "show sess all" + - BUG/MEDIUM: cli: make "show sess" really thread-safe + - BUG/MINOR: lua: Return an error if a legacy HTTP applet doesn't send anything + - BUG/MINOR: lua: bad args are returned for Lua actions + - BUG/MEDIUM: lua: dead lock when Lua tasks are trigerred + - BUG/CRITICAL: mux-h2: re-check the frame length when PRIORITY is used + +2018/12/21 : 1.8.16 + - BUG/MINOR: logs: leave startup-logs global and not per-thread + - BUG/MEDIUM: dns: Don't prevent reading the last byte of the payload in dns_validate_response() + - BUG/MEDIUM: dns: overflowed dns name start position causing invalid dns error + 2018/12/13 : 1.8.15 - MINOR: threads: Make sure threads_sync_pipe is initialized before using it. - DOC: clarify force-private-cache is an option diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.15~git0.6b6a350a/README new/haproxy-1.8.17~git0.e89d25b2/README --- old/haproxy-1.8.15~git0.6b6a350a/README 2018-12-13 00:59:21.000000000 +0100 +++ new/haproxy-1.8.17~git0.e89d25b2/README 2019-01-08 14:11:02.000000000 +0100 @@ -3,7 +3,7 @@ ---------------------- version 1.8 willy tarreau - 2018/12/13 + 2019/01/08 1) How to build it diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.15~git0.6b6a350a/VERDATE new/haproxy-1.8.17~git0.e89d25b2/VERDATE --- old/haproxy-1.8.15~git0.6b6a350a/VERDATE 2018-12-13 00:59:21.000000000 +0100 +++ new/haproxy-1.8.17~git0.e89d25b2/VERDATE 2019-01-08 14:11:02.000000000 +0100 @@ -1,2 +1,2 @@ $Format:%ci$ -2018/12/13 +2019/01/08 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.15~git0.6b6a350a/VERSION new/haproxy-1.8.17~git0.e89d25b2/VERSION --- old/haproxy-1.8.15~git0.6b6a350a/VERSION 2018-12-13 00:59:21.000000000 +0100 +++ new/haproxy-1.8.17~git0.e89d25b2/VERSION 2019-01-08 14:11:02.000000000 +0100 @@ -1 +1 @@ -1.8.15 +1.8.17 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.15~git0.6b6a350a/doc/configuration.txt new/haproxy-1.8.17~git0.e89d25b2/doc/configuration.txt --- old/haproxy-1.8.15~git0.6b6a350a/doc/configuration.txt 2018-12-13 00:59:21.000000000 +0100 +++ new/haproxy-1.8.17~git0.e89d25b2/doc/configuration.txt 2019-01-08 14:11:02.000000000 +0100 @@ -4,7 +4,7 @@ ---------------------- version 1.8 willy tarreau - 2018/12/13 + 2019/01/08 This document covers the configuration language as implemented in the version @@ -6528,8 +6528,8 @@ definitely stick to it because they cannot flush the cookie, so they will not be able to access the service anymore. - Specifying "option redispatch" will allow the proxy to break their - persistence and redistribute them to a working server. + Specifying "option redispatch" will allow the proxy to break cookie or + consistent hash based persistence and redistribute them to a working server. It also allows to retry connections to another server in case of multiple connection failures. Of course, it requires having "retries" set to a nonzero diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.15~git0.6b6a350a/examples/haproxy.spec new/haproxy-1.8.17~git0.e89d25b2/examples/haproxy.spec --- old/haproxy-1.8.15~git0.6b6a350a/examples/haproxy.spec 2018-12-13 00:59:21.000000000 +0100 +++ new/haproxy-1.8.17~git0.e89d25b2/examples/haproxy.spec 2019-01-08 14:11:02.000000000 +0100 @@ -1,6 +1,6 @@ Summary: HA-Proxy is a TCP/HTTP reverse proxy for high availability environments Name: haproxy -Version: 1.8.15 +Version: 1.8.17 Release: 1 License: GPL Group: System Environment/Daemons @@ -74,6 +74,12 @@ %attr(0755,root,root) %config %{_sysconfdir}/rc.d/init.d/%{name} %changelog +* Tue Jan 8 2019 Willy Tarreau <[email protected]> +- updated to 1.8.17 + +* Fri Dec 21 2018 William Lallemand <[email protected]> +- updated to 1.8.16 + * Thu Dec 13 2018 Willy Tarreau <[email protected]> - updated to 1.8.15 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.15~git0.6b6a350a/include/proto/lb_chash.h new/haproxy-1.8.17~git0.e89d25b2/include/proto/lb_chash.h --- old/haproxy-1.8.15~git0.6b6a350a/include/proto/lb_chash.h 2018-12-13 00:59:21.000000000 +0100 +++ new/haproxy-1.8.17~git0.e89d25b2/include/proto/lb_chash.h 2019-01-08 14:11:02.000000000 +0100 @@ -28,7 +28,7 @@ void chash_init_server_tree(struct proxy *p); struct server *chash_get_next_server(struct proxy *p, struct server *srvtoavoid); -struct server *chash_get_server_hash(struct proxy *p, unsigned int hash); +struct server *chash_get_server_hash(struct proxy *p, unsigned int hash, const struct server *avoid); #endif /* _PROTO_LB_CHASH_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.15~git0.6b6a350a/src/backend.c new/haproxy-1.8.17~git0.e89d25b2/src/backend.c --- old/haproxy-1.8.15~git0.6b6a350a/src/backend.c 2018-12-13 00:59:21.000000000 +0100 +++ new/haproxy-1.8.17~git0.e89d25b2/src/backend.c 2019-01-08 14:11:02.000000000 +0100 @@ -163,7 +163,7 @@ * If any server is found, it will be returned. If no valid server is found, * NULL is returned. */ -static struct server *get_server_sh(struct proxy *px, const char *addr, int len) +static struct server *get_server_sh(struct proxy *px, const char *addr, int len, const struct server *avoid) { unsigned int h, l; @@ -184,7 +184,7 @@ h = full_hash(h); hash_done: if (px->lbprm.algo & BE_LB_LKUP_CHTREE) - return chash_get_server_hash(px, h); + return chash_get_server_hash(px, h, avoid); else return map_get_server_hash(px, h); } @@ -201,7 +201,7 @@ * algorithm out of a tens because it gave him the best results. * */ -static struct server *get_server_uh(struct proxy *px, char *uri, int uri_len) +static struct server *get_server_uh(struct proxy *px, char *uri, int uri_len, const struct server *avoid) { unsigned int hash = 0; int c; @@ -237,7 +237,7 @@ hash = full_hash(hash); hash_done: if (px->lbprm.algo & BE_LB_LKUP_CHTREE) - return chash_get_server_hash(px, hash); + return chash_get_server_hash(px, hash, avoid); else return map_get_server_hash(px, hash); } @@ -251,7 +251,7 @@ * is returned. If any server is found, it will be returned. If no valid server * is found, NULL is returned. */ -static struct server *get_server_ph(struct proxy *px, const char *uri, int uri_len) +static struct server *get_server_ph(struct proxy *px, const char *uri, int uri_len, const struct server *avoid) { unsigned int hash = 0; const char *start, *end; @@ -294,7 +294,7 @@ hash = full_hash(hash); if (px->lbprm.algo & BE_LB_LKUP_CHTREE) - return chash_get_server_hash(px, hash); + return chash_get_server_hash(px, hash, avoid); else return map_get_server_hash(px, hash); } @@ -313,7 +313,7 @@ /* * this does the same as the previous server_ph, but check the body contents */ -static struct server *get_server_ph_post(struct stream *s) +static struct server *get_server_ph_post(struct stream *s, const struct server *avoid) { unsigned int hash = 0; struct http_txn *txn = s->txn; @@ -368,7 +368,7 @@ hash = full_hash(hash); if (px->lbprm.algo & BE_LB_LKUP_CHTREE) - return chash_get_server_hash(px, hash); + return chash_get_server_hash(px, hash, avoid); else return map_get_server_hash(px, hash); } @@ -394,7 +394,7 @@ * is returned. If any server is found, it will be returned. If no valid server * is found, NULL is returned. */ -static struct server *get_server_hh(struct stream *s) +static struct server *get_server_hh(struct stream *s, const struct server *avoid) { unsigned int hash = 0; struct http_txn *txn = s->txn; @@ -464,13 +464,13 @@ hash = full_hash(hash); hash_done: if (px->lbprm.algo & BE_LB_LKUP_CHTREE) - return chash_get_server_hash(px, hash); + return chash_get_server_hash(px, hash, avoid); else return map_get_server_hash(px, hash); } /* RDP Cookie HASH. */ -static struct server *get_server_rch(struct stream *s) +static struct server *get_server_rch(struct stream *s, const struct server *avoid) { unsigned int hash = 0; struct proxy *px = s->be; @@ -508,7 +508,7 @@ hash = full_hash(hash); hash_done: if (px->lbprm.algo & BE_LB_LKUP_CHTREE) - return chash_get_server_hash(px, hash); + return chash_get_server_hash(px, hash, avoid); else return map_get_server_hash(px, hash); } @@ -633,12 +633,12 @@ if (conn && conn->addr.from.ss_family == AF_INET) { srv = get_server_sh(s->be, (void *)&((struct sockaddr_in *)&conn->addr.from)->sin_addr, - 4); + 4, prev_srv); } else if (conn && conn->addr.from.ss_family == AF_INET6) { srv = get_server_sh(s->be, (void *)&((struct sockaddr_in6 *)&conn->addr.from)->sin6_addr, - 16); + 16, prev_srv); } else { /* unknown IP family */ @@ -653,7 +653,7 @@ break; srv = get_server_uh(s->be, b_ptr(s->req.buf, -http_uri_rewind(&s->txn->req)), - s->txn->req.sl.rq.u_l); + s->txn->req.sl.rq.u_l, prev_srv); break; case BE_LB_HASH_PRM: @@ -663,22 +663,22 @@ srv = get_server_ph(s->be, b_ptr(s->req.buf, -http_uri_rewind(&s->txn->req)), - s->txn->req.sl.rq.u_l); + s->txn->req.sl.rq.u_l, prev_srv); if (!srv && s->txn->meth == HTTP_METH_POST) - srv = get_server_ph_post(s); + srv = get_server_ph_post(s, prev_srv); break; case BE_LB_HASH_HDR: /* Header Parameter hashing */ if (!s->txn || s->txn->req.msg_state < HTTP_MSG_BODY) break; - srv = get_server_hh(s); + srv = get_server_hh(s, prev_srv); break; case BE_LB_HASH_RDP: /* RDP Cookie hashing */ - srv = get_server_rch(s); + srv = get_server_rch(s, prev_srv); break; default: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.15~git0.6b6a350a/src/dns.c new/haproxy-1.8.17~git0.e89d25b2/src/dns.c --- old/haproxy-1.8.15~git0.6b6a350a/src/dns.c 2018-12-13 00:59:21.000000000 +0100 +++ new/haproxy-1.8.17~git0.e89d25b2/src/dns.c 2019-01-08 14:11:02.000000000 +0100 @@ -415,7 +415,7 @@ if (depth++ > 100) goto err; - n = dns_read_name(buffer, bufend, buffer + reader[1], + n = dns_read_name(buffer, bufend, buffer + (*reader & 0x3f)*256 + reader[1], dest, dest_len - nb_bytes, offset, depth); if (n == 0) goto err; @@ -808,7 +808,7 @@ /* Move forward 2 bytes for data len */ reader += 2; - if (reader + dns_answer_record->data_len >= bufend) { + if (reader + dns_answer_record->data_len > bufend) { pool_free(dns_answer_item_pool, dns_answer_record); return DNS_RESP_INVALID; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.15~git0.6b6a350a/src/haproxy.c new/haproxy-1.8.17~git0.e89d25b2/src/haproxy.c --- old/haproxy-1.8.15~git0.6b6a350a/src/haproxy.c 2018-12-13 00:59:21.000000000 +0100 +++ new/haproxy-1.8.17~git0.e89d25b2/src/haproxy.c 2019-01-08 14:11:02.000000000 +0100 @@ -1,6 +1,6 @@ /* * HA-Proxy : High Availability-enabled HTTP/TCP proxy - * Copyright 2000-2018 Willy Tarreau <[email protected]>. + * Copyright 2000-2019 Willy Tarreau <[email protected]>. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -354,7 +354,7 @@ static void display_version() { printf("HA-Proxy version " HAPROXY_VERSION " " HAPROXY_DATE"\n"); - printf("Copyright 2000-2018 Willy Tarreau <[email protected]>\n\n"); + printf("Copyright 2000-2019 Willy Tarreau <[email protected]>\n\n"); } static void display_build_opts() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.15~git0.6b6a350a/src/hlua.c new/haproxy-1.8.17~git0.e89d25b2/src/hlua.c --- old/haproxy-1.8.15~git0.6b6a350a/src/hlua.c 2018-12-13 00:59:21.000000000 +0100 +++ new/haproxy-1.8.17~git0.e89d25b2/src/hlua.c 2019-01-08 14:11:02.000000000 +0100 @@ -864,16 +864,27 @@ * initialisation fails (example: out of memory error), the lua function * throws an error (longjmp). * - * This function manipulates two Lua stack: the main and the thread. Only + * In some case (at least one), this function can be called from safe + * environement, so we must not initialise it. While the support of + * threads appear, the safe environment set a lock to ensure only one + * Lua execution at a time. If we initialize safe environment in another + * safe environmenet, we have a dead lock. + * + * set "already_safe" true if the context is initialized form safe + * Lua fonction. + * + * This function manipulates two Lua stacks: the main and the thread. Only * the main stack can fail. The thread is not manipulated. This function * MUST NOT manipulate the created thread stack state, because is not * proctected agains error throwed by the thread stack. */ -int hlua_ctx_init(struct hlua *lua, struct task *task) +int hlua_ctx_init(struct hlua *lua, struct task *task, int already_safe) { - if (!SET_SAFE_LJMP(gL.T)) { - lua->Tref = LUA_REFNIL; - return 0; + if (!already_safe) { + if (!SET_SAFE_LJMP(gL.T)) { + lua->Tref = LUA_REFNIL; + return 0; + } } lua->Mref = LUA_REFNIL; lua->flags = 0; @@ -881,13 +892,15 @@ lua->T = lua_newthread(gL.T); if (!lua->T) { lua->Tref = LUA_REFNIL; - RESET_SAFE_LJMP(gL.T); + if (!already_safe) + RESET_SAFE_LJMP(gL.T); return 0; } hlua_sethlua(lua); lua->Tref = luaL_ref(gL.T, LUA_REGISTRYINDEX); lua->task = task; - RESET_SAFE_LJMP(gL.T); + if (!already_safe) + RESET_SAFE_LJMP(gL.T); return 1; } @@ -5700,8 +5713,8 @@ task->context = hlua; task->process = hlua_process_task; - if (!hlua_ctx_init(hlua, task)) - WILL_LJMP(luaL_error(L, "lua out of memory error.")); + if (!hlua_ctx_init(hlua, task, 1)) + WILL_LJMP(luaL_error(L, "Lua out of memory error.")); /* Restore the function in the stack. */ lua_rawgeti(hlua->T, LUA_REGISTRYINDEX, ref); @@ -5737,7 +5750,7 @@ SEND_ERR(stream->be, "Lua converter '%s': can't initialize Lua context.\n", fcn->name); return 0; } - if (!hlua_ctx_init(stream->hlua, stream->task)) { + if (!hlua_ctx_init(stream->hlua, stream->task, 0)) { SEND_ERR(stream->be, "Lua converter '%s': can't initialize Lua context.\n", fcn->name); return 0; } @@ -5857,7 +5870,7 @@ SEND_ERR(stream->be, "Lua sample-fetch '%s': can't initialize Lua context.\n", fcn->name); return 0; } - if (!hlua_ctx_init(stream->hlua, stream->task)) { + if (!hlua_ctx_init(stream->hlua, stream->task, 0)) { SEND_ERR(stream->be, "Lua sample-fetch '%s': can't initialize Lua context.\n", fcn->name); return 0; } @@ -6116,7 +6129,7 @@ rule->arg.hlua_rule->fcn.name); return ACT_RET_CONT; } - if (!hlua_ctx_init(s->hlua, s->task)) { + if (!hlua_ctx_init(s->hlua, s->task, 0)) { SEND_ERR(px, "Lua action '%s': can't initialize Lua context.\n", rule->arg.hlua_rule->fcn.name); return ACT_RET_CONT; @@ -6293,7 +6306,7 @@ * permits to save performances because a systematic * Lua initialization cause 5% performances loss. */ - if (!hlua_ctx_init(hlua, task)) { + if (!hlua_ctx_init(hlua, task, 0)) { SEND_ERR(px, "Lua applet tcp '%s': can't initialize Lua context.\n", ctx->rule->arg.hlua_rule->fcn.name); return 0; @@ -6493,7 +6506,7 @@ * permits to save performances because a systematic * Lua initialization cause 5% performances loss. */ - if (!hlua_ctx_init(hlua, task)) { + if (!hlua_ctx_init(hlua, task, 0)) { SEND_ERR(px, "Lua applet http '%s': can't initialize Lua context.\n", ctx->rule->arg.hlua_rule->fcn.name); return 0; @@ -6651,6 +6664,8 @@ } if (ctx->ctx.hlua_apphttp.flags & APPLET_DONE) { + if (!(ctx->ctx.hlua_apphttp.flags & APPLET_HDR_SENT)) + goto error; /* We must send the final chunk. */ if (ctx->ctx.hlua_apphttp.flags & APPLET_CHUNKED && @@ -6745,11 +6760,11 @@ /* Expect some arguments */ for (i = 0; i < fcn->nargs; i++) { - if (*args[i+1] == '\0') { + if (*args[*cur_arg] == '\0') { memprintf(err, "expect %d arguments", fcn->nargs); return ACT_RET_PRS_ERR; } - rule->arg.hlua_rule->args[i] = strdup(args[i + 1]); + rule->arg.hlua_rule->args[i] = strdup(args[*cur_arg]); if (!rule->arg.hlua_rule->args[i]) { memprintf(err, "out of memory error"); return ACT_RET_PRS_ERR; @@ -7031,7 +7046,7 @@ appctx->ctx.hlua_cli.task->process = hlua_applet_wakeup; /* Initialises the Lua context */ - if (!hlua_ctx_init(hlua, appctx->ctx.hlua_cli.task)) { + if (!hlua_ctx_init(hlua, appctx->ctx.hlua_cli.task, 0)) { SEND_ERR(NULL, "Lua cli '%s': can't initialize Lua context.\n", fcn->name); goto error; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.15~git0.6b6a350a/src/lb_chash.c new/haproxy-1.8.17~git0.e89d25b2/src/lb_chash.c --- old/haproxy-1.8.15~git0.6b6a350a/src/lb_chash.c 2018-12-13 00:59:21.000000000 +0100 +++ new/haproxy-1.8.17~git0.e89d25b2/src/lb_chash.c 2019-01-08 14:11:02.000000000 +0100 @@ -293,9 +293,10 @@ * the closest distance from the value of <hash>. Doing so ensures that even * with a well imbalanced hash, if some servers are close to each other, they * will still both receive traffic. If any server is found, it will be returned. + * It will also skip server <avoid> if the hash result ends on this one. * If no valid server is found, NULL is returned. */ -struct server *chash_get_server_hash(struct proxy *p, unsigned int hash) +struct server *chash_get_server_hash(struct proxy *p, unsigned int hash, const struct server *avoid) { struct eb32_node *next, *prev; struct server *nsrv, *psrv; @@ -339,7 +340,7 @@ } loop = 0; - while (p->lbprm.chash.balance_factor && !chash_server_is_eligible(nsrv)) { + while (nsrv == avoid || (p->lbprm.chash.balance_factor && !chash_server_is_eligible(nsrv))) { next = eb32_next(next); if (!next) { next = eb32_first(root); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.15~git0.6b6a350a/src/log.c new/haproxy-1.8.17~git0.e89d25b2/src/log.c --- old/haproxy-1.8.15~git0.6b6a350a/src/log.c 2018-12-13 00:59:21.000000000 +0100 +++ new/haproxy-1.8.17~git0.e89d25b2/src/log.c 2019-01-08 14:11:02.000000000 +0100 @@ -230,7 +230,7 @@ /* A global buffer used to store all startup alerts/warnings. It will then be * retrieve on the CLI. */ -static THREAD_LOCAL char *startup_logs = NULL; +static char *startup_logs = NULL; struct logformat_var_args { char *name; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.15~git0.6b6a350a/src/mux_h2.c new/haproxy-1.8.17~git0.e89d25b2/src/mux_h2.c --- old/haproxy-1.8.15~git0.6b6a350a/src/mux_h2.c 2018-12-13 00:59:21.000000000 +0100 +++ new/haproxy-1.8.17~git0.e89d25b2/src/mux_h2.c 2019-01-08 14:11:02.000000000 +0100 @@ -60,6 +60,7 @@ /* other flags */ #define H2_CF_GOAWAY_SENT 0x00001000 // a GOAWAY frame was successfully sent #define H2_CF_GOAWAY_FAILED 0x00002000 // a GOAWAY frame failed to be sent +#define H2_CF_WINDOW_OPENED 0x00010000 // demux increased window already advertised /* H2 connection state, in h2c->st0 */ @@ -263,7 +264,7 @@ /* returns true if the connection has too many conn_streams attached */ static inline int h2_has_too_many_cs(const struct h2c *h2c) { - return h2c->nb_cs >= h2_settings_max_concurrent_streams; + return h2c->nb_cs > h2_settings_max_concurrent_streams; } /* re-enables receiving on mux <target> after a buffer was allocated. It returns @@ -413,7 +414,7 @@ h2c->max_id = -1; h2c->errcode = H2_ERR_NO_ERROR; h2c->flags = H2_CF_NONE; - h2c->rcvd_c = H2_INITIAL_WINDOW_INCREMENT; + h2c->rcvd_c = 0; h2c->rcvd_s = 0; h2c->nb_streams = 0; h2c->nb_cs = 0; @@ -1334,6 +1335,14 @@ if (h2c->rcvd_c <= 0) return 1; + if (!(h2c->flags & H2_CF_WINDOW_OPENED)) { + /* increase the advertised connection window to 2G on + * first update. + */ + h2c->flags |= H2_CF_WINDOW_OPENED; + h2c->rcvd_c += H2_INITIAL_WINDOW_INCREMENT; + } + /* send WU for the connection */ ret = h2c_send_window_update(h2c, 0, h2c->rcvd_c); if (ret > 0) @@ -2717,6 +2726,11 @@ goto fail; } + if (flen < 5) { + h2c_error(h2c, H2_ERR_FRAME_SIZE_ERROR); + goto fail; + } + hdrs += 5; // stream dep = 4, weight = 1 flen -= 5; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.15~git0.6b6a350a/src/server.c new/haproxy-1.8.17~git0.e89d25b2/src/server.c --- old/haproxy-1.8.15~git0.6b6a350a/src/server.c 2018-12-13 00:59:21.000000000 +0100 +++ new/haproxy-1.8.17~git0.e89d25b2/src/server.c 2019-01-08 14:11:02.000000000 +0100 @@ -1460,6 +1460,7 @@ srv->check.addr = srv->agent.addr = src->check.addr; srv->check.use_ssl = src->check.use_ssl; srv->check.port = src->check.port; + srv->check.sni = src->check.sni; /* Note: 'flags' field has potentially been already initialized. */ srv->flags |= src->flags; srv->do_check = src->do_check; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.15~git0.6b6a350a/src/stream.c new/haproxy-1.8.17~git0.e89d25b2/src/stream.c --- old/haproxy-1.8.15~git0.6b6a350a/src/stream.c 2018-12-13 00:59:21.000000000 +0100 +++ new/haproxy-1.8.17~git0.e89d25b2/src/stream.c 2019-01-08 14:11:02.000000000 +0100 @@ -2712,13 +2712,9 @@ if (appctx->ctx.sess.section > 0 && appctx->ctx.sess.uid != strm->uniq_id) { /* stream changed, no need to go any further */ chunk_appendf(&trash, " *** session terminated while we were watching it ***\n"); - if (ci_putchk(si_ic(si), &trash) == -1) { - si_applet_cant_put(si); - return 0; - } - appctx->ctx.sess.uid = 0; - appctx->ctx.sess.section = 0; - return 1; + if (ci_putchk(si_ic(si), &trash) == -1) + goto full; + goto done; } switch (appctx->ctx.sess.section) { @@ -2754,8 +2750,9 @@ } chunk_appendf(&trash, - " flags=0x%x, conn_retries=%d, srv_conn=%p, pend_pos=%p\n", - strm->flags, strm->si[1].conn_retries, strm->srv_conn, strm->pend_pos); + " flags=0x%x, conn_retries=%d, srv_conn=%p, pend_pos=%p waiting=%d\n", + strm->flags, strm->si[1].conn_retries, strm->srv_conn, strm->pend_pos, + !LIST_ISEMPTY(&strm->buffer_wait.list)); chunk_appendf(&trash, " frontend=%s (id=%u mode=%s), listener=%s (id=%u)", @@ -2854,9 +2851,13 @@ if (strm->txn) chunk_appendf(&trash, - " txn=%p flags=0x%x meth=%d status=%d req.st=%s rsp.st=%s waiting=%d\n", + " txn=%p flags=0x%x meth=%d status=%d req.st=%s rsp.st=%s\n" + " req.f=0x%02x blen=%llu chnk=%llu next=%u\n" + " rsp.f=0x%02x blen=%llu chnk=%llu next=%u\n", strm->txn, strm->txn->flags, strm->txn->meth, strm->txn->status, - h1_msg_state_str(strm->txn->req.msg_state), h1_msg_state_str(strm->txn->rsp.msg_state), !LIST_ISEMPTY(&strm->buffer_wait.list)); + h1_msg_state_str(strm->txn->req.msg_state), h1_msg_state_str(strm->txn->rsp.msg_state), + strm->txn->req.flags, strm->txn->req.body_len, strm->txn->req.chunk_len, strm->txn->req.next, + strm->txn->rsp.flags, strm->txn->rsp.body_len, strm->txn->rsp.chunk_len, strm->txn->rsp.next); chunk_appendf(&trash, " si[0]=%p (state=%s flags=0x%02x endp0=%s:%p exp=%s, et=0x%03x)\n", @@ -3008,17 +3009,18 @@ strm->txn ? strm->txn->rsp.next : 0, strm->res.buf->i, strm->res.buf->size); - if (ci_putchk(si_ic(si), &trash) == -1) { - si_applet_cant_put(si); - return 0; - } + if (ci_putchk(si_ic(si), &trash) == -1) + goto full; /* use other states to dump the contents */ } /* end of dump */ + done: appctx->ctx.sess.uid = 0; appctx->ctx.sess.section = 0; return 1; + full: + return 0; } @@ -3041,14 +3043,16 @@ /* This function dumps all streams' states onto the stream interface's * read buffer. It returns 0 if the output buffer is full and it needs - * to be called again, otherwise non-zero. It is designed to be called - * from stats_dump_sess_to_buffer() below. + * to be called again, otherwise non-zero. It proceeds in an isolated + * thread so there is no thread safety issue here. */ static int cli_io_handler_dump_sess(struct appctx *appctx) { struct stream_interface *si = appctx->owner; struct connection *conn; + thread_isolate(); + if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW))) { /* If we're forced to shut down, we might have to remove our * reference to the last stream being dumped. @@ -3059,7 +3063,7 @@ LIST_INIT(&appctx->ctx.sess.bref.users); } } - return 1; + goto done; } chunk_reset(&trash); @@ -3074,14 +3078,11 @@ * pointer points back to the head of the streams list. */ LIST_INIT(&appctx->ctx.sess.bref.users); - HA_SPIN_LOCK(STRMS_LOCK, &streams_lock); appctx->ctx.sess.bref.ref = streams.n; - HA_SPIN_UNLOCK(STRMS_LOCK, &streams_lock); appctx->st2 = STAT_ST_LIST; /* fall through */ case STAT_ST_LIST: - HA_SPIN_LOCK(STRMS_LOCK, &streams_lock); /* first, let's detach the back-ref from a possible previous stream */ if (!LIST_ISEMPTY(&appctx->ctx.sess.bref.users)) { LIST_DEL(&appctx->ctx.sess.bref.users); @@ -3101,10 +3102,8 @@ LIST_ADDQ(&curr_strm->back_refs, &appctx->ctx.sess.bref.users); /* call the proper dump() function and return if we're missing space */ - if (!stats_dump_full_strm_to_buffer(si, curr_strm)) { - HA_SPIN_UNLOCK(STRMS_LOCK, &streams_lock); - return 0; - } + if (!stats_dump_full_strm_to_buffer(si, curr_strm)) + goto full; /* stream dump complete */ LIST_DEL(&appctx->ctx.sess.bref.users); @@ -3228,10 +3227,8 @@ /* let's try again later from this stream. We add ourselves into * this stream's users so that it can remove us upon termination. */ - si_applet_cant_put(si); LIST_ADDQ(&curr_strm->back_refs, &appctx->ctx.sess.bref.users); - HA_SPIN_UNLOCK(STRMS_LOCK, &streams_lock); - return 0; + goto full; } next_sess: @@ -3245,26 +3242,26 @@ else chunk_appendf(&trash, "Session not found.\n"); - if (ci_putchk(si_ic(si), &trash) == -1) { - si_applet_cant_put(si); - HA_SPIN_UNLOCK(STRMS_LOCK, &streams_lock); - return 0; - } + if (ci_putchk(si_ic(si), &trash) == -1) + goto full; appctx->ctx.sess.target = NULL; appctx->ctx.sess.uid = 0; - HA_SPIN_UNLOCK(STRMS_LOCK, &streams_lock); - return 1; + goto done; } - - HA_SPIN_UNLOCK(STRMS_LOCK, &streams_lock); - appctx->st2 = STAT_ST_FIN; /* fall through */ default: appctx->st2 = STAT_ST_FIN; - return 1; + goto done; } + done: + thread_release(); + return 1; + full: + thread_release(); + si_applet_cant_put(si); + return 0; } static void cli_release_show_sess(struct appctx *appctx) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.15~git0.6b6a350a/src/stream_interface.c new/haproxy-1.8.17~git0.e89d25b2/src/stream_interface.c --- old/haproxy-1.8.15~git0.6b6a350a/src/stream_interface.c 2018-12-13 00:59:21.000000000 +0100 +++ new/haproxy-1.8.17~git0.e89d25b2/src/stream_interface.c 2019-01-08 14:11:02.000000000 +0100 @@ -455,6 +455,7 @@ { struct channel *ic = si_ic(si); struct channel *oc = si_oc(si); + struct task *task = si_task(si); /* process consumer side */ if (channel_is_empty(oc)) { @@ -553,7 +554,14 @@ ((oc->flags & CF_WAKE_WRITE) && (si_opposite(si)->state != SI_ST_EST || (channel_is_empty(oc) && !oc->to_forward)))))) { - task_wakeup(si_task(si), TASK_WOKEN_IO); + task_wakeup(task, TASK_WOKEN_IO); + } + else { + /* Update expiration date for the task and requeue it */ + task->expire = tick_first((tick_is_expired(task->expire, now_ms) ? 0 : task->expire), + tick_first(tick_first(ic->rex, ic->wex), + tick_first(oc->rex, oc->wex))); + task_queue(task); } if (ic->flags & CF_READ_ACTIVITY) ic->flags &= ~CF_READ_DONTWAIT;
