summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaphael Zimmer <raphael.zimmer@tu-ilmenau.de>2026-05-27 16:06:17 +0200
committerIlya Dryomov <idryomov@gmail.com>2026-07-23 20:29:40 +0200
commit98917a499ec7064c14fc56d180a4fd636fc2784c (patch)
treeb15b3d4d8aae42db150494587e84a8ec8784c6e2
parent1590cf0329716306e948a8fc29f1d3ee87d3989f (diff)
downloadlinux-98917a499ec7064c14fc56d180a4fd636fc2784c.tar.gz
linux-98917a499ec7064c14fc56d180a4fd636fc2784c.tar.bz2
linux-98917a499ec7064c14fc56d180a4fd636fc2784c.zip
libceph: Fix multiplication overflow in decode_new_up_state_weight()
If a message of type CEPH_MSG_OSD_MAP contains a (maliciously) corrupted osdmap, out-of-bounds memory accesses may occur in decode_new_up_state_weight(). This happens because the bounds check for the new_state part is based on calculating its length depending on a len value read from the incoming message. This calculation may overflow leading to an incorrect bounds check. Subsequently, out-of-bounds reads may occur when decoding this part. This patch switches the multiplication to use check_mul_overflow() to abort processing the osdmap if an overflow occurred. Therefore, osdmaps/messages containing large values for len that result in a multiplication overflow are treated as invalid. [ idryomov: rename new_state_len -> new_state_item_size, formatting ] Cc: stable@vger.kernel.org Fixes: 930c53286977 ("libceph: apply new_state before new_up_client on incrementals") Signed-off-by: Raphael Zimmer <raphael.zimmer@tu-ilmenau.de> Reviewed-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
-rw-r--r--net/ceph/osdmap.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c
index 8b5b0587a0cf..8e77096718c4 100644
--- a/net/ceph/osdmap.c
+++ b/net/ceph/osdmap.c
@@ -1842,6 +1842,8 @@ static int decode_new_up_state_weight(void **p, void *end, u8 struct_v,
void *new_up_client;
void *new_state;
void *new_weight_end;
+ const u32 new_state_item_size =
+ sizeof(u32) + (struct_v >= 5 ? sizeof(u32) : sizeof(u8));
u32 len;
int ret;
int i;
@@ -1862,7 +1864,8 @@ static int decode_new_up_state_weight(void **p, void *end, u8 struct_v,
new_state = *p;
ceph_decode_32_safe(p, end, len, e_inval);
- len *= sizeof(u32) + (struct_v >= 5 ? sizeof(u32) : sizeof(u8));
+ if (check_mul_overflow(len, new_state_item_size, &len))
+ goto e_inval;
ceph_decode_need(p, end, len, e_inval);
*p += len;