packages/net/haproxy/patches/0001-BUG-MAJOR-backend-consistent-hash-can-loop-forever-i.patch
heil 58262c6392 package: haproxy
- update to 1.4.23 
   -  (CVE-2013-1912)
   -  fixup for consistent hash 
   -  refresh accept-proxy patch



git-svn-id: svn://svn.openwrt.org/openwrt/packages@36337 3c298f89-4303-0410-b956-a3cf2f4a3e73
2013-04-15 14:38:07 +00:00

58 lines
2.3 KiB
Diff

From d16a1b2a818359e8c3ade85f789e66ed7ca9488c Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Fri, 12 Apr 2013 14:46:51 +0200
Subject: BUG/MAJOR: backend: consistent hash can loop forever in certain
circumstances
When the parameter passed to a consistent hash is not found, we fall back to
round-robin using chash_get_next_server(). This one stores the last visited
server in lbprm.chash.last, which can be NULL upon the first invocation or if
the only server was recently brought up.
The loop used to scan for a server is able to skip the previously attempted
server in case of a redispatch, by passing this previous server in srvtoavoid.
For this reason, the loop stops when the currently considered server is
different from srvtoavoid and different from the original chash.last.
A problem happens in a special sequence : if a connection to a server fails,
then all servers are removed from the farm, then the original server is added
again before the redispatch happens, we have chash.last = NULL and srvtoavoid
set to the only server in the farm. Then this server is always equal to
srvtoavoid and never to NULL, and the loop never stops.
The fix consists in assigning the stop point to the first encountered node if
it was not yet set.
This issue cannot happen with the map-based algorithm since it's based on an
index and not a stop point.
This issue was reported by Henry Qian who kindly provided lots of critically
useful information to figure out the conditions to reproduce the issue.
The fix needs to be backported to 1.4 which is also affected.
---
src/lb_chash.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/lb_chash.c b/src/lb_chash.c
index 58f1c9e..d65de74 100644
--- a/src/lb_chash.c
+++ b/src/lb_chash.c
@@ -332,6 +332,13 @@ struct server *chash_get_next_server(struct proxy *p, struct server *srvtoavoid)
/* no node is available */
return NULL;
+ /* Note: if we came here after a down/up cycle with no last
+ * pointer, and after a redispatch (srvtoavoid is set), we
+ * must set stop to non-null otherwise we can loop forever.
+ */
+ if (!stop)
+ stop = node;
+
/* OK, we have a server. However, it may be saturated, in which
* case we don't want to reconsider it for now, so we'll simply
* skip it. Same if it's the server we try to avoid, in which
--
1.7.12.4.dirty