]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: `radosgw-admin bucket stats` on indexless bucket crashes
authorJ. Eric Ivancich <ivancich@redhat.com>
Thu, 23 Dec 2021 21:25:26 +0000 (16:25 -0500)
committerAdam C. Emerson <aemerson@redhat.com>
Tue, 1 Feb 2022 23:26:32 +0000 (18:26 -0500)
The new bucket layout code didn't check whether the bucket is
indexless prior to asking for the last entry in the layout log. The
layout log appears to be empty for an indexless bucket, thereby
putting the runtime in an undefined state that later may cause a
failed assertion.

This commit adds two safety checks and returns -EINVAL along with
putting useful information on stderr when either stats are requested
on an indexless bucket or when the layout log is empty.

Signed-off-by: J. Eric Ivancich <ivancich@redhat.com>
src/rgw/rgw_bucket.cc

index 2d98beb70173ad524d00adff91a4831a4a95b7fd..f119d23e4f2ea84fa7fe2eb974c6821f221a00e2 100644 (file)
@@ -1076,10 +1076,25 @@ static int bucket_stats(rgw::sal::Store* store,
     return ret;
   }
 
-  string bucket_ver, master_ver;
-  string max_marker;
+  if (bucket->get_info().layout.current_index.layout.type ==
+      rgw::BucketIndexType::Indexless) {
+    cerr << "error, indexless buckets do not maintain stats; bucket=" <<
+      bucket->get_name() << std::endl;
+    return -EINVAL;
+  }
+
+  if (bucket->get_info().layout.logs.empty()) {
+    // this check may be redundant with the previous check of
+    // layout.type; calling back() on an empty vector produces
+    // undefined behavior
+    cerr << "error, layout log list is empty; bucket=" << bucket->get_name() <<
+      std::endl;
+    return -EINVAL;
+  }
   const auto& latest_log = bucket->get_info().layout.logs.back();
   const auto& index = log_to_index_layout(latest_log);
+  std::string bucket_ver, master_ver;
+  std::string max_marker;
   ret = bucket->read_stats(dpp, index, RGW_NO_SHARD, &bucket_ver, &master_ver, stats, &max_marker);
   if (ret < 0) {
     cerr << "error getting bucket stats bucket=" << bucket->get_name() << " ret=" << ret << std::endl;