]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-client.git/commitdiff
libceph: Fix multiplication overflow in __decode_pg_upmap_items() testing
authorRaphael Zimmer <raphael.zimmer@tu-ilmenau.de>
Tue, 19 May 2026 11:01:30 +0000 (13:01 +0200)
committerIlya Dryomov <idryomov@gmail.com>
Wed, 20 May 2026 00:20:20 +0000 (02:20 +0200)
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 <raphael.zimmer@tu-ilmenau.de>
Reviewed-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
net/ceph/osdmap.c

index 8b5b0587a0cfa2c437b76c8c87251199efe20291..076763420b1d1de5173938cf87fd4eac4af44829 100644 (file)
@@ -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);