]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MINOR: peers: compare the received expiration date as unsigned
authorFrederic Lecaille <flecaille@haproxy.com>
Fri, 23 Oct 2026 15:39:13 +0000 (17:39 +0200)
committerFrederic Lecaille <flecaille@haproxy.com>
Mon, 26 Oct 2026 10:39:41 +0000 (11:39 +0100)
The expiration date received in timed update messages is an unsigned
32-bit value on the wire, but it is stored into an int and compared with
the table's expire as a signed value. A value of 2^31 or more thus becomes
negative, is not capped to the table's expire, and results in an entry
expiring in the past, hence purged immediately, instead of being capped to
the table's expiration delay.

Let's compare it as unsigned.

Note that only a buggy or malicious peer sending such a value can reach this: a
compliant peer always sends tick_remain() of its own entry, which cannot
exceed its table's expire and is therefore below 2^31. The effect is
limited to the entry carried by the message, which never lives: it is
purged at the next expiration pass. But since peers are meant to keep
identical tables on every node, this lets such a peer make a chosen key
disappear prematurely on its neighbours, which is a divergence rather
than a local drop.

This can be backported to all stable versions.

src/peers.c

index f22f1599e938ad99caba18a321c89c046eda97cc..2ef410806c3bffce271fad5e23c5da47e032fbb6 100644 (file)
@@ -1871,8 +1871,10 @@ int peer_treat_updatemsg(struct appctx *appctx, struct peer *p, int updt, int ex
                memcpy(&expire, *msg_cur, expire_sz);
                *msg_cur += expire_sz;
                expire = ntohl(expire);
-               /* Protocol contains expire in MS, check if value is less than table config */
-               if (expire > table->expire)
+               /* Protocol contains expire in MS, check if value is less than
+                * table config. It's unsigned on the wire.
+                */
+               if ((uint)expire > (uint)table->expire)
                        expire = table->expire;
                /* the rest of the code considers expire as ticks and not MS */
                expire = MS_TO_TICKS(expire);