[PATCH] drbd: reject an out-of-range offset when decoding a compressed bitmap
From: Yehyeong Lee
Date: Mon Oct 05 2026 - 23:58:22 EST
recv_bm_rle_bits() decodes a run-length-encoded bitmap from the peer and
accumulates the bit position s across the runs. The upper bound
(e >= c->bm_bits) is only checked in the branch taken for a set-bits
(toggle) run, so a clear run advances s with no check at all. A peer can
make s run past the bitmap with a single run; it is stored in
c->bit_offset unvalidated, recv_bm_rle_bits() returns "not done"
(s != c->bm_bits), and receive_bitmap() goes on to the next packet.
The following plain P_BITMAP packet computes c->bm_words - c->word_offset,
which underflows once word_offset is past bm_words, and drbd_bm_merge_lel()
turns the result into an out-of-range word offset. drbd_bm_merge_lel()
only WARN_ON()s that and proceeds into bm_word_to_page_idx(), which
BUG_ON()s on the out-of-range page index. A malicious or buggy peer can
thus panic the node with a crafted bitmap during the bitmap exchange.
Reject a decoded offset that is past the bitmap. s == c->bm_bits is the
normal end-of-bitmap signal and must still be accepted, so bound with '>'.
Fixes: b411b3637fa7 ("The DRBD driver")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Yehyeong Lee <yhlee@xxxxxxxxxxxxxxxxxx>
---
drivers/block/drbd/drbd_receiver.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 2135c14354a85..b3da2bcb646a7 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -4559,6 +4559,11 @@ recv_bm_rle_bits(struct drbd_peer_device *peer_device,
have += bits;
}
+ if (s > c->bm_bits) {
+ drbd_err(peer_device, "bitmap overflow (s:%lu) while decoding bm RLE packet\n", s);
+ return -EIO;
+ }
+
c->bit_offset = s;
bm_xfer_ctx_bit_to_word_offset(c);
--
2.43.0