facebook / hermes

A JavaScript engine optimized for running React Native.
https://hermesengine.dev/
MIT License
9.41k stars 596 forks source link

Race Condition between HadesGC and HermesInternal.getEpilogues() Causes Segfault #1356

Open WilliamParks opened 2 months ago

WilliamParks commented 2 months ago

Bug Description

Hermes git revision (if applicable): 55ccdf198078be78ac8c562b0087f561591aa950 OS: Linux Platform: x86_64

Steps To Reproduce

Most easily reproduced with handle sanitization enabled, but works with any seed.

function a() {
  Function()
  try {
    HermesInternal.getEpilogues()
  } catch {
  }
}
for (;;)
a()

ASAN log

==2590700==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0x000000000060 (pc 0x55555579c21c bp 0x7fffffffc0a0 sp 0x7fffffffc050 T2590700)
==2590700==The signal is caused by a READ memory access.
==2590700==Hint: address points to the zero page.
    #0 0x55555579c21c in hermes::vm::RuntimeModule::hidesEpilogue() const /home/b/projects/hermes_datacov/include/hermes/VM/RuntimeModule.h:342:19
    #1 0x55555579c21c in hermes::vm::Runtime::getEpilogues() /home/b/projects/hermes_datacov/lib/VM/Runtime.cpp:1214:12
    #2 0x5555557ef37e in hermes::vm::hermesInternalGetEpilogues(void*, hermes::vm::Runtime&, hermes::vm::NativeArgs) /home/b/projects/hermes_datacov/lib/VM/JSLib/HermesInternal.cpp:59:22
    #3 0x555555680c9d in hermes::vm::NativeFunction::_nativeCall(hermes::vm::NativeFunction*, hermes::vm::Runtime&) /home/b/projects/hermes_datacov/include/hermes/VM/Callable.h:507:9
    #4 0x5555556ba263 in hermes::vm::Interpreter::handleCallSlowPath(hermes::vm::Runtime&, hermes::vm::PinnedHermesValue*) /home/b/projects/hermes_datacov/lib/VM/Interpreter.cpp:274:12
    #5 0x5555556c161a in hermes::vm::CallResult<hermes::vm::HermesValue, (hermes::vm::detail::CallResultSpecialize)2> hermes::vm::Interpreter::interpretFunction<false, false>(hermes::vm::Runtime&, hermes::vm::InterpreterState&) /home/b/projects/hermes_datacov/lib/VM/Interpreter.cpp:1620:7
    #6 0x5555556dce88 in hermes::vm::Runtime::interpretFunctionImpl(hermes::vm::CodeBlock*) /home/b/projects/hermes_datacov/lib/VM/Interpreter.cpp:825:12
    #7 0x5555556dce88 in hermes::vm::Runtime::interpretFunction(hermes::vm::CodeBlock*) /home/b/projects/hermes_datacov/lib/VM/Interpreter.cpp:833:10
    #8 0x555555799c19 in hermes::vm::Runtime::runBytecode(std::shared_ptr<hermes::hbc::BCProviderBase>&&, hermes::vm::RuntimeModuleFlags, llvh::StringRef, hermes::vm::Handle<hermes::vm::Environment>, hermes::vm::Handle<hermes::vm::HermesValue>) /home/b/projects/hermes_datacov/lib/VM/Runtime.cpp:1085:11
    #9 0x5555559af685 in hermes::vm::Runtime::runBytecode(std::shared_ptr<hermes::hbc::BCProviderBase>&&, hermes::vm::RuntimeModuleFlags, llvh::StringRef, hermes::vm::Handle<hermes::vm::Environment>) /home/b/projects/hermes_datacov/include/hermes/VM/Runtime.h:281:12
    #10 0x5555559af685 in hermes::(anonymous namespace)::executeHBCBytecodeImpl(std::shared_ptr<hermes::hbc::BCProviderBase>&&, hermes::ExecuteOptions const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const*) /home/b/projects/hermes_datacov/lib/ConsoleHost/ConsoleHost.cpp:323:53
    #11 0x5555559af685 in hermes::executeHBCBytecode(std::shared_ptr<hermes::hbc::BCProviderBase>&&, hermes::ExecuteOptions const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const*)::$_0::operator()() const /home/b/projects/hermes_datacov/lib/ConsoleHost/ConsoleHost.cpp:409:12
    #12 0x5555559af685 in decltype(fp()) hermes::(anonymous namespace)::maybeCatchException<hermes::executeHBCBytecode(std::shared_ptr<hermes::hbc::BCProviderBase>&&, hermes::ExecuteOptions const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const*)::$_0>(hermes::executeHBCBytecode(std::shared_ptr<hermes::hbc::BCProviderBase>&&, hermes::ExecuteOptions const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const*)::$_0 const&) /home/b/projects/hermes_datacov/lib/ConsoleHost/ConsoleHost.cpp:245:12
    #13 0x5555559af685 in hermes::executeHBCBytecode(std::shared_ptr<hermes::hbc::BCProviderBase>&&, hermes::ExecuteOptions const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const*) /home/b/projects/hermes_datacov/lib/ConsoleHost/ConsoleHost.cpp:408:10
    #14 0x55555559cde8 in executeHBCBytecodeFromCL(std::unique_ptr<hermes::hbc::BCProviderBase, std::default_delete<hermes::hbc::BCProviderBase>>, hermes::driver::BytecodeBufferInfo const&) /home/b/projects/hermes_datacov/tools/hermes/hermes.cpp:139:15
    #15 0x55555559cde8 in main /home/b/projects/hermes_datacov/tools/hermes/hermes.cpp:221:16
    #16 0x7ffff522814f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #17 0x7ffff5228208 in __libc_start_main csu/../csu/libc-start.c:360:3
    #18 0x5555555820c4 in _start (/home/b/projects/hermes_datacov/norm_fuzz_build/bin/hermes+0x2e0c4) (BuildId: 69dc68ff1ee6a8d1c20c6c03911a0412b21a6580)

Looking through TSAN logs, the root issue seems to be the concurrent GC running during the getEpilogues builtin, and collecting the RuntimeModule while the iterator here is still running.

Because this bug is in an hermesInternal function, I do not believe it is a security issue.