Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Null Pointer Dereference Vulnerability in leveldb_open #1183

Open
YancyLii opened this issue Apr 21, 2024 · 1 comment
Open

Null Pointer Dereference Vulnerability in leveldb_open #1183

YancyLii opened this issue Apr 21, 2024 · 1 comment

Comments

@YancyLii
Copy link

Description

The leveldb_open function in LevelDB is vulnerable to a null pointer dereference issue, where it directly converts a const char* name to a std::string without null checks. This can lead to a std::logic_error being thrown if name is nullptr.

Steps to Reproduce

  1. Call leveldb_open with name set to nullptr.
  2. Observe a crash due to unhandled std::logic_error.

Expected Behavior

The function should handle nullptr inputs gracefully, either by returning an error or by rejecting the operation without crashing.

Suggested Fix

Implement a null check before using the name variable:

if (name == nullptr) {
  if (errptr != nullptr) {
    *errptr = strdup("Database name is null");
  }
  return nullptr;
}

##My Fuzzer
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  leveldb_options_t* options = nullptr;
  const char* path = nullptr;
  char** error = nullptr;
  leveldb_t* db = leveldb_open(options, path, error);
  if (db != nullptr) {
    leveldb_create_snapshot(db);
  }
  return 0;
}

root@2300d4f25744:/volume/PromptDriver# ./results/leveldb/fuzzer/Test_leveldb_Id56 ./results/leveldb/fuzzing/run1/out/Test_leveldb_Id56crash-da39a3ee5e6b4b0d3255bfef95601890afd80709 
INFO: Seed: 1250284794
INFO: Loaded 1 modules   (5466 inline 8-bit counters): 5466 [0x703f3f, 0x705499), 
INFO: Loaded 1 PC tables (5466 PCs): 5466 [0x68d6d0,0x6a2c70), 
./results/leveldb/fuzzer/Test_leveldb_Id56: Running 1 inputs 1 time(s) each.
Running: ./results/leveldb/fuzzing/run1/out/Test_leveldb_Id56crash-da39a3ee5e6b4b0d3255bfef95601890afd80709
terminate called after throwing an instance of 'std::logic_error'
  what():  basic_string::_M_construct null not valid
==325550== ERROR: libFuzzer: deadly signal
    #0 0x5292b1 in __sanitizer_print_stack_trace (/volume/PromptDriver/results/leveldb/fuzzer/Test_leveldb_Id56+0x5292b1)
    #1 0x474418 in fuzzer::PrintStackTrace() (/volume/PromptDriver/results/leveldb/fuzzer/Test_leveldb_Id56+0x474418)
    #2 0x459563 in fuzzer::Fuzzer::CrashCallback() (/volume/PromptDriver/results/leveldb/fuzzer/Test_leveldb_Id56+0x459563)
    #3 0x7fd3a5ac241f  (/lib/x86_64-linux-gnu/libpthread.so.0+0x1441f)
    #4 0x7fd3a58d200a in raise (/lib/x86_64-linux-gnu/libc.so.6+0x4300a)
    #5 0x7fd3a58b1858 in abort (/lib/x86_64-linux-gnu/libc.so.6+0x22858)
    #6 0x7fd3a5cbe8d0  (/lib/x86_64-linux-gnu/libstdc++.so.6+0x9e8d0)
    #7 0x7fd3a5cca37b  (/lib/x86_64-linux-gnu/libstdc++.so.6+0xaa37b)
    #8 0x7fd3a5cca3e6 in std::terminate() (/lib/x86_64-linux-gnu/libstdc++.so.6+0xaa3e6)
    #9 0x7fd3a5cca698 in __cxa_throw (/lib/x86_64-linux-gnu/libstdc++.so.6+0xaa698)
    #10 0x7fd3a5cc11db in std::__throw_logic_error(char const*) (/lib/x86_64-linux-gnu/libstdc++.so.6+0xa11db)
    #11 0x7fd3a5d65d9a in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char const*>(char const*, char const*, std::forward_iterator_tag) (/lib/x86_64-linux-gnu/libstdc++.so.6+0x145d9a)
    #12 0x552aaf in leveldb_open /mnt/UTopia/exp/leveldb/src/db/c.cc:171:48
    #13 0x55281e in LLVMFuzzerTestOneInput /mnt/PromptDriver/results/leveldb/driver/Test_leveldb_Id56.cc:52:19
    #14 0x45ac21 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/volume/PromptDriver/results/leveldb/fuzzer/Test_leveldb_Id56+0x45ac21)
    #15 0x446392 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) (/volume/PromptDriver/results/leveldb/fuzzer/Test_leveldb_Id56+0x446392)
    #16 0x44be46 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/volume/PromptDriver/results/leveldb/fuzzer/Test_leveldb_Id56+0x44be46)
    #17 0x474b02 in main (/volume/PromptDriver/results/leveldb/fuzzer/Test_leveldb_Id56+0x474b02)
    #18 0x7fd3a58b3082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082)
    #19 0x420a3d in _start (/volume/PromptDriver/results/leveldb/fuzzer/Test_leveldb_Id56+0x420a3d)

NOTE: libFuzzer has rudimentary signal handlers.
      Combine libFuzzer with AddressSanitizer or similar for better crash reports.
SUMMARY: libFuzzer: deadly signal
@fmorgner
Copy link

fmorgner commented Jun 1, 2024

The documentation of the C API for leveldb, found here, clearly states that all pointer arguments must never be NULL. It is the responsibility of the caller to ensure that they never pass a null pointer to any of the C API functions. Violating this requirement is a programmer error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants