diff options
| author | Raphael Zimmer <raphael.zimmer@tu-ilmenau.de> | 2026-07-28 10:43:40 +0200 |
|---|---|---|
| committer | Ilya Dryomov <idryomov@gmail.com> | 2026-08-12 21:21:41 +0200 |
| commit | 3660b98d1204b419f6a77e9a295f148dcf38d042 (patch) | |
| tree | 42662452c591cb9576c4fcae20fad8d0c71425bb /net/ceph | |
| parent | 00ead17c7de137a692edee59f2772e6af687e8eb (diff) | |
| download | linux-next-3660b98d1204b419f6a77e9a295f148dcf38d042.tar.gz linux-next-3660b98d1204b419f6a77e9a295f148dcf38d042.zip | |
libceph: Avoid using invalid osd indices from primary_temp
A corrupted osdmap received from a Ceph monitor or OSD may contain osd
indices in its pg_temp, primary_temp, pg_upmap, and pg_upmap_items parts
that don't exist, i.e., that are greater than max_osd or smaller than
CEPH_HOMELESS_OSD (-1). These indices are used to create the up and
acting set in ceph_pg_to_up_acting_osds(), called from calc_target().
While most of these osd indices are checked, the one from primary_temp
is not. Subsequently, this may lead to calc_target() returning this
(potentially invalid) 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 get_temp_osds(), so that
only valid osd indices from primary_temp are used, and it falls back to
using the primary from pg_temp or the up set if it is invalid.
[ idryomov: changelog ]
Cc: stable@vger.kernel.org
Fixes: 5e8d4d36bf23 ("libceph: add support for primary_temp mappings")
Signed-off-by: Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'net/ceph')
| -rw-r--r-- | net/ceph/osdmap.c | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index a4b0dd8672ec..d6282f0bcff8 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c @@ -2809,9 +2809,10 @@ static void get_temp_osds(struct ceph_osdmap *osdmap, } } - /* primary_temp? */ + /* primary_temp? (shouldn't ever be a nonexistent or down OSD) */ pg = lookup_pg_mapping(&osdmap->primary_temp, pgid); - if (pg) + if (pg && !WARN_ON_ONCE(ceph_osd_is_down(osdmap, + pg->primary_temp.osd))) temp->primary = pg->primary_temp.osd; } |
