Re: [PATCH v3] libceph: Fix multiplication overflow in __decode_pg_upmap_items()

Raphael Zimmer <[email protected]> Mon, 27 Jul 2026 10:47:23 +0200
Newsgroups org.kernel.vger.ceph-devel
Message-ID <[email protected]>
On 23.07.26 10:41 PM, Ilya Dryomov wrote:
> On Tue, May 19, 2026 at 1:01 PM Raphael Zimmer
> <[email protected]> wrote:
>>
>> 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 <[email protected]>
>> ---
>>  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)
> 
> Hi Raphael,
> 
> I think this can be just len > CEPH_PG_MAX_SIZE.  I have folded the
> corresponding fixup into someone else's patch that originally did that
> only for __decode_pg_temp():
> 
> https://github.com/ceph/ceph-client/commit/9f00f9cf2be293efe899db67dc5272e3a9c62717
> 
> If you agree, we can retire this patch.
> 
> Thanks,
> 
>                 Ilya

Hi Ilya,
this solution with "len > CEPH_PG_MAX_SIZE" will equally solve the
issue. Therefore, I'm fine with doing it this way.

Best regards,
Raphael