]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: tcp-rules: Fix track-sc* actions for L4/L5 TCP rules
authorChristopher Faulet <cfaulet@haproxy.com>
Mon, 10 Feb 2020 08:54:49 +0000 (09:54 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 10 Feb 2020 09:09:58 +0000 (10:09 +0100)
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

index f56129ae135c585d843c5b447d4a11d0967e3ec4..7eb5659140c17f3e870ec8bc5b0869046139e283 100644 (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;