UaF in DeferredTaskHandler::BreakConnections
Chrome
CVE-2020-6428
Chromium version: master branch build e577636 Also tested on release google Chrome 80.3987.122 Operating System: linux 18.04
When HandlePreRenderTask
is called during the rendering, it will check whether any source node should be stopped[1]. If an AudioScheduleSourceNode
, (e.g. ConstantSourceNode
) is to be stopped at or before the frame [2], it will then call the AudioScheduledSourceHandler::Finish()
method, which calls FinishWithoutOnEnded
. This has 2 effects:
BaseAudioContext::NotifySourceNodeFinishedProcessing
[3], which will add the AudioScheduledSourceHandler
in the |finished_source_handlers_
| vector, as raw pointer.void BaseAudioContext::NotifySourceNodeFinishedProcessing(
AudioHandler* handler) {
DCHECK(IsAudioThread());
GetDeferredTaskHandler().GetFinishedSourceHandlers()->push_back(handler);
}
AudioScheduledSourceHandler
to FINISHED_STATE
, allowing the AudioScheduledSourceNode
to be deleted[4]. If a suspend is also scheduled at the same frame, we can then return to main thread and delete the AudioScheduleSourceNode
. This is ok as the AudioScheduleSourceHandler
is also being kept alive in |active_source_handlers_
| when the start method of the source node is called[5], which is held in the BaseAudioContext
.
void BaseAudioContext::NotifySourceNodeStartedProcessing(AudioNode* node) {
DCHECK(IsMainThread());
GraphAutoLocker locker(this);
GetDeferredTaskHandler().GetActiveSourceHandlers()->insert(&node->Handler());
node->Handler().MakeConnection();
}
When the BaseAudioContext
is resumed, it will call the DeferredTaskHandler::BreakConnection
method in the HandlePostRenderTasks
method[6] to finish off with the AudioScheduleSourceNode
:
void DeferredTaskHandler::BreakConnections() {
...
wtf_size_t size = finished_source_handlers_.size();
if (size > 0) {
for (auto* finished : finished_source_handlers_) {
active_source_handlers_.erase(finished); //<-- finished is now free'd
finished->BreakConnectionWithLock(); //<-- UaF
}
finished_source_handlers_.clear();
}
}
The problem, however, is that BreakConnections
first erase the handler before using it in the next line. As the handler is now only kept alive by |active_source_handlers_
|, this deletes the handler and causes UaF.
Use-after-free in renderer.
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-037
in any communication regarding this issue.