This commit upgrades the rocksdb submodule from v7.9.2 to v7.10.2 to
address CVE-2022-23476, a security vulnerability in the Nokogiri gem
used by RocksDB's documentation build system.
CVE-2022-23476 Details:
- Affects: RocksDB versions < 7.10.2
- Issue: Unchecked return value from xmlTextReaderExpand in Nokogiri
- Fix commit:
6648dec0a3eee0a329af8342038ce099baa55122
- Fixed in: Nokogiri 1.13.10, included in RocksDB v7.10.2
The vulnerability was fixed in the upstream facebook/rocksdb repository
on December 8, 2022, and included in the v7.10.2 release. The v7.9.2
version currently used by Ceph does not contain this fix, as the 7.9.x
branch diverged before the security patch was applied.
Analysis confirmed that:
- Current Ceph RocksDB: v7.9.2 (commit
24ea35870fe9b3ba15285ec8746ba97ed5d67ff3)
- CVE fix present in v7.9.2: NO
- First version with fix: v7.10.2 (commit
9107c1059b4656513ae0d51e8976e4f69f59a9c3)
References:
- CVE-2022-23476: https://nvd.nist.gov/vuln/detail/CVE-2022-23476
- Nokogiri Advisory: GHSA-qv4q-mr5r-qprj
- Fix commit: facebook/rocksdb@
6648dec
also, in this change, we adapt BinnedLRUCache to CacheItemHelper API.
rocksdb 7.10 reshaped `rocksdb::Cache`, so we have to update our
overrides accordingly to address the build failure. the check for
RocksDB version is dropped, as mainstream distros ship RocksDB >=
7.10.2 at the time of writing:
- alpine 3.23: 10.9.1
- fedora 44: 10.2.1
- debian stable: 9.10.0
- ubuntu nobel: 8.9.1
- ubuntu resolute: 9.11.2
Signed-off-by: Justin Caratzas <jcaratza@ibm.com>
Signed-off-by: Kefu Chai <k.chai@proxmox.com>
void BinnedLRUCacheShard::ApplyToAllCacheEntries(
const std::function<void(const rocksdb::Slice& key,
- void* value,
+ rocksdb::Cache::ObjectPtr value,
size_t charge,
- DeleterFn)>& callback,
+ const rocksdb::Cache::CacheItemHelper* helper)>& callback,
bool thread_safe)
{
if (thread_safe) {
}
table_.ApplyToAllCacheEntries(
[callback](BinnedLRUHandle* h) {
- callback(h->key(), h->value, h->charge, h->deleter);
+ callback(h->key(), h->value, h->charge, h->helper);
});
if (thread_safe) {
mutex_.unlock();
return last_reference;
}
-rocksdb::Status BinnedLRUCacheShard::Insert(const rocksdb::Slice& key, uint32_t hash, void* value,
+rocksdb::Status BinnedLRUCacheShard::Insert(const rocksdb::Slice& key, uint32_t hash,
+ rocksdb::Cache::ObjectPtr value,
+ const rocksdb::Cache::CacheItemHelper* helper,
size_t charge,
- DeleterFn deleter,
rocksdb::Cache::Handle** handle, rocksdb::Cache::Priority priority) {
auto e = new BinnedLRUHandle();
rocksdb::Status s;
BinnedLRUHandle* deleted = nullptr;
e->value = value;
- e->deleter = deleter;
+ e->helper = helper;
e->charge = charge;
e->key_length = key.size();
e->key_data = new char[e->key_length];
return std::string(buffer);
}
-DeleterFn BinnedLRUCacheShard::GetDeleter(rocksdb::Cache::Handle* h) const
+const rocksdb::Cache::CacheItemHelper*
+BinnedLRUCacheShard::GetCacheItemHelper(rocksdb::Cache::Handle* h) const
{
auto* handle = reinterpret_cast<BinnedLRUHandle*>(h);
- return handle->deleter;
+ return handle->helper;
}
#undef dout_context
return reinterpret_cast<CacheShard*>(&shards_[shard]);
}
-void* BinnedLRUCache::Value(Handle* handle) {
+rocksdb::Cache::ObjectPtr BinnedLRUCache::Value(Handle* handle) {
return reinterpret_cast<const BinnedLRUHandle*>(handle)->value;
}
#endif // !__SANITIZE_ADDRESS__
}
-#if (ROCKSDB_MAJOR >= 7 || (ROCKSDB_MAJOR == 6 && ROCKSDB_MINOR >= 22))
-DeleterFn BinnedLRUCache::GetDeleter(Handle* handle) const
+const rocksdb::Cache::CacheItemHelper*
+BinnedLRUCache::GetCacheItemHelper(Handle* handle) const
{
- return reinterpret_cast<const BinnedLRUHandle*>(handle)->deleter;
+ return reinterpret_cast<const BinnedLRUHandle*>(handle)->helper;
}
-#endif
size_t BinnedLRUCache::TEST_GetLRUSize() {
size_t lru_size_of_all_shards = 0;
struct BinnedLRUHandle {
std::shared_ptr<uint64_t> age_bin;
- void* value;
- DeleterFn deleter;
+ rocksdb::Cache::ObjectPtr value;
+ const rocksdb::Cache::CacheItemHelper* helper;
BinnedLRUHandle* next_hash;
BinnedLRUHandle* next;
BinnedLRUHandle* prev;
void Free() {
ceph_assert((refs == 1 && InCache()) || (refs == 0 && !InCache()));
- if (deleter) {
- (*deleter)(key(), value);
+ if (helper && helper->del_cb) {
+ (*helper->del_cb)(value, /*allocator=*/nullptr);
}
delete[] key_data;
delete this;
void SetHighPriPoolRatio(double high_pri_pool_ratio);
// Like Cache methods, but with an extra "hash" parameter.
- virtual rocksdb::Status Insert(const rocksdb::Slice& key, uint32_t hash, void* value,
+ virtual rocksdb::Status Insert(const rocksdb::Slice& key, uint32_t hash,
+ rocksdb::Cache::ObjectPtr value,
+ const rocksdb::Cache::CacheItemHelper* helper,
size_t charge,
- DeleterFn deleter,
rocksdb::Cache::Handle** handle,
rocksdb::Cache::Priority priority) override;
virtual rocksdb::Cache::Handle* Lookup(const rocksdb::Slice& key, uint32_t hash) override;
virtual void ApplyToAllCacheEntries(
const std::function<void(const rocksdb::Slice& key,
- void* value,
+ rocksdb::Cache::ObjectPtr value,
size_t charge,
- DeleterFn)>& callback,
+ const rocksdb::Cache::CacheItemHelper* helper)>& callback,
bool thread_safe) override;
virtual void EraseUnRefEntries() override;
virtual std::string GetPrintableOptions() const override;
- virtual DeleterFn GetDeleter(rocksdb::Cache::Handle* handle) const override;
+ virtual const rocksdb::Cache::CacheItemHelper* GetCacheItemHelper(
+ rocksdb::Cache::Handle* handle) const override;
void TEST_GetLRUList(BinnedLRUHandle** lru, BinnedLRUHandle** lru_low_pri);
virtual const char* Name() const override { return "BinnedLRUCache"; }
virtual CacheShard* GetShard(int shard) override;
virtual const CacheShard* GetShard(int shard) const override;
- virtual void* Value(Handle* handle) override;
+ virtual rocksdb::Cache::ObjectPtr Value(Handle* handle) override;
virtual size_t GetCharge(Handle* handle) const override;
virtual uint32_t GetHash(Handle* handle) const override;
virtual void DisownData() override;
-#if (ROCKSDB_MAJOR >= 7 || (ROCKSDB_MAJOR == 6 && ROCKSDB_MINOR >= 22))
- virtual DeleterFn GetDeleter(Handle* handle) const override;
-#endif
+ virtual const rocksdb::Cache::CacheItemHelper* GetCacheItemHelper(
+ Handle* handle) const override;
// Retrieves number of elements in LRU, for unit test purpose only
size_t TEST_GetLRUSize();
// Sets the high pri pool ratio
strict_capacity_limit_ = strict_capacity_limit;
}
-rocksdb::Status ShardedCache::Insert(const rocksdb::Slice& key, void* value, size_t charge,
- DeleterFn deleter,
+rocksdb::Status ShardedCache::Insert(const rocksdb::Slice& key,
+ rocksdb::Cache::ObjectPtr value,
+ const rocksdb::Cache::CacheItemHelper* helper,
+ size_t charge,
rocksdb::Cache::Handle** handle, Priority priority) {
uint32_t hash = HashSlice(key);
return GetShard(Shard(hash))
- ->Insert(key, hash, value, charge, deleter, handle, priority);
+ ->Insert(key, hash, value, helper, charge, handle, priority);
}
-rocksdb::Cache::Handle* ShardedCache::Lookup(const rocksdb::Slice& key, rocksdb::Statistics* /*stats*/) {
+rocksdb::Cache::Handle* ShardedCache::Lookup(const rocksdb::Slice& key,
+ const rocksdb::Cache::CacheItemHelper* /*helper*/,
+ rocksdb::Cache::CreateContext* /*create_context*/,
+ Priority /*priority*/, bool /*wait*/,
+ rocksdb::Statistics* /*stats*/) {
+ // Secondary cache is not supported by BinnedLRUCache, so the helper,
+ // create_context, priority, wait, and stats arguments are ignored here.
uint32_t hash = HashSlice(key);
return GetShard(Shard(hash))->Lookup(key, hash);
}
return usage;
}
-#if (ROCKSDB_MAJOR >= 7 || (ROCKSDB_MAJOR == 6 && ROCKSDB_MINOR >= 22))
-DeleterFn ShardedCache::GetDeleter(Handle* handle) const
+const rocksdb::Cache::CacheItemHelper* ShardedCache::GetCacheItemHelper(
+ Handle* handle) const
{
uint32_t hash = GetHash(handle);
- return GetShard(Shard(hash))->GetDeleter(handle);
+ return GetShard(Shard(hash))->GetCacheItemHelper(handle);
}
void ShardedCache::ApplyToAllEntries(
- const std::function<void(const rocksdb::Slice& key, void* value, size_t charge,
- DeleterFn deleter)>& callback,
- const ApplyToAllEntriesOptions& opts)
+ const std::function<void(const rocksdb::Slice& key,
+ rocksdb::Cache::ObjectPtr value,
+ size_t charge,
+ const rocksdb::Cache::CacheItemHelper* helper)>& callback,
+ const ApplyToAllEntriesOptions& /*opts*/)
{
int num_shards = 1 << num_shard_bits_;
for (int s = 0; s < num_shards; s++) {
GetShard(s)->ApplyToAllCacheEntries(callback, true /* thread_safe */);
}
}
-#else
-void ShardedCache::ApplyToAllCacheEntries(void (*callback)(void*, size_t),
- bool thread_safe) {
- int num_shards = 1 << num_shard_bits_;
- for (int s = 0; s < num_shards; s++) {
- GetShard(s)->ApplyToAllCacheEntries(
- [callback](const rocksdb::Slice&, void* value, size_t charge, DeleterFn) {
- callback(value, charge);
- },
- thread_safe);
- }
-}
-#endif
void ShardedCache::EraseUnRefEntries() {
int num_shards = 1 << num_shard_bits_;
namespace rocksdb_cache {
-using DeleterFn = void (*)(const rocksdb::Slice& key, void* value);
-
// Single cache shard interface.
class CacheShard {
public:
CacheShard() = default;
virtual ~CacheShard() = default;
- virtual rocksdb::Status Insert(const rocksdb::Slice& key, uint32_t hash, void* value,
+ virtual rocksdb::Status Insert(const rocksdb::Slice& key, uint32_t hash,
+ rocksdb::Cache::ObjectPtr value,
+ const rocksdb::Cache::CacheItemHelper* helper,
size_t charge,
- DeleterFn deleter,
- rocksdb::Cache::Handle** handle, rocksdb::Cache::Priority priority) = 0;
+ rocksdb::Cache::Handle** handle,
+ rocksdb::Cache::Priority priority) = 0;
virtual rocksdb::Cache::Handle* Lookup(const rocksdb::Slice& key, uint32_t hash) = 0;
virtual bool Ref(rocksdb::Cache::Handle* handle) = 0;
virtual bool Release(rocksdb::Cache::Handle* handle, bool force_erase = false) = 0;
virtual size_t GetPinnedUsage() const = 0;
virtual void ApplyToAllCacheEntries(
const std::function<void(const rocksdb::Slice& key,
- void* value,
+ rocksdb::Cache::ObjectPtr value,
size_t charge,
- DeleterFn)>& callback,
+ const rocksdb::Cache::CacheItemHelper* helper)>& callback,
bool thread_safe) = 0;
virtual void EraseUnRefEntries() = 0;
virtual std::string GetPrintableOptions() const { return ""; }
- virtual DeleterFn GetDeleter(rocksdb::Cache::Handle* handle) const = 0;
+ virtual const rocksdb::Cache::CacheItemHelper* GetCacheItemHelper(
+ rocksdb::Cache::Handle* handle) const = 0;
};
// Generic cache interface which shards cache by hash of keys. 2^num_shard_bits
// rocksdb::Cache
virtual const char* Name() const override = 0;
using rocksdb::Cache::Insert;
- virtual rocksdb::Status Insert(const rocksdb::Slice& key, void* value, size_t charge,
- DeleterFn,
- rocksdb::Cache::Handle** handle, Priority priority) override;
+ virtual rocksdb::Status Insert(const rocksdb::Slice& key,
+ rocksdb::Cache::ObjectPtr value,
+ const rocksdb::Cache::CacheItemHelper* helper,
+ size_t charge,
+ rocksdb::Cache::Handle** handle,
+ Priority priority) override;
using rocksdb::Cache::Lookup;
- virtual rocksdb::Cache::Handle* Lookup(const rocksdb::Slice& key, rocksdb::Statistics* stats) override;
+ virtual rocksdb::Cache::Handle* Lookup(const rocksdb::Slice& key,
+ const rocksdb::Cache::CacheItemHelper* helper,
+ rocksdb::Cache::CreateContext* create_context,
+ Priority priority, bool wait,
+ rocksdb::Statistics* stats) override;
virtual bool Ref(rocksdb::Cache::Handle* handle) override;
using rocksdb::Cache::Release;
virtual bool Release(rocksdb::Cache::Handle* handle, bool force_erase = false) override;
- virtual void* Value(Handle* handle) override = 0;
+ virtual rocksdb::Cache::ObjectPtr Value(Handle* handle) override = 0;
virtual void Erase(const rocksdb::Slice& key) override;
virtual uint64_t NewId() override;
virtual void SetCapacity(size_t capacity) override;
virtual size_t GetUsage() const override;
virtual size_t GetUsage(rocksdb::Cache::Handle* handle) const override;
virtual size_t GetPinnedUsage() const override;
- virtual size_t GetCharge(Handle* handle) const = 0;
-#if (ROCKSDB_MAJOR >= 7 || (ROCKSDB_MAJOR == 6 && ROCKSDB_MINOR >= 22))
- virtual DeleterFn GetDeleter(Handle* handle) const override;
-#endif
+ virtual size_t GetCharge(Handle* handle) const override = 0;
+ virtual const rocksdb::Cache::CacheItemHelper* GetCacheItemHelper(
+ Handle* handle) const override;
virtual void DisownData() override = 0;
-#if (ROCKSDB_MAJOR >= 7 || (ROCKSDB_MAJOR == 6 && ROCKSDB_MINOR >= 22))
virtual void ApplyToAllEntries(
- const std::function<void(const rocksdb::Slice& key, void* value, size_t charge,
- DeleterFn deleter)>& callback,
+ const std::function<void(const rocksdb::Slice& key,
+ rocksdb::Cache::ObjectPtr value,
+ size_t charge,
+ const rocksdb::Cache::CacheItemHelper* helper)>& callback,
const ApplyToAllEntriesOptions& opts) override;
-#else
- virtual void ApplyToAllCacheEntries(void (*callback)(void*, size_t),
- bool thread_safe) override;
-#endif
virtual void EraseUnRefEntries() override;
virtual std::string GetPrintableOptions() const override;
virtual CacheShard* GetShard(int shard) = 0;
-Subproject commit 24ea35870fe9b3ba15285ec8746ba97ed5d67ff3
+Subproject commit 0bd97e703ec62ad602717482508b08dd91baa8f5