]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: bwlim: Be sure to never set the analyze expiration date in past
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 9 Jul 2024 16:51:43 +0000 (18:51 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 11 Jul 2024 12:51:23 +0000 (14:51 +0200)
Every time a bandwidth limitation is evaluated on a channel, the analyze
expiration date is renewed, mainly based on the internal bandwidth
limitation filter expiration date. However, when the filter is called while
there is no data to filter, we skip all limitation computations to jump at
the end of the function. At this stage, the analyze expiration date is
renewed before exiting. But here the internal expiration date may be expired
and not reset.

To sum up, it is possible to set the analyze expiration date of a channel in
the past. It is unexpected and this could lead to a loop in process_stream.

To fix the issue, we just now take care to reset the internal expiration
date, if needed, before exiting.

This patch should fix the issue #2634. It must be backported as far as 2.8.

src/flt_bwlim.c

index c5078c8419000f3537084c1ba498507668963986..11eb2484a9e2aa2bb5f22cc2611b69454ff494ee 100644 (file)
@@ -85,10 +85,13 @@ static int bwlim_apply_limit(struct filter *filter, struct channel *chn, unsigne
        /* Don't forward anything if there is nothing to forward or the waiting
         * time is not expired
         */
-       if (!len || (tick_isset(st->exp) && !tick_is_expired(st->exp, now_ms)))
+       if (tick_isset(st->exp) && !tick_is_expired(st->exp, now_ms))
                goto end;
 
        st->exp = TICK_ETERNITY;
+       if (!len)
+               goto end;
+
        ret = len;
        if (conf->flags & BWLIM_FL_SHARED) {
                void *ptr;
@@ -177,6 +180,7 @@ static int bwlim_apply_limit(struct filter *filter, struct channel *chn, unsigne
   end:
        chn->analyse_exp = tick_first((tick_is_expired(chn->analyse_exp, now_ms) ? TICK_ETERNITY : chn->analyse_exp),
                                      st->exp);
+       BUG_ON(tick_is_expired(chn->analyse_exp, now_ms));
        return ret;
 }