From c866db09111b700e8fc93d86347b19a27e138010 Mon Sep 17 00:00:00 2001
From: Christian Lachner <gladiac@gmail.com>
Date: Sun, 29 Apr 2018 10:04:49 +0200
Subject: [PATCH] haproxy: Update all patches for HAProxy v1.8.8 - Add new
 patches (see https://www.haproxy.org/bugs/bugs-1.8.8.html) - Raise
 patch-level to 02

Signed-off-by: Christian Lachner <gladiac@gmail.com>
---
 net/haproxy/Makefile                          |   2 +-
 ...issing-HA_SPIN_INIT-in-pat_ref_newid.patch |  26 +++
 ...-trying-to-read-from-a-closed-socket.patch |  87 ++++++++++
 ...idle-Ti-is-not-set-for-some-requests.patch |  50 ++++++
 ...gmentation-fault-if-a-Lua-task-exits.patch |  48 +++++
 ...nce-of-CONNECT-and-or-content-length.patch | 147 ++++++++++++++++
 ...-support-for-chunked-encoded-uploads.patch | 164 ++++++++++++++++++
 ...s-tasks-sticky-to-the-current-thread.patch |  36 ++++
 8 files changed, 559 insertions(+), 1 deletion(-)
 create mode 100644 net/haproxy/patches/0000-BUG-MINOR-pattern-Add-a-missing-HA_SPIN_INIT-in-pat_ref_newid.patch
 create mode 100644 net/haproxy/patches/0001-BUG-MAJOR-channel-Fix-crash-when-trying-to-read-from-a-closed-socket.patch
 create mode 100644 net/haproxy/patches/0002-BUG-MINOR-log-t_idle-Ti-is-not-set-for-some-requests.patch
 create mode 100644 net/haproxy/patches/0003-BUG-MEDIUM-lua-Fix-segmentation-fault-if-a-Lua-task-exits.patch
 create mode 100644 net/haproxy/patches/0004-MINOR-h2-detect-presence-of-CONNECT-and-or-content-length.patch
 create mode 100644 net/haproxy/patches/0005-BUG-MEDIUM-h2-implement-missing-support-for-chunked-encoded-uploads.patch
 create mode 100644 net/haproxy/patches/0006-BUG-MINOR-lua-threads-Make-luas-tasks-sticky-to-the-current-thread.patch

diff --git a/net/haproxy/Makefile b/net/haproxy/Makefile
index 6f07eaf20..44544c97f 100644
--- a/net/haproxy/Makefile
+++ b/net/haproxy/Makefile
@@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
 
 PKG_NAME:=haproxy
 PKG_VERSION:=1.8.8
-PKG_RELEASE:=01
+PKG_RELEASE:=02
 
 PKG_SOURCE:=haproxy-$(PKG_VERSION).tar.gz
 PKG_SOURCE_URL:=https://www.haproxy.org/download/1.8/src/
diff --git a/net/haproxy/patches/0000-BUG-MINOR-pattern-Add-a-missing-HA_SPIN_INIT-in-pat_ref_newid.patch b/net/haproxy/patches/0000-BUG-MINOR-pattern-Add-a-missing-HA_SPIN_INIT-in-pat_ref_newid.patch
new file mode 100644
index 000000000..eb3a18a10
--- /dev/null
+++ b/net/haproxy/patches/0000-BUG-MINOR-pattern-Add-a-missing-HA_SPIN_INIT-in-pat_ref_newid.patch
@@ -0,0 +1,26 @@
+commit 6c9efc8219e35f4eb17e94b364f4c371cfb56cca
+Author: Aurélien Nephtali <aurelien.nephtali@corp.ovh.com>
+Date:   Thu Apr 19 16:56:07 2018 +0200
+
+    BUG/MINOR: pattern: Add a missing HA_SPIN_INIT() in pat_ref_newid()
+    
+    pat_ref_newid() is lacking a spinlock init. It was probably forgotten
+    in b5997f740b ("MAJOR: threads/map: Make acls/maps thread safe").
+    
+    Signed-off-by: Aurélien Nephtali <aurelien.nephtali@corp.ovh.com>
+    (cherry picked from commit 564d15a71ecb3ae3372767866335cfbc068c4b48)
+    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
+
+diff --git a/src/pattern.c b/src/pattern.c
+index fe672f12..2eb82650 100644
+--- a/src/pattern.c
++++ b/src/pattern.c
+@@ -1906,7 +1906,7 @@ struct pat_ref *pat_ref_newid(int unique_id, const char *display, unsigned int f
+ 	ref->unique_id = unique_id;
+ 	LIST_INIT(&ref->head);
+ 	LIST_INIT(&ref->pat);
+-
++	HA_SPIN_INIT(&ref->lock);
+ 	LIST_ADDQ(&pattern_reference, &ref->list);
+ 
+ 	return ref;
diff --git a/net/haproxy/patches/0001-BUG-MAJOR-channel-Fix-crash-when-trying-to-read-from-a-closed-socket.patch b/net/haproxy/patches/0001-BUG-MAJOR-channel-Fix-crash-when-trying-to-read-from-a-closed-socket.patch
new file mode 100644
index 000000000..606c3bf09
--- /dev/null
+++ b/net/haproxy/patches/0001-BUG-MAJOR-channel-Fix-crash-when-trying-to-read-from-a-closed-socket.patch
@@ -0,0 +1,87 @@
+commit e0f6d4a4e8696140d1fcff812fb287d534d702e9
+Author: Tim Duesterhus <tim@bastelstu.be>
+Date:   Tue Apr 24 19:20:43 2018 +0200
+
+    BUG/MAJOR: channel: Fix crash when trying to read from a closed socket
+    
+    When haproxy is compiled using GCC <= 3.x or >= 5.x the `unlikely`
+    macro performs a comparison with zero: `(x) != 0`, thus returning
+    either 0 or 1.
+    
+    In `int co_getline_nc()` this macro was accidentally applied to
+    the variable `retcode` itself, instead of the result of the
+    comparison `retcode <= 0`. As a result any negative `retcode`
+    is converted to `1` for purposes of the comparison.
+    Thus never taking the branch (and exiting the function) for
+    negative values.
+    
+    This in turn leads to reads of uninitialized memory in the for-loop
+    below:
+    
+      ==12141== Conditional jump or move depends on uninitialised value(s)
+      ==12141==    at 0x4EB6B4: co_getline_nc (channel.c:346)
+      ==12141==    by 0x421CA4: hlua_socket_receive_yield (hlua.c:1713)
+      ==12141==    by 0x421F6F: hlua_socket_receive (hlua.c:1896)
+      ==12141==    by 0x529B08F: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==    by 0x52A7EFC: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==    by 0x529B497: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==    by 0x529711A: lua_pcallk (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==    by 0x52ABDF0: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==    by 0x529B08F: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==    by 0x52A7EFC: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==    by 0x529A9F1: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==    by 0x529B523: lua_resume (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==
+      ==12141== Use of uninitialised value of size 8
+      ==12141==    at 0x4EB6B9: co_getline_nc (channel.c:346)
+      ==12141==    by 0x421CA4: hlua_socket_receive_yield (hlua.c:1713)
+      ==12141==    by 0x421F6F: hlua_socket_receive (hlua.c:1896)
+      ==12141==    by 0x529B08F: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==    by 0x52A7EFC: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==    by 0x529B497: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==    by 0x529711A: lua_pcallk (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==    by 0x52ABDF0: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==    by 0x529B08F: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==    by 0x52A7EFC: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==    by 0x529A9F1: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==    by 0x529B523: lua_resume (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==
+      ==12141== Invalid read of size 1
+      ==12141==    at 0x4EB6B9: co_getline_nc (channel.c:346)
+      ==12141==    by 0x421CA4: hlua_socket_receive_yield (hlua.c:1713)
+      ==12141==    by 0x421F6F: hlua_socket_receive (hlua.c:1896)
+      ==12141==    by 0x529B08F: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==    by 0x52A7EFC: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==    by 0x529B497: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==    by 0x529711A: lua_pcallk (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==    by 0x52ABDF0: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==    by 0x529B08F: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==    by 0x52A7EFC: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==    by 0x529A9F1: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==    by 0x529B523: lua_resume (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==12141==  Address 0x8637171e928bb500 is not stack'd, malloc'd or (recently) free'd
+    
+    Fix this bug by correctly applying the `unlikely` macro to the result of the comparison.
+    
+    This bug exists as of commit ca16b038132444dea06e6d83953034128a812bce
+    which is the first commit adding this function.
+    
+    v1.6-dev1 is the first tag containing this commit, the fix should
+    be backported to haproxy 1.6 and newer.
+    
+    (cherry picked from commit 45be38c9c7ba2b20806f2b887876db4fb5b9457c)
+    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
+
+diff --git a/src/channel.c b/src/channel.c
+index bd5c4de0..3770502c 100644
+--- a/src/channel.c
++++ b/src/channel.c
+@@ -340,7 +340,7 @@ int co_getline_nc(const struct channel *chn,
+ 	int l;
+ 
+ 	retcode = co_getblk_nc(chn, blk1, len1, blk2, len2);
+-	if (unlikely(retcode) <= 0)
++	if (unlikely(retcode <= 0))
+ 		return retcode;
+ 
+ 	for (l = 0; l < *len1 && (*blk1)[l] != '\n'; l++);
diff --git a/net/haproxy/patches/0002-BUG-MINOR-log-t_idle-Ti-is-not-set-for-some-requests.patch b/net/haproxy/patches/0002-BUG-MINOR-log-t_idle-Ti-is-not-set-for-some-requests.patch
new file mode 100644
index 000000000..9fffb9597
--- /dev/null
+++ b/net/haproxy/patches/0002-BUG-MINOR-log-t_idle-Ti-is-not-set-for-some-requests.patch
@@ -0,0 +1,50 @@
+commit 0e645ba57ddff9163a3d9b5626f189e974e671bd
+Author: Rian McGuire <rian.mcguire@stileeducation.com>
+Date:   Tue Apr 24 11:19:21 2018 -0300
+
+    BUG/MINOR: log: t_idle (%Ti) is not set for some requests
+    
+    If TCP content inspection is used, msg_state can be >= HTTP_MSG_ERROR
+    the first time http_wait_for_request is called. t_idle was being left
+    unset in that case.
+    
+    In the example below :
+         stick-table type string len 64 size 100k expire 60s
+         tcp-request inspect-delay 1s
+         tcp-request content track-sc1 hdr(X-Session)
+    
+    %Ti will always be -1, because the msg_state is already at HTTP_MSG_BODY
+    when http_wait_for_request is called for the first time.
+    
+    This patch should backported to 1.8 and 1.7.
+    
+    (cherry picked from commit 89fcb7d929283e904cabad58de495d62fc753da2)
+    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
+
+diff --git a/src/proto_http.c b/src/proto_http.c
+index b38dd84f..4c18a27c 100644
+--- a/src/proto_http.c
++++ b/src/proto_http.c
+@@ -1618,18 +1618,16 @@ int http_wait_for_request(struct stream *s, struct channel *req, int an_bit)
+ 	/* we're speaking HTTP here, so let's speak HTTP to the client */
+ 	s->srv_error = http_return_srv_error;
+ 
++	/* If there is data available for analysis, log the end of the idle time. */
++	if (buffer_not_empty(req->buf) && s->logs.t_idle == -1)
++		s->logs.t_idle = tv_ms_elapsed(&s->logs.tv_accept, &now) - s->logs.t_handshake;
++
+ 	/* There's a protected area at the end of the buffer for rewriting
+ 	 * purposes. We don't want to start to parse the request if the
+ 	 * protected area is affected, because we may have to move processed
+ 	 * data later, which is much more complicated.
+ 	 */
+ 	if (buffer_not_empty(req->buf) && msg->msg_state < HTTP_MSG_ERROR) {
+-
+-		/* This point is executed when some data is avalaible for analysis,
+-		 * so we log the end of the idle time. */
+-		if (s->logs.t_idle == -1)
+-			s->logs.t_idle = tv_ms_elapsed(&s->logs.tv_accept, &now) - s->logs.t_handshake;
+-
+ 		if (txn->flags & TX_NOT_FIRST) {
+ 			if (unlikely(!channel_is_rewritable(req))) {
+ 				if (req->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_WRITE_ERROR|CF_WRITE_TIMEOUT))
diff --git a/net/haproxy/patches/0003-BUG-MEDIUM-lua-Fix-segmentation-fault-if-a-Lua-task-exits.patch b/net/haproxy/patches/0003-BUG-MEDIUM-lua-Fix-segmentation-fault-if-a-Lua-task-exits.patch
new file mode 100644
index 000000000..2a52c7cbd
--- /dev/null
+++ b/net/haproxy/patches/0003-BUG-MEDIUM-lua-Fix-segmentation-fault-if-a-Lua-task-exits.patch
@@ -0,0 +1,48 @@
+commit 17f3e16826e5b1a3f79b7421d69bb85be09a4ad9
+Author: Tim Duesterhus <tim@bastelstu.be>
+Date:   Tue Apr 24 13:56:01 2018 +0200
+
+    BUG/MEDIUM: lua: Fix segmentation fault if a Lua task exits
+    
+    PiBa-NL reported that haproxy crashes with a segmentation fault
+    if a function registered using `core.register_task` returns.
+    
+    An example Lua script that reproduces the bug is:
+    
+      mytask = function()
+            core.Info("Stopping task")
+      end
+      core.register_task(mytask)
+    
+    The Valgrind output is as follows:
+    
+      ==6759== Process terminating with default action of signal 11 (SIGSEGV)
+      ==6759==  Access not within mapped region at address 0x20
+      ==6759==    at 0x5B60AA9: lua_sethook (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
+      ==6759==    by 0x430264: hlua_ctx_resume (hlua.c:1009)
+      ==6759==    by 0x43BB68: hlua_process_task (hlua.c:5525)
+      ==6759==    by 0x4FED0A: process_runnable_tasks (task.c:231)
+      ==6759==    by 0x4B2256: run_poll_loop (haproxy.c:2397)
+      ==6759==    by 0x4B2256: run_thread_poll_loop (haproxy.c:2459)
+      ==6759==    by 0x41A7E4: main (haproxy.c:3049)
+    
+    Add the missing `task = NULL` for the `HLUA_E_OK` case. The error cases
+    have been fixed as of 253e53e661c49fb9723535319cf511152bf09bc7 which
+    first was included in haproxy v1.8-dev3. This bugfix should be backported
+    to haproxy 1.8.
+    
+    (cherry picked from commit cd235c60425dbe66c9015a357369afacc4880211)
+    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
+
+diff --git a/src/hlua.c b/src/hlua.c
+index 4e759c7c..d4b7ce91 100644
+--- a/src/hlua.c
++++ b/src/hlua.c
+@@ -5528,6 +5528,7 @@ static struct task *hlua_process_task(struct task *task)
+ 		hlua_ctx_destroy(hlua);
+ 		task_delete(task);
+ 		task_free(task);
++		task = NULL;
+ 		break;
+ 
+ 	case HLUA_E_AGAIN: /* co process or timeout wake me later. */
diff --git a/net/haproxy/patches/0004-MINOR-h2-detect-presence-of-CONNECT-and-or-content-length.patch b/net/haproxy/patches/0004-MINOR-h2-detect-presence-of-CONNECT-and-or-content-length.patch
new file mode 100644
index 000000000..4369ff04a
--- /dev/null
+++ b/net/haproxy/patches/0004-MINOR-h2-detect-presence-of-CONNECT-and-or-content-length.patch
@@ -0,0 +1,147 @@
+commit a8bcc7dd3fe5aa615f21e795375ff9225f004498
+Author: Willy Tarreau <w@1wt.eu>
+Date:   Wed Apr 25 18:13:58 2018 +0200
+
+    MINOR: h2: detect presence of CONNECT and/or content-length
+    
+    We'll need this in order to support uploading chunks. The h2 to h1
+    converter checks for the presence of the content-length header field
+    as well as the CONNECT method and returns these information to the
+    caller. The caller indicates whether or not a body is detected for
+    the message (presence of END_STREAM or not). No transfer-encoding
+    header is emitted yet.
+    
+    (cherry picked from commit 174b06a572ef141f15d8b7ea64eb6b34ec4c9af1)
+    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
+
+diff --git a/include/common/h2.h b/include/common/h2.h
+index 65c5ab1c..576ed105 100644
+--- a/include/common/h2.h
++++ b/include/common/h2.h
+@@ -145,9 +145,15 @@ enum h2_err {
+ 	"\x0d\x0a\x53\x4d\x0d\x0a\x0d\x0a"
+ 
+ 
++/* some flags related to protocol parsing */
++#define H2_MSGF_BODY           0x0001    // a body is present
++#define H2_MSGF_BODY_CL        0x0002    // content-length is present
++#define H2_MSGF_BODY_TUNNEL    0x0004    // a tunnel is in use (CONNECT)
++
++
+ /* various protocol processing functions */
+ 
+-int h2_make_h1_request(struct http_hdr *list, char *out, int osize);
++int h2_make_h1_request(struct http_hdr *list, char *out, int osize, unsigned int *msgf);
+ 
+ /*
+  * Some helpful debugging functions.
+diff --git a/src/h2.c b/src/h2.c
+index 43ed7f3c..7d9ddd50 100644
+--- a/src/h2.c
++++ b/src/h2.c
+@@ -36,9 +36,10 @@
+  * stored in <phdr[]>. <fields> indicates what was found so far. This should be
+  * called once at the detection of the first general header field or at the end
+  * of the request if no general header field was found yet. Returns 0 on success
+- * or a negative error code on failure.
++ * or a negative error code on failure. Upon success, <msgf> is updated with a
++ * few H2_MSGF_* flags indicating what was found while parsing.
+  */
+-static int h2_prepare_h1_reqline(uint32_t fields, struct ist *phdr, char **ptr, char *end)
++static int h2_prepare_h1_reqline(uint32_t fields, struct ist *phdr, char **ptr, char *end, unsigned int *msgf)
+ {
+ 	char *out = *ptr;
+ 	int uri_idx = H2_PHDR_IDX_PATH;
+@@ -62,6 +63,7 @@ static int h2_prepare_h1_reqline(uint32_t fields, struct ist *phdr, char **ptr,
+ 		}
+ 		// otherwise OK ; let's use the authority instead of the URI
+ 		uri_idx = H2_PHDR_IDX_AUTH;
++		*msgf |= H2_MSGF_BODY_TUNNEL;
+ 	}
+ 	else if ((fields & (H2_PHDR_FND_METH|H2_PHDR_FND_SCHM|H2_PHDR_FND_PATH)) !=
+ 	         (H2_PHDR_FND_METH|H2_PHDR_FND_SCHM|H2_PHDR_FND_PATH)) {
+@@ -113,6 +115,10 @@ static int h2_prepare_h1_reqline(uint32_t fields, struct ist *phdr, char **ptr,
+  * for a max of <osize> bytes, and the amount of bytes emitted is returned. In
+  * case of error, a negative error code is returned.
+  *
++ * Upon success, <msgf> is filled with a few H2_MSGF_* flags indicating what
++ * was found while parsing. The caller must set it to zero in or H2_MSGF_BODY
++ * if a body is detected (!ES).
++ *
+  * The headers list <list> must be composed of :
+  *   - n.name != NULL, n.len  > 0 : literal header name
+  *   - n.name == NULL, n.len  > 0 : indexed pseudo header name number <n.len>
+@@ -124,7 +130,7 @@ static int h2_prepare_h1_reqline(uint32_t fields, struct ist *phdr, char **ptr,
+  * The Cookie header will be reassembled at the end, and for this, the <list>
+  * will be used to create a linked list, so its contents may be destroyed.
+  */
+-int h2_make_h1_request(struct http_hdr *list, char *out, int osize)
++int h2_make_h1_request(struct http_hdr *list, char *out, int osize, unsigned int *msgf)
+ {
+ 	struct ist phdr_val[H2_PHDR_NUM_ENTRIES];
+ 	char *out_end = out + osize;
+@@ -176,7 +182,7 @@ int h2_make_h1_request(struct http_hdr *list, char *out, int osize)
+ 		/* regular header field in (name,value) */
+ 		if (!(fields & H2_PHDR_FND_NONE)) {
+ 			/* no more pseudo-headers, time to build the request line */
+-			ret = h2_prepare_h1_reqline(fields, phdr_val, &out, out_end);
++			ret = h2_prepare_h1_reqline(fields, phdr_val, &out, out_end, msgf);
+ 			if (ret != 0)
+ 				goto leave;
+ 			fields |= H2_PHDR_FND_NONE;
+@@ -185,6 +191,10 @@ int h2_make_h1_request(struct http_hdr *list, char *out, int osize)
+ 		if (isteq(list[idx].n, ist("host")))
+ 			fields |= H2_PHDR_FND_HOST;
+ 
++		if ((*msgf & (H2_MSGF_BODY|H2_MSGF_BODY_TUNNEL|H2_MSGF_BODY_CL)) == H2_MSGF_BODY &&
++		    isteq(list[idx].n, ist("content-length")))
++			*msgf |= H2_MSGF_BODY_CL;
++
+ 		/* these ones are forbidden in requests (RFC7540#8.1.2.2) */
+ 		if (isteq(list[idx].n, ist("connection")) ||
+ 		    isteq(list[idx].n, ist("proxy-connection")) ||
+@@ -232,7 +242,7 @@ int h2_make_h1_request(struct http_hdr *list, char *out, int osize)
+ 
+ 	/* Let's dump the request now if not yet emitted. */
+ 	if (!(fields & H2_PHDR_FND_NONE)) {
+-		ret = h2_prepare_h1_reqline(fields, phdr_val, &out, out_end);
++		ret = h2_prepare_h1_reqline(fields, phdr_val, &out, out_end, msgf);
+ 		if (ret != 0)
+ 			goto leave;
+ 	}
+diff --git a/src/mux_h2.c b/src/mux_h2.c
+index 4fde7fcc..82dd414a 100644
+--- a/src/mux_h2.c
++++ b/src/mux_h2.c
+@@ -2626,6 +2626,7 @@ static int h2_frt_decode_headers(struct h2s *h2s, struct buffer *buf, int count)
+ 	struct chunk *tmp = get_trash_chunk();
+ 	struct http_hdr list[MAX_HTTP_HDR * 2];
+ 	struct chunk *copy = NULL;
++	unsigned int msgf;
+ 	int flen = h2c->dfl;
+ 	int outlen = 0;
+ 	int wrap;
+@@ -2727,13 +2728,22 @@ static int h2_frt_decode_headers(struct h2s *h2s, struct buffer *buf, int count)
+ 	}
+ 
+ 	/* OK now we have our header list in <list> */
+-	outlen = h2_make_h1_request(list, bi_end(buf), try);
++	msgf = (h2c->dff & H2_F_DATA_END_STREAM) ? 0 : H2_MSGF_BODY;
++	outlen = h2_make_h1_request(list, bi_end(buf), try, &msgf);
+ 
+ 	if (outlen < 0) {
+ 		h2c_error(h2c, H2_ERR_COMPRESSION_ERROR);
+ 		goto fail;
+ 	}
+ 
++	if (msgf & H2_MSGF_BODY) {
++		/* a payload is present */
++		if (msgf & H2_MSGF_BODY_CL)
++			h2s->flags |= H2_SF_DATA_CLEN;
++		else if (!(msgf & H2_MSGF_BODY_TUNNEL))
++			h2s->flags |= H2_SF_DATA_CHNK;
++	}
++
+ 	/* now consume the input data */
+ 	bi_del(h2c->dbuf, h2c->dfl);
+ 	h2c->st0 = H2_CS_FRAME_H;
diff --git a/net/haproxy/patches/0005-BUG-MEDIUM-h2-implement-missing-support-for-chunked-encoded-uploads.patch b/net/haproxy/patches/0005-BUG-MEDIUM-h2-implement-missing-support-for-chunked-encoded-uploads.patch
new file mode 100644
index 000000000..f2dc3e6f3
--- /dev/null
+++ b/net/haproxy/patches/0005-BUG-MEDIUM-h2-implement-missing-support-for-chunked-encoded-uploads.patch
@@ -0,0 +1,164 @@
+commit 05657bd24ebaf20e5c508a435be9a0830591f033
+Author: Willy Tarreau <w@1wt.eu>
+Date:   Wed Apr 25 20:44:22 2018 +0200
+
+    BUG/MEDIUM: h2: implement missing support for chunked encoded uploads
+    
+    Upload requests not carrying a content-length nor tunnelling data must
+    be sent chunked-encoded over HTTP/1. The code was planned but for some
+    reason forgotten during the implementation, leading to such payloads to
+    be sent as tunnelled data.
+    
+    Browsers always emit a content length in uploads so this problem doesn't
+    happen for most sites. However some applications may send data frames
+    after a request without indicating it earlier.
+    
+    The only way to detect that a client will need to send data is that the
+    HEADERS frame doesn't hold the ES bit. In this case it's wise to look
+    for the content-length header. If it's not there, either we're in tunnel
+    (CONNECT method) or chunked-encoding (other methods).
+    
+    This patch implements this.
+    
+    The following request is sent using content-length :
+    
+        curl --http2 -sk https://127.0.0.1:4443/s2 -XPOST -T /large/file
+    
+    and these ones using chunked-encoding :
+    
+        curl --http2 -sk https://127.0.0.1:4443/s2 -XPUT -T /large/file
+        curl --http2 -sk https://127.0.0.1:4443/s2 -XPUT -T - < /dev/urandom
+    
+    Thanks to Robert Samuel Newson for raising this issue with details.
+    This fix must be backported to 1.8.
+    
+    (cherry picked from commit eba10f24b7da27cde60d2db24aeb1147e1657579)
+    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
+
+diff --git a/src/h2.c b/src/h2.c
+index 7d9ddd50..5c83d6b6 100644
+--- a/src/h2.c
++++ b/src/h2.c
+@@ -262,6 +262,14 @@ int h2_make_h1_request(struct http_hdr *list, char *out, int osize, unsigned int
+ 		*(out++) = '\n';
+ 	}
+ 
++	if ((*msgf & (H2_MSGF_BODY|H2_MSGF_BODY_TUNNEL|H2_MSGF_BODY_CL)) == H2_MSGF_BODY) {
++		/* add chunked encoding */
++		if (out + 28 > out_end)
++			goto fail;
++		memcpy(out, "transfer-encoding: chunked\r\n", 28);
++		out += 28;
++	}
++
+ 	/* now we may have to build a cookie list. We'll dump the values of all
+ 	 * visited headers.
+ 	 */
+diff --git a/src/mux_h2.c b/src/mux_h2.c
+index 82dd414a..5f1da0df 100644
+--- a/src/mux_h2.c
++++ b/src/mux_h2.c
+@@ -2785,6 +2785,7 @@ static int h2_frt_transfer_data(struct h2s *h2s, struct buffer *buf, int count)
+ 	struct h2c *h2c = h2s->h2c;
+ 	int block1, block2;
+ 	unsigned int flen = h2c->dfl;
++	unsigned int chklen = 0;
+ 
+ 	h2s->cs->flags &= ~CS_FL_RCV_MORE;
+ 	h2c->flags &= ~H2_CF_DEM_SFULL;
+@@ -2820,14 +2821,35 @@ static int h2_frt_transfer_data(struct h2s *h2s, struct buffer *buf, int count)
+ 			return 0;
+ 	}
+ 
++	/* chunked-encoding requires more room */
++	if (h2s->flags & H2_SF_DATA_CHNK) {
++		chklen = MIN(flen, count);
++		chklen = (chklen < 16) ? 1 : (chklen < 256) ? 2 :
++			(chklen < 4096) ? 3 : (chklen < 65536) ? 4 :
++			(chklen < 1048576) ? 4 : 8;
++		chklen += 4; // CRLF, CRLF
++	}
++
+ 	/* does it fit in output buffer or should we wait ? */
+-	if (flen > count) {
+-		flen = count;
+-		if (!flen) {
+-			h2c->flags |= H2_CF_DEM_SFULL;
+-			h2s->cs->flags |= CS_FL_RCV_MORE;
+-			return 0;
+-		}
++	if (flen + chklen > count) {
++		if (chklen >= count)
++			goto full;
++		flen = count - chklen;
++	}
++
++	if (h2s->flags & H2_SF_DATA_CHNK) {
++		/* emit the chunk size */
++		unsigned int chksz = flen;
++		char str[10];
++		char *beg;
++
++		beg = str + sizeof(str);
++		*--beg = '\n';
++		*--beg = '\r';
++		do {
++			*--beg = hextab[chksz & 0xF];
++		} while (chksz >>= 4);
++		bi_putblk(buf, beg, str + sizeof(str) - beg);
+ 	}
+ 
+ 	/* Block1 is the length of the first block before the buffer wraps,
+@@ -2844,6 +2866,11 @@ static int h2_frt_transfer_data(struct h2s *h2s, struct buffer *buf, int count)
+ 	if (block2)
+ 		bi_putblk(buf, b_ptr(h2c->dbuf, block1), block2);
+ 
++	if (h2s->flags & H2_SF_DATA_CHNK) {
++		/* emit the CRLF */
++		bi_putblk(buf, "\r\n", 2);
++	}
++
+ 	/* now mark the input data as consumed (will be deleted from the buffer
+ 	 * by the caller when seeing FRAME_A after sending the window update).
+ 	 */
+@@ -2854,15 +2881,22 @@ static int h2_frt_transfer_data(struct h2s *h2s, struct buffer *buf, int count)
+ 
+ 	if (h2c->dfl > h2c->dpl) {
+ 		/* more data available, transfer stalled on stream full */
+-		h2c->flags |= H2_CF_DEM_SFULL;
+-		h2s->cs->flags |= CS_FL_RCV_MORE;
+-		return flen;
++		goto more;
+ 	}
+ 
+  end_transfer:
+ 	/* here we're done with the frame, all the payload (except padding) was
+ 	 * transferred.
+ 	 */
++
++	if (h2c->dff & H2_F_DATA_END_STREAM && h2s->flags & H2_SF_DATA_CHNK) {
++		/* emit the trailing 0 CRLF CRLF */
++		if (count < 5)
++			goto more;
++		chklen += 5;
++		bi_putblk(buf, "0\r\n\r\n", 5);
++	}
++
+ 	h2c->rcvd_c += h2c->dpl;
+ 	h2c->rcvd_s += h2c->dpl;
+ 	h2c->dpl = 0;
+@@ -2877,7 +2911,13 @@ static int h2_frt_transfer_data(struct h2s *h2s, struct buffer *buf, int count)
+ 		h2s->flags |= H2_SF_ES_RCVD;
+ 	}
+ 
+-	return flen;
++	return flen + chklen;
++ full:
++	flen = chklen = 0;
++ more:
++	h2c->flags |= H2_CF_DEM_SFULL;
++	h2s->cs->flags |= CS_FL_RCV_MORE;
++	return flen + chklen;
+ }
+ 
+ /*
diff --git a/net/haproxy/patches/0006-BUG-MINOR-lua-threads-Make-luas-tasks-sticky-to-the-current-thread.patch b/net/haproxy/patches/0006-BUG-MINOR-lua-threads-Make-luas-tasks-sticky-to-the-current-thread.patch
new file mode 100644
index 000000000..f6f9d55e5
--- /dev/null
+++ b/net/haproxy/patches/0006-BUG-MINOR-lua-threads-Make-luas-tasks-sticky-to-the-current-thread.patch
@@ -0,0 +1,36 @@
+commit 8b8d55be7e94ee3d758d41a21fa86a036e91a264
+Author: Christopher Faulet <cfaulet@haproxy.com>
+Date:   Wed Apr 25 10:34:45 2018 +0200
+
+    BUG/MINOR: lua/threads: Make lua's tasks sticky to the current thread
+    
+    PiBa-NL reported a bug with tasks registered in lua when HAProxy is started with
+    serveral threads. These tasks have not specific affinity with threads so they
+    can be woken up on any threads. So, it is impossbile for these tasks to handled
+    cosockets or applets, because cosockets and applets are sticky on the thread
+    which created them. It is forbbiden to manipulate a cosocket from another
+    thread.
+    
+    So to fix the bug, tasks registered in lua are now sticky to the current
+    thread. Because these tasks can be registered before threads creation, the
+    affinity is set the first time a lua's task is processed.
+    
+    This patch must be backported in HAProxy 1.8.
+    
+    (cherry picked from commit 5bc9972ed836517924eea91954d255d317a53418)
+    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
+
+diff --git a/src/hlua.c b/src/hlua.c
+index d4b7ce91..bd0b87e3 100644
+--- a/src/hlua.c
++++ b/src/hlua.c
+@@ -5513,6 +5513,9 @@ static struct task *hlua_process_task(struct task *task)
+ 	struct hlua *hlua = task->context;
+ 	enum hlua_exec status;
+ 
++	if (task->thread_mask == MAX_THREADS_MASK)
++		task_set_affinity(task, tid_bit);
++
+ 	/* If it is the first call to the task, we must initialize the
+ 	 * execution timeouts.
+ 	 */