Closed Bug 1647115 Opened 5 years ago Closed 5 years ago

AddressSanitizer: heap-use-after-free [@ runtimeMatches] through [@ js::CancelOffThreadCompressions] with READ of size 8

Categories

(Core :: JavaScript Engine, defect, P1)

x86_64
Linux
defect

Tracking

()

RESOLVED FIXED
mozilla79
Tracking Status
firefox-esr68 --- unaffected
firefox-esr78 --- unaffected
firefox77 --- unaffected
firefox78 --- unaffected
firefox79 + fixed

People

(Reporter: decoder, Assigned: allstars.chh)

References

(Regression)

Details

(4 keywords, Whiteboard: [post-critsmash-triage][sec-survey])

Crash Data

Attachments

(1 file)

The following crash occurred on mozilla-central revision 20200619-341563fe5463 (asan-opt build, with --fuzzing-safe --cpu-count=2 --ion-offthread-compile=off --disable-oom-functions --ion-pgo=off --nursery-strings=on):

Backtrace:

==3375==ERROR: AddressSanitizer: heap-use-after-free on address 0x60600002f5a8 at pc 0x55adfc6365a7 bp 0x7f15ba407110 sp 0x7f15ba407108
READ of size 8 at 0x60600002f5a8 thread T17
    #0 0x55adfc6365a6 in runtimeMatches /builds/worker/checkouts/gecko/js/src/vm/HelperThreads.h:820:69
    #1 0x55adfc6365a6 in js::CancelOffThreadCompressions(JSRuntime*) /builds/worker/checkouts/gecko/js/src/vm/HelperThreads.cpp:2277:25
    #2 0x55adfc8dc20c in JSRuntime::destroyRuntime() /builds/worker/checkouts/gecko/js/src/vm/Runtime.cpp:272:5
    #3 0x55adfc7521de in js::DestroyContext(JSContext*) /builds/worker/checkouts/gecko/js/src/vm/JSContext.cpp:213:7
    #4 0x55adfc043803 in operator() /builds/worker/checkouts/gecko/js/src/shell/js.cpp:4124:5
    #5 0x55adfc043803 in ~ScopeExit /builds/worker/workspace/obj-build/dist/include/mozilla/ScopeExit.h:111:7
    #6 0x55adfc043803 in WorkerMain(WorkerInput*) /builds/worker/checkouts/gecko/js/src/shell/js.cpp:4186:1
    #7 0x55adfc044047 in callMain<0> /builds/worker/checkouts/gecko/js/src/threading/Thread.h:217:5
    #8 0x55adfc044047 in js::detail::ThreadTrampoline<void (&)(WorkerInput*), WorkerInput*&>::Start(void*) /builds/worker/checkouts/gecko/js/src/threading/Thread.h:206:11
    #9 0x7f15c4f6e6b9 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x76b9)
    #10 0x7f15c394c41c in clone /build/glibc-LK5gWL/glibc-2.23/misc/../sysdeps/unix/sysv/linux/x86_64/clone.S:109

