Hi Willy,
On 2014/10/30 21:48, Willy Tarreau wrote:
Hi Godbach,
[ and first, sorry for not having yet responded to your
other mail about caching ]
Take it easy. :)
Yes, it looks fine to me, feel free to send a patch and tag it as BUG/MAJOR.
In the future we'll probably need to rework all these functions, they have
lived a lot since version 1.1...
Thanks!
Willy
Please check the attached for the patch.
--
Best Regards,
Godbach
>From 553f81769046f39a1047b70ac5505176bec50dec Mon Sep 17 00:00:00 2001
From: Godbach <[email protected]>
Date: Fri, 31 Oct 2014 13:16:37 +0800
Subject: [PATCH] BUG/MAJOR: buffer: check the space left is enough or not
when input data in a buffer is wrapped
HAProxy will crash with the following configuration:
global
...
tune.bufsize 1024
tune.maxrewrite 0
frontend xxx
...
backend yyy
...
cookie cookie insert maxidle 300s
If client sends a request of which object size is more than tune.bufsize (1024
bytes), HAProxy will crash.
After doing some debugging, the crash was caused by http_header_add_tail2() ->
buffer_insert_line2() while inserting cookie at the end of response header.
Part codes of buffer_insert_line2() are as below:
int buffer_insert_line2(struct buffer *b, char *pos, const char *str, int len)
{
int delta;
delta = len + 2;
if (bi_end(b) + delta >= b->data + b->size)
return 0; /* no space left */
/* first, protect the end of the buffer */
memmove(pos + delta, pos, bi_end(b) - pos);
...
}
Since tune.maxrewrite is 0, HAProxy can receive 1024 bytes once which is equals
to full buffer size. Under such condition, the buffer is full and bi_end(b)
will be wrapped to the start of buffer which pointed to b->data. As a result,
though there is no space left in buffer, the check condition
if (bi_end(b) + delta >= b->data + b->size)
will be true, then memmove() is called, and (pos + delta) will exceed the end
of buffer (b->data + b->size), HAProxy crashes
Just take buffer_replace2() as a reference, the other check when input data in
a buffer is wrapped should be also added into buffer_insert_line2().
This fix must be backported to 1.5.
Signed-off-by: Godbach <[email protected]>
---
src/buffer.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/src/buffer.c b/src/buffer.c
index 91bee63..9037dd3 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -88,6 +88,11 @@ int buffer_insert_line2(struct buffer *b, char *pos, const
char *str, int len)
if (bi_end(b) + delta >= b->data + b->size)
return 0; /* no space left */
+ if (buffer_not_empty(b) &&
+ bi_end(b) + delta > bo_ptr(b) &&
+ bo_ptr(b) >= bi_end(b))
+ return 0; /* no space left before wrapping data */
+
/* first, protect the end of the buffer */
memmove(pos + delta, pos, bi_end(b) - pos);
--
1.7.7