[PATCH v3] libceph: Reject osdmaps advertising pools of unsupported types
Raphael Zimmer <[email protected]> Tue, 7 Jul 2026 12:31:19 +0200
| Newsgroups | org.kernel.vger.ceph-devel |
|---|---|
| Message-ID | <[email protected]> |
osdmaps are received over the network and typically contain information
about existing pools. Information about each pool is decoded in
decode_pool(). A pool is either replicated or erasure coded, which is
encoded in the type field as an 8-bit value. Currently, any value in
this field is treated as valid even though only two values have an
actual meaning. If this field contains a value other than
CEPH_POOL_TYPE_REP or CEPH_POOL_TYPE_EC, a BUG() assertion in
ceph_can_shift_osds() can be triggered subsequently. This happens the
next time calc_target() is called for a request in this pool.
This patch fixes the issue by adding a check that verifies the pool type
directly during decoding and rejecting osdmaps that contain invalid
values. To also account for incremental maps that are updated in-place,
the corrupted pool is removed from the osdmap if its decoding fails.
Fixes: 4f6a7e5ee139 ("ceph: update support for PGID64, PGPOOL3, OSDENC protocol features")
Signed-off-by: Raphael Zimmer <[email protected]>
---
include/linux/ceph/rados.h | 5 +++++
net/ceph/osdmap.c | 8 +++++++-
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/include/linux/ceph/rados.h b/include/linux/ceph/rados.h
index 73c3efbec36c..5b5c33845301 100644
--- a/include/linux/ceph/rados.h
+++ b/include/linux/ceph/rados.h
@@ -86,6 +86,11 @@ struct ceph_pg_v1 {
#define CEPH_POOL_TYPE_RAID4 2 /* never implemented */
#define CEPH_POOL_TYPE_EC 3
+static inline bool ceph_pool_type_is_supported(__u8 type)
+{
+ return type == CEPH_POOL_TYPE_REP || type == CEPH_POOL_TYPE_EC;
+}
+
/*
* stable_mod func is used to control number of placement groups.
* similar to straight-up modulo, but produces a stable mapping as b
diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c
index f8d5621bc767..0ad2e4801294 100644
--- a/net/ceph/osdmap.c
+++ b/net/ceph/osdmap.c
@@ -818,6 +818,10 @@ static int decode_pool(void **p, void *end, struct ceph_pg_pool_info *pi)
ceph_decode_need(p, end, 4 + 4 + 4, bad);
pi->type = ceph_decode_8(p);
+ if (!ceph_pool_type_is_supported(pi->type)) {
+ pr_warn_ratelimited("got unsupported pool type %u\n", pi->type);
+ return -EINVAL;
+ }
pi->size = ceph_decode_8(p);
pi->crush_ruleset = ceph_decode_8(p);
pi->object_hash = ceph_decode_8(p);
@@ -1363,8 +1367,10 @@ static int __decode_pools(void **p, void *end, struct ceph_osdmap *map,
}
ret = decode_pool(p, end, pi);
- if (ret)
+ if (ret) {
+ __remove_pg_pool(&map->pg_pools, pi);
return ret;
+ }
}
return 0;
--
2.47.3