0x60600002f5a8 is located 8 bytes inside of 56-byte region [0x60600002f5a0,0x60600002f5d8)
freed by thread T2 (JS Helper) here:
    #0 0x55adfbf9dced in free /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:123:3
    #1 0x55adfc636ae5 in js_free /builds/worker/workspace/obj-build/dist/include/js/Utility.h:432:3
    #2 0x55adfc636ae5 in js_delete<js::SourceCompressionTask> /builds/worker/workspace/obj-build/dist/include/js/Utility.h:573:5
    #3 0x55adfc636ae5 in operator() /builds/worker/workspace/obj-build/dist/include/js/Utility.h:645:35
    #4 0x55adfc636ae5 in reset /builds/worker/workspace/obj-build/dist/include/mozilla/UniquePtr.h:302:7
    #5 0x55adfc636ae5 in ~UniquePtr /builds/worker/workspace/obj-build/dist/include/mozilla/UniquePtr.h:253:18
    #6 0x55adfc636ae5 in js::AttachFinishedCompressions(JSRuntime*, js::AutoLockHelperThreadState&) /builds/worker/checkouts/gecko/js/src/vm/HelperThreads.cpp:2302:5
    #7 0x55adfd038f56 in js::gc::GCRuntime::sweepCompressionTasks() /builds/worker/checkouts/gecko/js/src/gc/GC.cpp:5077:3
    #8 0x55adfd05a296 in js::GCParallelTask::runTask() /builds/worker/checkouts/gecko/js/src/gc/GCParallelTask.cpp:146:3
    #9 0x55adfd05a075 in js::GCParallelTask::runFromHelperThread(js::AutoLockHelperThreadState&) /builds/worker/checkouts/gecko/js/src/gc/GCParallelTask.cpp:131:5
    #10 0x55adfc62faec in js::HelperThread::handleGCParallelWorkload(js::AutoLockHelperThreadState&) /builds/worker/checkouts/gecko/js/src/vm/HelperThreads.cpp:1675:21
    #11 0x55adfc633206 in js::HelperThread::threadLoop() /builds/worker/checkouts/gecko/js/src/vm/HelperThreads.cpp:2473:5
    #12 0x55adfc62b065 in js::HelperThread::ThreadMain(void*) /builds/worker/checkouts/gecko/js/src/vm/HelperThreads.cpp:2000:11
    #13 0x55adfc643247 in callMain<0> /builds/worker/checkouts/gecko/js/src/threading/Thread.h:217:5
    #14 0x55adfc643247 in js::detail::ThreadTrampoline<void (&)(void*), js::HelperThread*>::Start(void*) /builds/worker/checkouts/gecko/js/src/threading/Thread.h:206:11
    #15 0x7f15c4f6e6b9 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x76b9)

previously allocated by thread T18 here:
    #0 0x55adfbf9df6d in malloc /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:145:3
    #1 0x55adfc7f4288 in js_arena_malloc /builds/worker/workspace/obj-build/dist/include/js/Utility.h:385:10
    #2 0x55adfc7f4288 in js_malloc /builds/worker/workspace/obj-build/dist/include/js/Utility.h:389:10
    #3 0x55adfc7f4288 in js_new<js::SourceCompressionTask, JSRuntime *, js::ScriptSource *> /builds/worker/workspace/obj-build/dist/include/js/Utility.h:538:1
    #4 0x55adfc7f4288 in js::detail::UniqueSelector<js::SourceCompressionTask>::SingleObject js::MakeUnique<js::SourceCompressionTask, JSRuntime*, js::ScriptSource*>(JSRuntime*&&, js::ScriptSource*&&) /builds/worker/workspace/obj-build/dist/include/js/UniquePtr.h:43:23
    #5 0x55adfc7f3fcd in js::ScriptSource::tryCompressOffThread(JSContext*) /builds/worker/checkouts/gecko/js/src/vm/JSScript.cpp:2313:15
    #6 0x55adfcf31ea4 in js::frontend::ScriptCompiler<char16_t>::compileScript(js::frontend::CompilationInfo&, js::frontend::SharedContext*) /builds/worker/checkouts/gecko/js/src/frontend/BytecodeCompiler.cpp:504:48
    #7 0x55adfcee4ec4 in CreateGlobalScript<char16_t> /builds/worker/checkouts/gecko/js/src/frontend/BytecodeCompiler.cpp:185:17
    #8 0x55adfcee4ec4 in js::frontend::CompileGlobalScript(js::frontend::CompilationInfo&, js::frontend::GlobalSharedContext&, JS::SourceText<char16_t>&) /builds/worker/checkouts/gecko/js/src/frontend/BytecodeCompiler.cpp:200:10
    #9 0x55adfc5ac7bd in JSScript* CompileSourceBuffer<char16_t>(JSContext*, JS::ReadOnlyCompileOptions const&, JS::SourceText<char16_t>&) /builds/worker/checkouts/gecko/js/src/vm/CompilationAndEvaluation.cpp:80:10
    #10 0x55adfc04329e in WorkerMain(WorkerInput*) /builds/worker/checkouts/gecko/js/src/shell/js.cpp:4176:29
    #11 0x55adfc044047 in callMain<0> /builds/worker/checkouts/gecko/js/src/threading/Thread.h:217:5
    #12 0x55adfc044047 in js::detail::ThreadTrampoline<void (&)(WorkerInput*), WorkerInput*&>::Start(void*) /builds/worker/checkouts/gecko/js/src/threading/Thread.h:206:11
    #13 0x7f15c4f6e6b9 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x76b9)

