Skip to content

Commit 8e77fe0

Browse files
ecsvgregkh
authored andcommitted
batman-adv: tp_meter: avoid window underflow
commit 765947b upstream. In batadv_tp_avail(), win_left is calculated with 32-bit unsigned arithmetic: win_left = win_limit - tp_vars->last_sent; During Fast Recovery, cwnd is inflated and last_sent advances rapidly. When Fast Recovery ends, cwnd drops abruptly back to ss_threshold. If the newly shrunk win_limit is less than last_sent, the unsigned subtraction will underflow, wrapping to a massive positive value. Instead of returning that the window is full (unavailable), it returns that the sender can continue sending. To handle this situation, it must be checked whether the windows end sequence number (win_limit) has to be compared with the last sent sequence number. If it would be before the last sent sequence number, then more acks are needed before the transmission can be started again. Cc: stable@kernel.org Fixes: 33a3bb4 ("batman-adv: throughput meter implementation") Signed-off-by: Sven Eckelmann <sven@narfation.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 7cb88d9 commit 8e77fe0

1 file changed

Lines changed: 6 additions & 1 deletion

File tree

net/batman-adv/tp_meter.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -817,10 +817,15 @@ static void batadv_tp_recv_ack(struct batadv_priv *bat_priv,
817817
static bool batadv_tp_avail(struct batadv_tp_vars *tp_vars,
818818
size_t payload_len)
819819
{
820+
u32 last_sent = READ_ONCE(tp_vars->last_sent);
820821
u32 win_left, win_limit;
821822

822823
win_limit = atomic_read(&tp_vars->last_acked) + tp_vars->cwnd;
823-
win_left = win_limit - tp_vars->last_sent;
824+
825+
if (batadv_seq_before(last_sent, win_limit))
826+
win_left = win_limit - last_sent;
827+
else
828+
win_left = 0;
824829

825830
return win_left >= payload_len;
826831
}

0 commit comments

Comments
 (0)