From 67307796e63ec45a024de6fa4368cc749d527b98 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Mon, 10 Feb 2020 09:54:49 +0100 Subject: [PATCH] BUG/MEDIUM: tcp-rules: Fix track-sc* actions for L4/L5 TCP rules A bug was introduced during TCP rules refactoring by the commit ac98d81f4 ("MINOR: http-rule/tcp-rules: Make track-sc* custom actions"). There is no stream when L4/L5 TCP rules are evaluated. For these rulesets, In track-sc* actions, we must take care to rely on the session instead of the stream. Because of this bug, any evaluation of L4/L5 TCP rules using a track-sc* action leads to a crash of HAProxy. No backport needed, except if the above commit is backported. --- src/tcp_rules.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/tcp_rules.c b/src/tcp_rules.c index f56129ae13..7eb5659140 100644 --- a/src/tcp_rules.c +++ b/src/tcp_rules.c @@ -635,27 +635,35 @@ static enum act_return tcp_action_track_sc(struct act_rule *rule, struct proxy * struct sample smp; int opt; - opt = ((rule->from == ACT_F_TCP_REQ_CNT) ? SMP_OPT_DIR_REQ : SMP_OPT_DIR_RES); + opt = SMP_OPT_DIR_REQ; if (flags & ACT_FLAG_FINAL) opt |= SMP_OPT_FINAL; - if (stkctr_entry(&s->stkctr[rule->action])) - goto end; - t = rule->arg.trk_ctr.table.t; - key = stktable_fetch_key(t, s->be, sess, s, opt, rule->arg.trk_ctr.expr, &smp); + if (rule->from == ACT_F_TCP_REQ_CNT) { /* L7 rules: use the stream */ + if (stkctr_entry(&s->stkctr[rule->action])) + goto end; - if ((smp.flags & SMP_F_MAY_CHANGE) && !(flags & ACT_FLAG_FINAL)) - return ACT_RET_YIELD; /* key might appear later */ + key = stktable_fetch_key(t, s->be, sess, s, opt, rule->arg.trk_ctr.expr, &smp); - if (key && (ts = stktable_get_entry(t, key))) { - stream_track_stkctr(&s->stkctr[rule->action], t, ts); - if (rule->from == ACT_F_TCP_REQ_CNT) { + if ((smp.flags & SMP_F_MAY_CHANGE) && !(flags & ACT_FLAG_FINAL)) + return ACT_RET_YIELD; /* key might appear later */ + + if (key && (ts = stktable_get_entry(t, key))) { + stream_track_stkctr(&s->stkctr[rule->action], t, ts); stkctr_set_flags(&s->stkctr[rule->action], STKCTR_TRACK_CONTENT); if (sess->fe != s->be) stkctr_set_flags(&s->stkctr[rule->action], STKCTR_TRACK_BACKEND); } } + else { /* L4/L5 rules: use the session */ + if (stkctr_entry(&sess->stkctr[rule->action])) + goto end; + + key = stktable_fetch_key(t, sess->fe, sess, NULL, opt, rule->arg.trk_ctr.expr, NULL); + if (key && (ts = stktable_get_entry(t, key))) + stream_track_stkctr(&sess->stkctr[rule->action], t, ts); + } end: return ACT_RET_CONT;