glog icon indicating copy to clipboard operation
glog copied to clipboard

Demangle API: SEGV on unknown address

Open autofuzzoss opened this issue 4 years ago • 0 comments

Bug Report

Found SEGV on Demangle() API Function, that may cause security vulnerabilities such as 'Invalid Memory Access'.

PoC Code

#include "demangle.h"
 
using namespace GOOGLE_NAMESPACE;
 
const char *Poc = "_Z5\3435Dfuzzvaemanzz4f[ZZ6vaema6666666666666666666666666nzz3\264f[ZZ8nz\347z2f[ZZ8vaemanz:3f[ZZ8\"Dfufuzz3nzzvf[ZZ8nz\347z2f[DfufuzzvaemDemafuzzvaem4\"\n";
 
int main() {
  char demangled[4096];
  Demangle(Poc, demangled, sizeof(demangled));
  return 0;
}

Address Sanitizer Report

!!!! AVASFUZZ_TEST: Add Pre Function:fuzz_test_AVASFUZZ_TestAutoFuzz_Demangle_Test-0x500560, Pre-Func size:1, TCs size:1 !!!!
!!!! AVASFUZZ_TEST: Add Fuzz Test Case Function:fuzz_test_AVASFUZZ_TestAutoFuzz_Demangle_Test-0x500740, TCs size:1 !!!!
!!!! AVASFUZZ_TEST: Add Post Function:fuzz_test_AVASFUZZ_TestAutoFuzz_Demangle_Test-0x500c90, Post-Func size:1, TCs size:1 !!!!
INFO: Seed: 1725690318
INFO: Loaded 1 modules   (1482 inline 8-bit counters): 1482 [0x93d988, 0x93df52),
INFO: Loaded 1 PC tables (1482 PCs): 1482 [0x93df58,0x943bf8),
INFO:        1 files found in crash
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
INFO: seed corpus: files: 1 min: 167b max: 167b total: 167b rss: 29Mb
!!!! RUN_ALL_AVASFUZZ_TESTS : Fuzz TC size: 1. It should be same with added count !!!!
!!!! AVASFUZZ_TEST: START 1 PRE-ACTIONS, fuzz_test_AVASFUZZ_TestAutoFuzz_Demangle_Test
!!!! AVASFUZZ_TEST: SRART TC, fuzz_test_AVASFUZZ_TestAutoFuzz_Demangle_Test
AddressSanitizer:DEADLYSIGNAL
=================================================================
==28497==ERROR: AddressSanitizer: SEGV on unknown address 0x60cfc0aab1a0 (pc 0x00000050479c bp 0x7ffec9ac7040 sp 0x7ffec9ac7000 T0)
==28497==The signal is caused by a READ memory access.
    #0 0x50479c in google::ParseOneCharToken(google::State*, char) /root/fuzz-test-generation/exp/glog/src/demangle.cc:211:7
    #1 0x50bc19 in google::ParseAbiTag(google::State*) /root/fuzz-test-generation/exp/glog/src/demangle.cc:723:10
    #2 0x506519 in google::OneOrMore(bool (*)(google::State*), google::State*) /root/fuzz-test-generation/exp/glog/src/demangle.cc:251:7
    #3 0x50b7de in google::ParseAbiTags(google::State*) /root/fuzz-test-generation/exp/glog/src/demangle.cc:713:7
    #4 0x50b0a4 in google::ParseUnqualifiedName(google::State*) /root/fuzz-test-generation/exp/glog/src/demangle.cc:605:47
    #5 0x50457f in google::ParseUnscopedName(google::State*) /root/fuzz-test-generation/exp/glog/src/demangle.cc:530:7
    #6 0x5040d4 in google::ParseUnscopedTemplateName(google::State*) /root/fuzz-test-generation/exp/glog/src/demangle.cc:547:10
    #7 0x502b65 in google::ParseName(google::State*) /root/fuzz-test-generation/exp/glog/src/demangle.cc:514:7
    #8 0x508ac4 in google::ParseClassEnumType(google::State*) /root/fuzz-test-generation/exp/glog/src/demangle.cc:1044:10
    #9 0x50700e in google::ParseType(google::State*) /root/fuzz-test-generation/exp/glog/src/demangle.cc:965:7
    #10 0x50654d in google::OneOrMore(bool (*)(google::State*), google::State*) /root/fuzz-test-generation/exp/glog/src/demangle.cc:252:12
    #11 0x502e1e in google::ParseBareFunctionType(google::State*) /root/fuzz-test-generation/exp/glog/src/demangle.cc:1033:7
    #12 0x502870 in google::ParseEncoding(google::State*) /root/fuzz-test-generation/exp/glog/src/demangle.cc:493:27
    #13 0x501f53 in google::ParseMangledName(google::State*) /root/fuzz-test-generation/exp/glog/src/demangle.cc:485:44
    #14 0x501ca4 in google::ParseTopLevelMangledName(google::State*) /root/fuzz-test-generation/exp/glog/src/demangle.cc:1306:7
    #15 0x501873 in google::Demangle(char const*, char*, unsigned long) /root/fuzz-test-generation/exp/glog/src/demangle.cc:1360:10
    #16 0x500260 in DemangleIt(char const*) /root/fuzz-test-generation/exp/glog/src/autofuzz_unittest.cc:22:7
    #17 0x4fff31 in TestAutoFuzz_Demangle_Test::TestBody() /root/fuzz-test-generation/exp/glog/src/autofuzz_unittest.cc:30:3
    #18 0x5009f9 in AVASGtestTest::runTest() /root/fuzz-test-generation/exp/glog/src/autofuzz_unittest.cc:44:7
    #19 0x50078b in fuzz_test_AVASFUZZ_TestAutoFuzz_Demangle_Test() /root/fuzz-test-generation/exp/glog/src/autofuzz_unittest.cc:64:13
    #20 0x55a48e in RUN_ALL_AVASFUZZ_TESTS() /root/fuzz-test-generation/exp/glog/src/avasfuzz_common/0avasfuzz.cpp:125:5
    #21 0x555858 in TestOneProtoInput(mutation::APIArgument const&) /root/fuzz-test-generation/exp/glog/src/fuzz_entry.cc:20:3
    #22 0x5556da in LLVMFuzzerTestOneInput /root/fuzz-test-generation/exp/glog/src/fuzz_entry.cc:17:1
    #23 0x43cb22 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /home/bjeong/2020_aiva/llvm/llvm-project/compiler-rt/lib/fuzzer/./Fu                                                                                                                                                                zzerLoop.cpp:556:15
    #24 0x43c19b in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) /home/bjeong/2020_aiva/llvm/llvm-project/com                                                                                                                                                                piler-rt/lib/fuzzer/./FuzzerLoop.cpp:470:3
    #25 0x43dc43 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) /home/bjeong/202                                                                                                                                                                0_aiva/llvm/llvm-project/compiler-rt/lib/fuzzer/./FuzzerLoop.cpp:765:7
    #26 0x43e139 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) /home/bjeong/2020_aiva/llvm/llvm-proj                                                                                                                                                                ect/compiler-rt/lib/fuzzer/./FuzzerLoop.cpp:792:3
    #27 0x42dbe9 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /home/bjeong/2020_aiva/llvm/llvm-project/compiler-rt/li                                                                                                                                                                b/fuzzer/./FuzzerDriver.cpp:829:6
    #28 0x4441b0 in main /home/bjeong/2020_aiva/llvm/llvm-project/compiler-rt/lib/fuzzer/./FuzzerMain.cpp:19:10
    #29 0x7fa761cb0bf6 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21bf6)
    #30 0x4235c9 in _start (/root/fuzz-test-generation/AutoFuzz_Exp/test/glog_demangle_1/TestAutoFuzz_Demangle_Test+0x4235c9)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /root/fuzz-test-generation/exp/glog/src/demangle.cc:211:7 in google::ParseOneCharToken(google::State*, char)
