|
 |
d58b22 |
From b4d05093bc89f71377230228007e69a1434c1a0c Mon Sep 17 00:00:00 2001
|
|
 |
d58b22 |
From: Willy Tarreau <w@1wt.eu>
|
|
 |
d58b22 |
Date: Mon, 1 Sep 2014 20:35:55 +0200
|
|
 |
d58b22 |
Subject: [PATCH] BUG/CRITICAL: http: don't update msg->sov once data start to
|
|
 |
d58b22 |
leave the buffer
|
|
 |
d58b22 |
|
|
 |
d58b22 |
Commit bb2e669 ("BUG/MAJOR: http: correctly rewind the request body
|
|
 |
d58b22 |
after start of forwarding") was incorrect/incomplete. It used to rely on
|
|
 |
d58b22 |
CF_READ_ATTACHED to stop updating msg->sov once data start to leave the
|
|
 |
d58b22 |
buffer, but this is unreliable because since commit a6eebb3 ("[BUG]
|
|
 |
d58b22 |
session: clear BF_READ_ATTACHED before next I/O") merged in 1.5-dev1,
|
|
 |
d58b22 |
this flag is only ephemeral and is cleared once all analysers have
|
|
 |
d58b22 |
seen it. So we can start updating msg->sov again each time we pass
|
|
 |
d58b22 |
through this place with new data. With a sufficiently large amount of
|
|
 |
d58b22 |
data, it is possible to make msg->sov wrap and validate the if()
|
|
 |
d58b22 |
condition at the top, causing the buffer to advance by about 2GB and
|
|
 |
d58b22 |
crash the process.
|
|
 |
d58b22 |
|
|
 |
d58b22 |
Note that the offset cannot be controlled by the attacker because it is
|
|
 |
d58b22 |
a sum of millions of small random sizes depending on how many bytes were
|
|
 |
d58b22 |
read by the server and how many were left in the buffer, only because
|
|
 |
d58b22 |
of the speed difference between reading and writing. Also, nothing is
|
|
 |
d58b22 |
written, the invalid pointer resulting from this operation is only read.
|
|
 |
d58b22 |
|
|
 |
d58b22 |
Many thanks to James Dempsey for reporting this bug and to Chris Forbes for
|
|
 |
d58b22 |
narrowing down the faulty area enough to make its root cause analysable.
|
|
 |
d58b22 |
|
|
 |
d58b22 |
This fix must be backported to haproxy 1.5.
|
|
 |
d58b22 |
(cherry picked from commit a2d002aeb669a9bbca2dcd3e6be71615f435e9e6)
|
|
 |
d58b22 |
---
|
|
 |
d58b22 |
include/types/channel.h | 2 +-
|
|
 |
d58b22 |
src/proto_http.c | 8 ++++----
|
|
 |
d58b22 |
src/stream_interface.c | 4 ++--
|
|
 |
d58b22 |
3 files changed, 7 insertions(+), 7 deletions(-)
|
|
 |
d58b22 |
|
|
 |
d58b22 |
diff --git a/include/types/channel.h b/include/types/channel.h
|
|
 |
d58b22 |
index 88a52a4..8bc3958 100644
|
|
 |
d58b22 |
--- a/include/types/channel.h
|
|
 |
d58b22 |
+++ b/include/types/channel.h
|
|
 |
d58b22 |
@@ -105,7 +105,7 @@
|
|
 |
d58b22 |
#define CF_STREAMER 0x00010000 /* the producer is identified as streaming data */
|
|
 |
d58b22 |
#define CF_STREAMER_FAST 0x00020000 /* the consumer seems to eat the stream very fast */
|
|
 |
d58b22 |
|
|
 |
d58b22 |
-/* unused: 0x00040000 */
|
|
 |
d58b22 |
+#define CF_WROTE_DATA 0x00040000 /* some data were sent from this buffer */
|
|
 |
d58b22 |
#define CF_ANA_TIMEOUT 0x00080000 /* the analyser timeout has expired */
|
|
 |
d58b22 |
#define CF_READ_ATTACHED 0x00100000 /* the read side is attached for the first time */
|
|
 |
d58b22 |
#define CF_KERN_SPLICING 0x00200000 /* kernel splicing desired for this channel */
|
|
 |
d58b22 |
diff --git a/src/proto_http.c b/src/proto_http.c
|
|
 |
d58b22 |
index a47f0a1..4d27b2c 100644
|
|
 |
d58b22 |
--- a/src/proto_http.c
|
|
 |
d58b22 |
+++ b/src/proto_http.c
|
|
 |
d58b22 |
@@ -4886,8 +4886,8 @@ void http_end_txn_clean_session(struct session *s)
|
|
 |
d58b22 |
s->req->cons->conn_retries = 0; /* used for logging too */
|
|
 |
d58b22 |
s->req->cons->exp = TICK_ETERNITY;
|
|
 |
d58b22 |
s->req->cons->flags &= SI_FL_DONT_WAKE; /* we're in the context of process_session */
|
|
 |
d58b22 |
- s->req->flags &= ~(CF_SHUTW|CF_SHUTW_NOW|CF_AUTO_CONNECT|CF_WRITE_ERROR|CF_STREAMER|CF_STREAMER_FAST|CF_NEVER_WAIT|CF_WAKE_CONNECT);
|
|
 |
d58b22 |
- s->rep->flags &= ~(CF_SHUTR|CF_SHUTR_NOW|CF_READ_ATTACHED|CF_READ_ERROR|CF_READ_NOEXP|CF_STREAMER|CF_STREAMER_FAST|CF_WRITE_PARTIAL|CF_NEVER_WAIT);
|
|
 |
d58b22 |
+ s->req->flags &= ~(CF_SHUTW|CF_SHUTW_NOW|CF_AUTO_CONNECT|CF_WRITE_ERROR|CF_STREAMER|CF_STREAMER_FAST|CF_NEVER_WAIT|CF_WAKE_CONNECT|CF_WROTE_DATA);
|
|
 |
d58b22 |
+ s->rep->flags &= ~(CF_SHUTR|CF_SHUTR_NOW|CF_READ_ATTACHED|CF_READ_ERROR|CF_READ_NOEXP|CF_STREAMER|CF_STREAMER_FAST|CF_WRITE_PARTIAL|CF_NEVER_WAIT|CF_WROTE_DATA);
|
|
 |
d58b22 |
s->flags &= ~(SN_DIRECT|SN_ASSIGNED|SN_ADDR_SET|SN_BE_ASSIGNED|SN_FORCE_PRST|SN_IGNORE_PRST);
|
|
 |
d58b22 |
s->flags &= ~(SN_CURR_SESS|SN_REDIRECTABLE|SN_SRV_REUSED);
|
|
 |
d58b22 |
|
|
 |
d58b22 |
@@ -5430,7 +5430,7 @@ int http_request_forward_body(struct session *s, struct channel *req, int an_bit
|
|
 |
d58b22 |
* such as last chunk of data or trailers.
|
|
 |
d58b22 |
*/
|
|
 |
d58b22 |
b_adv(req->buf, msg->next);
|
|
 |
d58b22 |
- if (unlikely(!(s->rep->flags & CF_READ_ATTACHED)))
|
|
 |
d58b22 |
+ if (unlikely(!(s->req->flags & CF_WROTE_DATA)))
|
|
 |
d58b22 |
msg->sov -= msg->next;
|
|
 |
d58b22 |
msg->next = 0;
|
|
 |
d58b22 |
|
|
 |
d58b22 |
@@ -5482,7 +5482,7 @@ int http_request_forward_body(struct session *s, struct channel *req, int an_bit
|
|
 |
d58b22 |
missing_data:
|
|
 |
d58b22 |
/* we may have some pending data starting at req->buf->p */
|
|
 |
d58b22 |
b_adv(req->buf, msg->next);
|
|
 |
d58b22 |
- if (unlikely(!(s->rep->flags & CF_READ_ATTACHED)))
|
|
 |
d58b22 |
+ if (unlikely(!(s->req->flags & CF_WROTE_DATA)))
|
|
 |
d58b22 |
msg->sov -= msg->next + MIN(msg->chunk_len, req->buf->i);
|
|
 |
d58b22 |
|
|
 |
d58b22 |
msg->next = 0;
|
|
 |
d58b22 |
diff --git a/src/stream_interface.c b/src/stream_interface.c
|
|
 |
d58b22 |
index 67a5234..9f7e979 100644
|
|
 |
d58b22 |
--- a/src/stream_interface.c
|
|
 |
d58b22 |
+++ b/src/stream_interface.c
|
|
 |
d58b22 |
@@ -658,7 +658,7 @@ static void si_conn_send(struct connection *conn)
|
|
 |
d58b22 |
if (chn->pipe && conn->xprt->snd_pipe) {
|
|
 |
d58b22 |
ret = conn->xprt->snd_pipe(conn, chn->pipe);
|
|
 |
d58b22 |
if (ret > 0)
|
|
 |
d58b22 |
- chn->flags |= CF_WRITE_PARTIAL;
|
|
 |
d58b22 |
+ chn->flags |= CF_WRITE_PARTIAL | CF_WROTE_DATA;
|
|
 |
d58b22 |
|
|
 |
d58b22 |
if (!chn->pipe->data) {
|
|
 |
d58b22 |
put_pipe(chn->pipe);
|
|
 |
d58b22 |
@@ -702,7 +702,7 @@ static void si_conn_send(struct connection *conn)
|
|
 |
d58b22 |
|
|
 |
d58b22 |
ret = conn->xprt->snd_buf(conn, chn->buf, send_flag);
|
|
 |
d58b22 |
if (ret > 0) {
|
|
 |
d58b22 |
- chn->flags |= CF_WRITE_PARTIAL;
|
|
 |
d58b22 |
+ chn->flags |= CF_WRITE_PARTIAL | CF_WROTE_DATA;
|
|
 |
d58b22 |
|
|
 |
d58b22 |
if (!chn->buf->o) {
|
|
 |
d58b22 |
/* Always clear both flags once everything has been sent, they're one-shot */
|
|
 |
d58b22 |
--
|
|
 |
d58b22 |
1.9.3
|
|
 |
d58b22 |
|