Thread T17 created by T0 here:
    #0 0x55adfbf8871a in pthread_create /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_interceptors.cc:209:3
    #1 0x55adfc5095b1 in js::Thread::create(void* (*)(void*), void*) /builds/worker/checkouts/gecko/js/src/threading/posix/PosixThread.cpp:52:7
    #2 0x55adfc042554 in bool js::Thread::init<void (&)(WorkerInput*), WorkerInput*&>(void (&)(WorkerInput*), WorkerInput*&) /builds/worker/checkouts/gecko/js/src/threading/Thread.h:90:12
    #3 0x55adfc0188e4 in EvalInWorker(JSContext*, unsigned int, JS::Value*) /builds/worker/checkouts/gecko/js/src/shell/js.cpp:4255:29
    #4 0x21f21d9c954f  (<unknown module>)
    #5 0x6290000a8a37  (<unknown module>)
    #6 0x21f21da12a37  (<unknown module>)

Thread T2 (JS Helper) created by T0 here:
    #0 0x55adfbf8871a in pthread_create /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_interceptors.cc:209:3
    #1 0x55adfc5095b1 in js::Thread::create(void* (*)(void*), void*) /builds/worker/checkouts/gecko/js/src/threading/posix/PosixThread.cpp:52:7
    #2 0x55adfc62af54 in bool js::Thread::init<void (&)(void*), js::HelperThread*>(void (&)(void*), js::HelperThread*&&) /builds/worker/checkouts/gecko/js/src/threading/Thread.h:90:12
    #3 0x55adfc6234b2 in js::GlobalHelperThreadState::ensureInitialized() /builds/worker/checkouts/gecko/js/src/vm/HelperThreads.cpp:1109:27
    #4 0x55adfc8db8dc in JSRuntime::init(JSContext*, unsigned int) /builds/worker/checkouts/gecko/js/src/vm/Runtime.cpp:200:32
    #5 0x55adfc751d9c in js::NewContext(unsigned int, JSRuntime*) /builds/worker/checkouts/gecko/js/src/vm/JSContext.cpp:182:17
    #6 0x55adfbfe3b42 in main /builds/worker/checkouts/gecko/js/src/shell/js.cpp:11272:25
    #7 0x7f15c386582f in __libc_start_main /build/glibc-LK5gWL/glibc-2.23/csu/../csu/libc-start.c:291

Thread T18 created by T0 here:
    #0 0x55adfbf8871a in pthread_create /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_interceptors.cc:209:3
    #1 0x55adfc5095b1 in js::Thread::create(void* (*)(void*), void*) /builds/worker/checkouts/gecko/js/src/threading/posix/PosixThread.cpp:52:7
    #2 0x55adfc042554 in bool js::Thread::init<void (&)(WorkerInput*), WorkerInput*&>(void (&)(WorkerInput*), WorkerInput*&) /builds/worker/checkouts/gecko/js/src/threading/Thread.h:90:12
    #3 0x55adfc0188e4 in EvalInWorker(JSContext*, unsigned int, JS::Value*) /builds/worker/checkouts/gecko/js/src/shell/js.cpp:4255:29
    #4 0x21f21d9c954f  (<unknown module>)
    #5 0x6290000a8a37  (<unknown module>)
    #6 0x21f21da12a37  (<unknown module>)

