From: Willy Tarreau Date: Wed, 13 May 2015 13:39:48 +0000 (+0200) Subject: BUG/MAJOR: checks: break infinite loops when tcp-checks starts with comment X-Git-Tag: v1.6-dev2~111 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=449f952cb3fa17f2b3197ccc7cf327ca5c316967;p=thirdparty%2Fhaproxy.git BUG/MAJOR: checks: break infinite loops when tcp-checks starts with comment If a tcp-check sequence starts with "comment", then the action is not matched in the while() loop and the pointer doesn't advance so we face an endless loop. It is normally detected early except in the case where very slow checks are performed causing it to trigger after the admin stops watching. This bug is 1.6-only and very recent so it didn't have the time to affect anyone. --- diff --git a/src/checks.c b/src/checks.c index 9b09645086..8d8c31c803 100644 --- a/src/checks.c +++ b/src/checks.c @@ -2455,8 +2455,14 @@ static void tcpcheck_main(struct connection *conn) * wait for a connection to complete unless we're before and existing * step 1. */ + + /* find first rule and skip comments */ + next = LIST_NEXT(head, struct tcpcheck_rule *, list); + while (&next->list != head && next->action == TCPCHK_ACT_COMMENT) + next = LIST_NEXT(&next->list, struct tcpcheck_rule *, list); + if ((!(conn->flags & CO_FL_CONNECTED) || (conn->flags & CO_FL_HANDSHAKE)) && - (check->current_step || LIST_ISEMPTY(head))) { + (check->current_step || &next->list == head)) { /* we allow up to min(inter, timeout.connect) for a connection * to establish but only when timeout.check is set * as it may be to short for a full check otherwise @@ -2474,7 +2480,7 @@ static void tcpcheck_main(struct connection *conn) } /* special case: option tcp-check with no rule, a connect is enough */ - if (LIST_ISEMPTY(head)) { + if (&next->list == head) { set_server_check_status(check, HCHK_STATUS_L4OK, NULL); goto out_end_tcpcheck; } @@ -2486,7 +2492,7 @@ static void tcpcheck_main(struct connection *conn) check->bo->o = 0; check->bi->p = check->bi->data; check->bi->i = 0; - check->current_step = LIST_ELEM(head->n, struct tcpcheck_rule *, list); + check->current_step = next; t->expire = tick_add(now_ms, MS_TO_TICKS(check->inter)); if (s->proxy->timeout.check) t->expire = tick_add_ifset(now_ms, s->proxy->timeout.check);