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.
This commit is contained in:
Christopher Faulet 2020-02-10 09:54:49 +01:00
parent 696f317f13
commit 67307796e6
1 changed files with 18 additions and 10 deletions

View File

@ -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;