mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-01-13 09:11:06 +00:00
BUG/MEDIUM: checks: do not dereference a list as a tcpcheck struct
The method used to skip to next rule in the list is wrong, it assumes that the list element starts at the same offset as the rule. It happens to be true on most architectures since the list is the first element for now but it's definitely wrong. Now the code doesn't crash anymore when the struct list is moved anywhere else in the struct tcpcheck_rule. This fix must be backported to 1.5.
This commit is contained in:
parent
f2c87353a7
commit
5581c27b57
@ -4706,24 +4706,20 @@ stats_error_parsing:
|
||||
const char *ptr_arg;
|
||||
int cur_arg;
|
||||
struct tcpcheck_rule *tcpcheck;
|
||||
struct list *l;
|
||||
|
||||
/* check if first rule is also a 'connect' action */
|
||||
l = (struct list *)&curproxy->tcpcheck_rules;
|
||||
if (l->p != l->n) {
|
||||
tcpcheck = (struct tcpcheck_rule *)l->n;
|
||||
while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
|
||||
tcpcheck->action == TCPCHK_ACT_COMMENT) {
|
||||
tcpcheck = (struct tcpcheck_rule *)tcpcheck->list.n;
|
||||
}
|
||||
tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
|
||||
while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
|
||||
tcpcheck->action == TCPCHK_ACT_COMMENT) {
|
||||
tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
|
||||
}
|
||||
|
||||
if (&tcpcheck->list != &curproxy->tcpcheck_rules
|
||||
&& tcpcheck->action != TCPCHK_ACT_CONNECT) {
|
||||
Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
|
||||
file, linenum);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
if (&tcpcheck->list != &curproxy->tcpcheck_rules
|
||||
&& tcpcheck->action != TCPCHK_ACT_CONNECT) {
|
||||
Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
|
||||
file, linenum);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cur_arg = 2;
|
||||
|
25
src/checks.c
25
src/checks.c
@ -1476,7 +1476,10 @@ static int connect_conn_chk(struct task *t)
|
||||
quickack = check->type == 0 || check->type == PR_O2_TCPCHK_CHK;
|
||||
|
||||
if (check->type == PR_O2_TCPCHK_CHK && !LIST_ISEMPTY(check->tcpcheck_rules)) {
|
||||
struct tcpcheck_rule *r = (struct tcpcheck_rule *) check->tcpcheck_rules->n;
|
||||
struct tcpcheck_rule *r;
|
||||
|
||||
r = LIST_NEXT(check->tcpcheck_rules, struct tcpcheck_rule *, list);
|
||||
|
||||
/* if first step is a 'connect', then tcpcheck_main must run it */
|
||||
if (r->action == TCPCHK_ACT_CONNECT) {
|
||||
tcpcheck_main(conn);
|
||||
@ -2519,11 +2522,11 @@ static void tcpcheck_main(struct connection *conn)
|
||||
/* have 'next' point to the next rule or NULL if we're on the
|
||||
* last one, connect() needs this.
|
||||
*/
|
||||
next = (struct tcpcheck_rule *)check->current_step->list.n;
|
||||
next = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
|
||||
|
||||
/* bypass all comment rules */
|
||||
while (&next->list != head && next->action == TCPCHK_ACT_COMMENT)
|
||||
next = (struct tcpcheck_rule *)next->list.n;
|
||||
next = LIST_NEXT(&next->list, struct tcpcheck_rule *, list);
|
||||
|
||||
/* NULL if we're on the last rule */
|
||||
if (&next->list == head)
|
||||
@ -2633,12 +2636,12 @@ static void tcpcheck_main(struct connection *conn)
|
||||
}
|
||||
|
||||
/* allow next rule */
|
||||
check->current_step = (struct tcpcheck_rule *)check->current_step->list.n;
|
||||
check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
|
||||
|
||||
/* bypass all comment rules */
|
||||
while (&check->current_step->list != head &&
|
||||
check->current_step->action == TCPCHK_ACT_COMMENT)
|
||||
check->current_step = (struct tcpcheck_rule *)check->current_step->list.n;
|
||||
check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
|
||||
|
||||
if (&check->current_step->list == head)
|
||||
break;
|
||||
@ -2695,12 +2698,12 @@ static void tcpcheck_main(struct connection *conn)
|
||||
*check->bo->p = '\0'; /* to make gdb output easier to read */
|
||||
|
||||
/* go to next rule and try to send */
|
||||
check->current_step = (struct tcpcheck_rule *)check->current_step->list.n;
|
||||
check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
|
||||
|
||||
/* bypass all comment rules */
|
||||
while (&check->current_step->list != head &&
|
||||
check->current_step->action == TCPCHK_ACT_COMMENT)
|
||||
check->current_step = (struct tcpcheck_rule *)check->current_step->list.n;
|
||||
check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
|
||||
|
||||
if (&check->current_step->list == head)
|
||||
break;
|
||||
@ -2794,12 +2797,12 @@ static void tcpcheck_main(struct connection *conn)
|
||||
/* matched and was supposed to => OK, next step */
|
||||
else {
|
||||
/* allow next rule */
|
||||
check->current_step = (struct tcpcheck_rule *)check->current_step->list.n;
|
||||
check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
|
||||
|
||||
/* bypass all comment rules */
|
||||
while (&check->current_step->list != head &&
|
||||
check->current_step->action == TCPCHK_ACT_COMMENT)
|
||||
check->current_step = (struct tcpcheck_rule *)check->current_step->list.n;
|
||||
check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
|
||||
|
||||
if (&check->current_step->list == head)
|
||||
break;
|
||||
@ -2814,12 +2817,12 @@ static void tcpcheck_main(struct connection *conn)
|
||||
/* not matched and was not supposed to => OK, next step */
|
||||
if (check->current_step->inverse) {
|
||||
/* allow next rule */
|
||||
check->current_step = (struct tcpcheck_rule *)check->current_step->list.n;
|
||||
check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
|
||||
|
||||
/* bypass all comment rules */
|
||||
while (&check->current_step->list != head &&
|
||||
check->current_step->action == TCPCHK_ACT_COMMENT)
|
||||
check->current_step = (struct tcpcheck_rule *)check->current_step->list.n;
|
||||
check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
|
||||
|
||||
if (&check->current_step->list == head)
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user