SUMMARY: AddressSanitizer: heap-use-after-free /builds/worker/checkouts/gecko/js/src/vm/HelperThreads.h:820:69 in runtimeMatches
Shadow bytes around the buggy address:
  0x0c0c7fffdea0: fd fd fd fd fa fa fa fa fd fd fd fd fd fd fd fa
=>0x0c0c7fffdeb0: fa fa fa fa fd[fd]fd fd fd fd fd fa fa fa fa fa
  0x0c0c7fffdec0: fd fd fd fd fd fd fd fd fa fa fa fa 00 00 00 00
  0x0c0c7fffded0: 00 00 00 00 fa fa fa fa 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd

I do not have a testcase for this, but from the use-after-free trace it should be clear what is going on. Marking s-s until we have investigated if this only affects the shell or not.

It sounds like compression tasks and GC sweep-ing can happen concurrently.
I presume the fix would require adding proper synchonization between the helper-thread handling the compressing tasks and the GC.

Steve, do you mind having a look?

Flags: needinfo?(sphink)
See Also: → 1647007

Bug 1647007 seems like the same issue happening in a regular WPT, so I'll mark this sec-high. Presumably one of the bugs can be duped to the other.

I think this was caused by bug 1628204. Yoshi, can you take a look?

Flags: needinfo?(sphink) → needinfo?(allstars.chh)
Regressed by: 1628204
Has Regression Range: --- → yes
Assignee: nobody → allstars.chh
Flags: needinfo?(allstars.chh)

Set release status flags based on info from the regressing bug 1628204

Attachment #9158927 - Attachment description: Bug 1647115 - Add a HelperTask and takes a lock in runTaskImpl. → Bug 1647115 - Add a HelperTask and takes a lock in runTaskLocked.
Severity: -- → S4
Priority: -- → P1
Attachment #9158927 - Attachment description: Bug 1647115 - Add a HelperTask and takes a lock in runTaskLocked. → Bug 1647115 - Add a RunnableTaskLocked class.
Attachment #9158927 - Attachment description: Bug 1647115 - Add a RunnableTaskLocked class. → Bug 1647115 - Add a runTaskLocked method in SourceCompressionTask.

Comment on attachment 9158927 [details]
Bug 1647115 - Add a runTaskLocked method in SourceCompressionTask.

Security Approval Request

  • How easily could an exploit be constructed based on the patch?: Not easy, this patch makes sure the 'moving to compressionFinishedList part' and currentTask.reset happens within the same lock.
  • Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?: No
  • Which older supported branches are affected by this flaw?: none
  • If not all supported branches, which bug introduced the flaw?: Bug 1628204
  • Do you have backports for the affected branches?: No
  • If not, how different, hard to create, and risky will they be?: The bug introduced the regression is bug 1628204, which is still in nightly.
    (but if this patch is landed in firefox80, it will have to be uplifted to firefox79)
  • How likely is this patch to cause regressions; how much testing does it need?: Unlikely, this patch reverts the unlock introduced by bug 1628204.
Attachment #9158927 - Flags: sec-approval?

Comment on attachment 9158927 [details]
Bug 1647115 - Add a runTaskLocked method in SourceCompressionTask.

Doesn't need sec-approval since it's Nightly-only.

https://hg.mozilla.org/integration/autoland/rev/f2c470e06d308602428ea31875812ea321a14906

Attachment #9158927 - Flags: sec-approval?
Group: javascript-core-security → core-security-release
Status: NEW → RESOLVED
Closed: 5 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla79
Flags: qe-verify-
Whiteboard: [post-critsmash-triage]

As part of a security bug pattern analysis, we are requesting your help with a high level analysis of this bug. It is our hope to develop static analysis (or potentially runtime/dynamic analysis) in the future to identify classes of bugs.

Please visit this google form to reply.

Flags: needinfo?(allstars.chh)
Whiteboard: [post-critsmash-triage] → [post-critsmash-triage][sec-survey]

done

Flags: needinfo?(allstars.chh)
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: