[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