From 449f952cb3fa17f2b3197ccc7cf327ca5c316967 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 13 May 2015 15:39:48 +0200 Subject: [PATCH] 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. --- src/checks.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/checks.c b/src/checks.c index 9b0964508..8d8c31c80 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);