Re: [PATCH v2] libceph: Assign requests to homeless osd if calculated osd exceeds max_osd

Ilya Dryomov <[email protected]> Mon, 27 Jul 2026 12:35:11 +0200
Newsgroups org.kernel.vger.ceph-devel
Message-ID <CAOi1vP9jaHW2Eixk6i0gemBnWUgcybciFv025sXykPxk19ojpw@mail.gmail.com>
On Wed, Jul 1, 2026 at 5:56=E2=80=AFPM Raphael Zimmer
<[email protected]> wrote:
>
> A corrupted osdmap received from a Ceph monitor or OSD may contain
> placement groups with osd indices that don't exist, i.e., that are
> greater than max_osd or smaller than CEPH_HOMELESS_OSD (-1).

Hi Raphael,

The osdmap doesn't contain all placement group mappings -- they are
produced on demand by CRUSH based off of the crushmap that is embedded
in the osdmap but doesn't contain any OSD indices.  There are a few
(usually small or empty) exception tables in the form of pg_temp,
primary_temp, pg_upmap and pg_upmap_items where the "override" OSD
indices are stored.  Are those what you have in mind wrt. osdmap
corruption?

If so, I'd suggest adding map->max_osd checks to the corresponding
decode routines.  Munging ct_res to CALC_TARGET_NEED_RESEND as done in
this patch doesn't make much sense -- you are asking the OSD client to
arrange for the OSD request to be resent when there is no valid OSD to
send it to (and no expectation whatsoever that the resend's invocation
of calc_target() would produce a different result).

Thanks,

                Ilya

> Subsequently, this may lead to calc_target() returning such an index as
> target osd for a (linger) request. Because the osd_state, osd_weight,
> and osd_addr arrays only contain max_osd entries (with indices 0 to
> max_osd -1), this leads to out-of-bounds accesses when trying to read
> values from these arrays.
>
> This patch fixes the issue by adding a check to calc_target() assigning
> the request to the homeless osd if the target osd index read from the
> osdmap falls outside the valid osd index range.
>
> Fixes: 63244fa123a7 ("libceph: introduce ceph_osd_request_target, calc_ta=
rget()")
> Signed-off-by: Raphael Zimmer <[email protected]>
> ---
>  net/ceph/osd_client.c | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
> index a4d3cbfd27a3..3d13226a5d1f 100644
> --- a/net/ceph/osd_client.c
> +++ b/net/ceph/osd_client.c
> @@ -1707,6 +1707,12 @@ static enum calc_target_result calc_target(struct =
ceph_osd_client *osdc,
>                 }
>         }
>
> +       if (t->osd !=3D CEPH_HOMELESS_OSD && (u32)t->osd >=3D osdc->osdma=
p->max_osd) {
> +               t->osd =3D CEPH_HOMELESS_OSD;
> +               ct_res =3D CALC_TARGET_NEED_RESEND;
> +               goto out;
> +       }
> +
>         if (unpaused || legacy_change || force_resend || split)
>                 ct_res =3D CALC_TARGET_NEED_RESEND;
>         else
> --
> 2.47.3
>