From 456a5e661d1356f1cee87783179385996183f63d Mon Sep 17 00:00:00 2001 From: "J. Eric Ivancich" Date: Wed, 16 Apr 2025 12:38:33 -0400 Subject: [PATCH] rgw: prevent crash in `radosgw-admin bucket object shard ...` This subcommand is used to ask radosgw-admin which bucket index shard a given object in a given bucket would have its bucket index entry on. The user is required to supply the number of shards (i.e., the command doesn't look that up). If 0 is provided it would result in a divide by zero runtime exception. Values less than or equal to zero are now protected. Signed-off-by: J. Eric Ivancich (cherry picked from commit a2b76b0e09ece61fd0978411d08d13257fe6ddbe) --- src/rgw/driver/rados/rgw_tools.h | 7 +++++-- src/rgw/rgw_admin.cc | 7 ++++++- src/rgw/services/svc_bi_rados.h | 8 ++++---- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/rgw/driver/rados/rgw_tools.h b/src/rgw/driver/rados/rgw_tools.h index 9f5a1ae1a42..8bfe5b5aee1 100644 --- a/src/rgw/driver/rados/rgw_tools.h +++ b/src/rgw/driver/rados/rgw_tools.h @@ -45,10 +45,13 @@ inline int rgw_shards_max() // only called by rgw_shard_id and rgw_bucket_shard_index static inline int rgw_shards_mod(unsigned hval, int max_shards) { - if (max_shards <= RGW_SHARDS_PRIME_0) { + if (max_shards <= 0) { + return -1; + } else if (max_shards <= RGW_SHARDS_PRIME_0) { return hval % RGW_SHARDS_PRIME_0 % max_shards; + } else { + return hval % RGW_SHARDS_PRIME_1 % max_shards; } - return hval % RGW_SHARDS_PRIME_1 % max_shards; } // used for logging and tagging diff --git a/src/rgw/rgw_admin.cc b/src/rgw/rgw_admin.cc index 620f124ef43..70875a17b5f 100644 --- a/src/rgw/rgw_admin.cc +++ b/src/rgw/rgw_admin.cc @@ -7474,8 +7474,13 @@ int main(int argc, const char **argv) cerr << "ERROR: num-shards and object must be specified." << std::endl; return EINVAL; + } else if (num_shards <= 0) { + cerr << "ERROR: non-positive value supplied for num-shards: " << + num_shards << std::endl; + return EINVAL; } - auto shard = RGWSI_BucketIndex_RADOS::bucket_shard_index(object, num_shards); + auto shard = + RGWSI_BucketIndex_RADOS::bucket_shard_index(object, num_shards); formatter->open_object_section("obj_shard"); encode_json("shard", shard, formatter.get()); formatter->close_section(); diff --git a/src/rgw/services/svc_bi_rados.h b/src/rgw/services/svc_bi_rados.h index c6c11f8bc00..d9fc3dd65a3 100644 --- a/src/rgw/services/svc_bi_rados.h +++ b/src/rgw/services/svc_bi_rados.h @@ -99,15 +99,15 @@ public: return rgw_shard_id(key, max_shards); } - static uint32_t bucket_shard_index(const std::string& key, - int num_shards) { + static int32_t bucket_shard_index(const std::string& key, + int num_shards) { uint32_t sid = ceph_str_hash_linux(key.c_str(), key.size()); uint32_t sid2 = sid ^ ((sid & 0xFF) << 24); return rgw_shards_mod(sid2, num_shards); } - static uint32_t bucket_shard_index(const rgw_obj_key& obj_key, - int num_shards) + static int32_t bucket_shard_index(const rgw_obj_key& obj_key, + int num_shards) { std::string sharding_key; if (obj_key.ns == RGW_OBJ_NS_MULTIPART) { -- 2.39.5