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

Ilya Dryomov <[email protected]> Thu, 23 Jul 2026 22:41:31 +0200
Newsgroups org.kernel.vger.ceph-devel
Message-ID <CAOi1vP_6WjqQp-7a_g6g=U9100cW54G-1jSjWRH3ieh4u9u-bA@mail.gmail.com>
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