April 16, 2020

GHSL-2020-040: Use After Free in Chrome WebAudio

Man Yue Mo


UaF in DeferredTaskHandler::BreakConnections(2)





Tested Version

Chrome version: master branch build 79956ba, asan build 80.3987.132 Operating System: Ubuntu 18.04


This issue has the same crash site as 1057593, but the root cause and the fix is different.

Similar to 1057593, when a suspend of the BaseAudioContext and a stop of an AudioScheduleSourceNode happens in the same quantum, the AudioScheduleSourceNode can be destroyed while the BaseAudioContext is suspended. At this point, active_source_handlers_ in DeferredTaskHandler[1] is responsible for keeping the corresponding AudioScheduleSourceHandler alive before it is used in DeferredTaskHandler::BreakConnections[2].

The code in DeferredTaskHandler::BreakConnections implicitly assumed that finished_source_handlers_ is a subset of active_source_handlers_ and hence active_source_handlers_ is keeping the raw pointers in finished_source_handlers_ alive. (as can be seen from the active_source_handlers_.erase, which assumes finished is contained in active_source_handlers_)

This problem, however, is that active_source_handlers_ can be cleared by the DeferredTaskHandler::ClearHandlersToBeDeleted method[3] while finished_source_handlers_ does not get cleared at the same time, leaving dangling pointers in finished_source_handlers_, which will then cause UaF in BreakConnections.

    for (auto* finished : finished_source_handlers_) {
      // Break connection first and then remove from the list because that can
      // cause the handler to be deleted.
      finished->BreakConnectionWithLock();     //<-- `active_source_handlers_` may have been cleared, and finished is already freed
      active_source_handlers_.erase(finished); //<-- assumes `active_source_handlers_` contains finished

By destroying the context to trigger BaseAudioContext::Uninitialize, which will then call ClearHandlersToBeDeleted, it is possible to clear active_source_handlers_ and then trigger DeferredTaskHandler::BreakConnections to cause a UaF.

  1. https://source.chromium.org/chromium/chromium/src/+/bf433ad6dcfcaac460512bb45a53d5a2ea5356f9:third_party/blink/renderer/modules/webaudio/deferred_task_handler.h;drc=67e598a2ae32101acac19318c0c56830c12a303f;bpv=1;bpt=1;l=255?originalUrl=https:%2F%2Fcs.chromium.org%2F

  2. https://source.chromium.org/chromium/chromium/src/+/bf433ad6dcfcaac460512bb45a53d5a2ea5356f9:third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc;l=83;drc=67e598a2ae32101acac19318c0c56830c12a303f;bpv=1;bpt=1?originalUrl=https:%2F%2Fcs.chromium.org%2F

  3. https://source.chromium.org/chromium/chromium/src/+/bf433ad6dcfcaac460512bb45a53d5a2ea5356f9:third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc;l=361;drc=67e598a2ae32101acac19318c0c56830c12a303f;bpv=1;bpt=1?originalUrl=https:%2F%2Fcs.chromium.org%2F


Use-after-free in renderer.

Coordinated Disclosure Timeline


This issue was discovered and reported by GHSL team member @m-y-mo (Man Yue Mo).


You can contact the GHSL team at securitylab@github.com, please include the GHSL-2020-040 in any communication regarding this issue.