==28497==ABORTING
MS: 0 ; base unit: 0000000000000000000000000000000000000000
0x66,0x75,0x7a,0x7a,0x76,0x61,0x72,0x32,0x3a,0x20,0x22,0x5f,0x5a,0x35,0x5c,0x33,0x34,0x33,0x35,0x44,0x66,0x75,0x7a,0x7a,0x76,0x61,0x65,0x6d,0x61,0x6e,0x7a,0x                                                                                                                                                                7a,0x34,0x66,0x5b,0x5a,0x5a,0x36,0x76,0x61,0x65,0x6d,0x61,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36                                                                                                                                                                ,0x36,0x36,0x36,0x36,0x36,0x6e,0x7a,0x7a,0x33,0x5c,0x32,0x36,0x34,0x66,0x5b,0x5a,0x5a,0x38,0x6e,0x7a,0x5c,0x33,0x34,0x37,0x7a,0x32,0x66,0x5b,0x5a,0x5a,0x38,0                                                                                                                                                                x76,0x61,0x65,0x6d,0x61,0x6e,0x7a,0x3a,0x33,0x66,0x5b,0x5a,0x5a,0x38,0x5c,0x22,0x44,0x66,0x75,0x66,0x75,0x7a,0x7a,0x33,0x6e,0x7a,0x7a,0x76,0x66,0x5b,0x5a,0x5                                                                                                                                                                a,0x38,0x6e,0x7a,0x5c,0x33,0x34,0x37,0x7a,0x32,0x66,0x5b,0x44,0x66,0x75,0x66,0x75,0x7a,0x7a,0x76,0x61,0x65,0x6d,0x44,0x65,0x6d,0x61,0x66,0x75,0x7a,0x7a,0x76,                                                                                                                                                                0x61,0x65,0x6d,0x34,0x5c,0x22,0x5c,0x6e,0x22,0xa,
fuzzvar2: \"_Z5\\3435Dfuzzvaemanzz4f[ZZ6vaema6666666666666666666666666nzz3\\264f[ZZ8nz\\347z2f[ZZ8vaemanz:3f[ZZ8\\\"Dfufuzz3nzzvf[ZZ8nz\\347z2f[DfufuzzvaemDe                                                                                                                                                                mafuzzvaem4\\\"\\n\"\x0a
artifact_prefix='./'; Test unit written to ./crash-cfe825f8687b933ba7fe90b763eebc2c6db533b2
Base64: ZnV6enZhcjI6ICJfWjVcMzQzNURmdXp6dmFlbWFueno0ZltaWjZ2YWVtYTY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjZuenozXDI2NGZbWlo4bnpcMzQ3ejJmW1paOHZhZW1hbno6M2ZbWlo4XCJEZ                                                                                                                                                                nVmdXp6M256enZmW1paOG56XDM0N3oyZltEZnVmdXp6dmFlbURlbWFmdXp6dmFlbTRcIlxuIgo=

Reason

static bool ParseSourceName(State *state) { //Debugging: state has mangled_cur element that points input string indicates mangled name.
  State copy = *state;
  int length = -1;
  if (ParseNumber(state, &length) && ParseIdentifier(state, length)) { //Debugging: length set inside ParserNumber is used in ParseIdentifier.
    return true;
  }
  *state = copy;
  return false;
}
 
static bool ParseNumber(State *state, int *number_out) {
  int sign = 1;
  if (ParseOneCharToken(state, 'n')) {
    sign = -1;
  }
  const char *p = state->mangled_cur; //Debugging: assume that state->mangle_cur points "666666666666666666" string.
  int number = 0;
  for (;*p != '\0'; ++p) { // This loop works until consume all "6" in the string.
    if (IsDigit(*p)) { // always true.
      number = number * 10 + (*p - '0'); //Debugging: number, overflow.
    } else {
      break;
    }
  }
  if (p != state->mangled_cur) {  // Conversion succeeded.
    state->mangled_cur = p;
    if (number_out != NULL) {
      *number_out = number * sign; //Debugging: number_out set to overflowed value.
    }
    return true;
  }
  return false;
}
 
static bool ParseIdentifier(State *state, int length) {
  if (length == -1 ||
      !AtLeastNumCharsRemaining(state->mangled_cur, length)) {
    return false;
  }
  if (IdentifierIsAnonymousNamespace(state, length)) {
    MaybeAppend(state, "(anonymous namespace)");
 
  } else {
    MaybeAppendWithLength(state, state->mangled_cur, length);
 
  }
  state->mangled_cur += length; //Debugging: pointer for buffer points address based on overflowed, Now this program enters unexpected state.
  return true;
}

2 suggestions:

[1] Request CVE number for this bug to inform opencv users to prevent potential security vulnerabilities. [2] Register below fuzzer code to ossfuzz (https://github.com/google/oss-fuzz) for continuous fuzzing. (I found that there is no fuzzing test for glog in ossfuzz.) Note that, the git repo of UTopia project(https://github.com/Samsung/UTopia) is currently empty and will be updated until the end of May. Fuzzer Code:

/*
 * This fuzzer is generated by UTopia project based on TEST(Test_Tensorflow, read_inception).
 * (UTopia Project: https://github.com/Samsung/UTopia)
 */
#include "demangle.h"

using namespace GOOGLE_NAMESPACE;

extern "C" int LLVMFuzzerTestOneInput(const unsigned char *Data, unsigned Size) {
  char Buffer[Size + 1];
  memcpy(Buffer, Data, Size);
  Buffer[Size] = 0;
  char demangled[4096];
  Demangle(Buffer, demangled, Size);
  return 0;
}

autofuzzoss avatar Apr 11 '22 07:04 autofuzzoss