From 19e63d1e35eded5b730072898bc112fe3f4853f7 Mon Sep 17 00:00:00 2001 From: Raphael Zimmer Date: Tue, 19 May 2026 13:01:30 +0200 Subject: [PATCH] libceph: Fix multiplication overflow in __decode_pg_upmap_items() A message of type CEPH_MSG_OSD_MAP holds an OSD map, which typically contains a pg_upmap part at its end. When decoding this part in __decode_pg_upmap_items(), a len value is decoded from the message to determine the number of items and the size of the allocation needed for them. If the len value is greater than or equal to 2^31, an overflow occurs in the multiplication that is performed to determine the needed size of the incoming buffer to decode, as well as for the length of the allocation for the ceph_pg_mapping struct. Subsequently, this results in out-of-bounds writes (and reads) when decoding the incoming message fields into the ceph_pg_mapping struct. This patch fixes the issue by splitting the computation into multiple parts and storing the results in local variables of type size_t. This prevents the overflow by performing the multiplication in the appropriate data type and ensures that the result is calculated only once. Signed-off-by: Raphael Zimmer Reviewed-by: Viacheslav Dubeyko --- net/ceph/osdmap.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index 8b5b0587a0cf..076763420b1d 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c @@ -1615,13 +1615,16 @@ static struct ceph_pg_mapping *__decode_pg_upmap_items(void **p, void *end, { struct ceph_pg_mapping *pg; u32 len, i; + const size_t item_size = 2 * sizeof(u32); + size_t payload_len; ceph_decode_32_safe(p, end, len, e_inval); - if ((size_t)len > (SIZE_MAX - sizeof(*pg)) / (2 * sizeof(u32))) + if ((size_t)len > (SIZE_MAX - sizeof(*pg)) / item_size) return ERR_PTR(-EINVAL); - ceph_decode_need(p, end, 2 * len * sizeof(u32), e_inval); - pg = alloc_pg_mapping(2 * len * sizeof(u32)); + payload_len = len * item_size; + ceph_decode_need(p, end, payload_len, e_inval); + pg = alloc_pg_mapping(payload_len); if (!pg) return ERR_PTR(-ENOMEM); -- 2.47.3