|
From 3f34b5539e7ba31e44055d853b9ba496e73e0bae Mon Sep 17 00:00:00 2001
|
|
From: Willy Tarreau <w@1wt.eu>
|
|
Date: Mon, 7 Sep 2015 19:32:33 +0200
|
|
Subject: [PATCH 15/16] BUG/MAJOR: http: don't call http_send_name_header()
|
|
after an error
|
|
|
|
A crash was reported when using the "famous" http-send-name-header
|
|
directive. This time it's a bit tricky, it requires a certain number of
|
|
conditions to be met including maxconn on a server, queuing, timeout in
|
|
the queue and cookie-based persistence.
|
|
|
|
The problem is that in stream.c, before calling http_send_name_header(),
|
|
we check a number of conditions to know if we have to replace the header
|
|
name. But prior to reaching this place, it's possible for
|
|
sess_update_stream_int() to fail and change the stream-int's state to
|
|
SI_ST_CLO, send an error 503 to the client, and flush all buffers. But
|
|
http_send_name_header() can only be called with valid buffer contents
|
|
matching the http_msg's description. So when it rewinds the stream to
|
|
modify the header, buf->o becomes negative by the size of the incoming
|
|
request and is used as the argument to memmove() which basically
|
|
displaces 4GB of memory off a few bytes to write the new name, resulting
|
|
in a core and a core file that's really not fun to play with.
|
|
|
|
The solution obviously consists in refraining from calling this nasty
|
|
function when the stream interface is already closed.
|
|
|
|
This bug also affects 1.5 and possibly 1.4, so the fix must be backported
|
|
there.
|
|
(cherry picked from commit 9c03b33329cb4924716edc1c851913a18b0670dc)
|
|
---
|
|
src/session.c | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/src/session.c b/src/session.c
|
|
index 6d62e36..7520a85 100644
|
|
--- a/src/session.c
|
|
+++ b/src/session.c
|
|
@@ -2293,7 +2293,7 @@ struct task *process_session(struct task *t)
|
|
|
|
/* Now we can add the server name to a header (if requested) */
|
|
/* check for HTTP mode and proxy server_name_hdr_name != NULL */
|
|
- if ((s->si[1].state >= SI_ST_CON) &&
|
|
+ if ((s->si[1].state >= SI_ST_CON) && (s->si[1].state < SI_ST_CLO) &&
|
|
(s->be->server_id_hdr_name != NULL) &&
|
|
(s->be->mode == PR_MODE_HTTP) &&
|
|
objt_server(s->target)) {
|
|
--
|
|
2.4.6
|
|
|