-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[CoreIPC] heap-use-after-free in WebCore::MockMediaSourcePrivate::mar…
…kEndOfStream rdar://115982856 Reviewed by Jean-Yves Avenard and Eric Carlson. Error only hit in internal testing. Object was referenced after deletion. Updated `MockMediaPlayer` to use weak pointer for `m_player` instead of reference and added checks to methods to check that `m_player` exists before trying to read/write * Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.cpp: added check that `m_player` exists before accessing * Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.h: changed `m_player` to weak pointer instead of a reference * Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp: (WebCore::MockSourceBufferPrivate::readyState const): (WebCore::MockSourceBufferPrivate::setReadyState): Canonical link: https://commits.webkit.org/267815.570@safari-7617-branch
- Loading branch information
Showing
7 changed files
with
405 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
let knownSizes = { | ||
"unsigned": 4, | ||
"int": 4, | ||
"uint8_t": 1, | ||
"int8_t": 1, | ||
"uint64_t": 8, | ||
"int64_t": 8, | ||
"uint32_t": 4, | ||
"int32_t": 4, | ||
"uint16_t": 2, | ||
"int16_t": 2, | ||
"double": 8, | ||
"float": 4, | ||
"bool": 1, | ||
"size_t": 8, | ||
"unsigned short": 2, | ||
"long long": 8, | ||
"UUID": 16 | ||
}; | ||
|
||
|
||
// manual additions | ||
$F.fuzzerTypeInfo = {}; | ||
$F.fuzzerTypeInfo['WebCore::DOMCacheEngine::CacheIdentifierOrError'] = [{'type': 'Expected<WebCore::DOMCacheEngine::CacheIdentifierOperationResult, Error>'}]; | ||
|
||
let ArgumentParser = {}; | ||
function align(pos, granularity) { | ||
if(pos%granularity) { | ||
pos = pos + granularity-(pos%granularity); | ||
} | ||
return pos; | ||
} | ||
|
||
ArgumentParser.parseMessage = function(msg, proc) { | ||
let buffer = new Uint8Array(msg.buffer); | ||
window.bada = buffer; | ||
let name = msg.description; | ||
let args = IPCmessages[name].arguments; | ||
let results = {}; | ||
try { | ||
ArgumentParser.parse(buffer, args, 0x10 /*skip message header*/, results); | ||
if(proc) results[proc + "Connection"] = [ msg.destinationID ]; | ||
let clz = msg.description.substring(0, msg.description.indexOf("_")); | ||
if(proc) results["clz_" + clz + "Connection"] = [ msg.destinationID ]; | ||
//$F.exec.log("//blam: " + msg.destinationID); | ||
if($F.rand && $F.rand.chance(16)) { | ||
//$F.exec.log("// focus on " + clz); | ||
$F.focusClass = clz; | ||
} | ||
} catch (e) { | ||
//$F.exec.log("//Bug: " + e); | ||
} | ||
return results; | ||
} | ||
|
||
ArgumentParser.parseMessageFromReply = function(args, buffer) { | ||
buffer = new Uint8Array(buffer); | ||
let results = {}; | ||
try { | ||
ArgumentParser.parse(buffer, args, 0x10/*skip message header*/, results); | ||
} catch (e) { | ||
//$F.exec.log("//Bug: " + e); | ||
} | ||
return results; | ||
} | ||
|
||
function addResult(results, t, id) { | ||
if(t in results) { | ||
results[t].push(id); | ||
} else { | ||
results[t] = [ id ]; | ||
} | ||
} | ||
|
||
ArgumentParser.parse = function(buf, args, pos, results) { | ||
if(args == null) return -1; | ||
if(args.length == 0) return pos; | ||
let arg = args.shift(); | ||
let t = arg['type']; | ||
//$F.exec.log("// next " + t + " -> " + arg['optional']); | ||
if(arg['optional']) { | ||
let haz = !!buf[pos]; | ||
pos += 1 | ||
if(!haz) { | ||
//$F.exec.log("// skipping optional argument") | ||
return ArgumentParser.parse(buf, args, pos, results); | ||
} | ||
} | ||
if (processQualified.includes(t)) { | ||
pos = align(pos, 8); | ||
if(pos + 16 > buf.length) { | ||
//$F.exec.log("// Message too small to contain identifier") | ||
return -1; | ||
} | ||
let view = new DataView(buf.buffer, pos); | ||
let id1 = view.getBigUint64(0, true); | ||
let id2 = view.getBigUint64(8, true); | ||
addResult(results, t, id1); | ||
addResult(results, "WebCore::ProcessIdentifier", id2); | ||
return ArgumentParser.parse(buf, args, pos + 16, results); | ||
} else if ( IPCobjectIdentifiers.includes(t) ) { | ||
pos = align(pos, 8); | ||
if(pos + 8 > buf.length) { | ||
//$F.exec.log("// Message too small to contain identifier") | ||
return -1; | ||
} | ||
let view = new DataView(buf.buffer, pos); | ||
let id = view.getBigUint64(0, true); | ||
//$F.exec.log("// Got Identifier '" + t + "': " + id); | ||
//$F.objstore.addObj(t, id); | ||
addResult(results, t, id); | ||
return ArgumentParser.parse(buf, args, pos + 8, results); | ||
} else if ( knownSizes[t] ) { | ||
pos = align(pos, knownSizes[t]); | ||
pos += knownSizes[t]; | ||
return ArgumentParser.parse(buf, args, pos, results); | ||
} else if ( IPCserializedEnumInfo[t] ) { | ||
let enumInfo = IPCserializedEnumInfo[t]; | ||
pos = align(pos, enumInfo.size); | ||
pos += enumInfo.size; | ||
return ArgumentParser.parse(buf, args, pos, results); | ||
} else if ( $F.fuzzerTypeInfo[t] ) { | ||
pos = ArgumentParser.parse(buf, $F.fuzzerTypeInfo[t], pos, results); | ||
if(pos==-1) return -1; | ||
return ArgumentParser.parse(buf, args, pos, results); | ||
} else if ( IPCserializedTypeInfo[t] ) { | ||
let typeInfo = IPCserializedTypeInfo[t]; | ||
let subArgs = []; | ||
for (const element of typeInfo) { | ||
subArgs.push(element); | ||
} | ||
pos = ArgumentParser.parse(buf, subArgs, pos, results); | ||
if(pos==-1) return -1; | ||
return ArgumentParser.parse(buf, args, pos, results); | ||
} else if ( t == "String" || t == "URL" ) { | ||
pos = align(pos, 4); | ||
let view = new DataView(buf.buffer, pos); | ||
let strLen = view.getUint32(0, true); | ||
pos += 4; | ||
if ( buf[pos++] == 0x01 ) { | ||
let str = ""; | ||
for(let i=0; i<strLen; i++) { | ||
str += String.fromCharCode(buf[pos++]); | ||
} | ||
return ArgumentParser.parse(buf, args, pos, results); | ||
} else { | ||
// Other encodings are not supported | ||
return -1; | ||
} | ||
} else if ( t.indexOf("std::pair<") == 0) { | ||
let types = t.substr(10).split(", "); | ||
for(const nextt of types) { | ||
let contentArg = {'type': nextt}; | ||
pos = ArgumentParser.parse(buf, [ contentArg ], pos, results); | ||
if(pos==-1) return -1; | ||
} | ||
return ArgumentParser.parse(buf, args, pos, results); | ||
} else if ( t.indexOf("Expected<") == 0) { | ||
let haz = !!buf[pos]; | ||
pos += 1 | ||
if(haz) { | ||
let expected_type = t.substr(9).split(",")[0]; | ||
let contentArg = {'type': expected_type}; | ||
pos = ArgumentParser.parse(buf, [ contentArg ], pos, results); | ||
if (pos == -1) { | ||
return -1; | ||
} | ||
return ArgumentParser.parse(buf, args, pos, results); | ||
} else { | ||
return -1; | ||
} | ||
} else if ( t.indexOf("Vector<") == 0 ) { | ||
pos = align(pos, 8); | ||
if(pos + 8 > buf.length) { | ||
//$F.exec.log("// Message too small to contain identifier") | ||
return -1; | ||
} | ||
let view = new DataView(buf.buffer, pos); | ||
let id = view.getBigUint64(0, true); | ||
pos += 8; | ||
if(id > 0x1000) { | ||
return -1; | ||
} | ||
let contentArg = {'type': t.substring(7, t.length-1)}; | ||
for(let x = 0; x<id; x++) { | ||
pos = ArgumentParser.parse(buf, [ contentArg ], pos, results); | ||
if (pos == -1) { | ||
return -1 | ||
} | ||
} | ||
return ArgumentParser.parse(buf, args, pos, results); | ||
} else { | ||
//$F.exec.log("//[x] could not parse '"+t+"'"); | ||
} | ||
return -1; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
if(!window.$F) { | ||
$F={}; | ||
$F.enableListener= true; | ||
} | ||
|
||
if(window.testRunner) { | ||
testRunner.waitUntilDone(); | ||
} | ||
|
||
if (window.IPC) { | ||
// Cache to avoid context switches from JavaScript to Native | ||
const IPCmessages = JSON.parse(JSON.stringify(IPC.messages)); | ||
const IPCobjectIdentifiers = JSON.parse(JSON.stringify(IPC.objectIdentifiers)); | ||
IPCobjectIdentifiers.push("PAL::SessionID"); | ||
IPCobjectIdentifiers.push("WebCore::ProcessIdentifier"); | ||
IPCobjectIdentifiers.push("WebKit::RemoteMediaSourceIdentifier"); | ||
IPCobjectIdentifiers.push("WebCore::MediaPlayerIdentifier"); | ||
IPCobjectIdentifiers.push("IPC::AsyncReplyID"); | ||
IPCobjectIdentifiers.push("ActivityStateChangeID"); | ||
IPCobjectIdentifiers.push("WebKit::EditorStateIdentifier"); | ||
IPCobjectIdentifiers.push("WebCore::PageOverlay::PageOverlayID"); | ||
IPCobjectIdentifiers.push("WebKit::DisplayLinkObserverID"); | ||
IPCobjectIdentifiers.push("WebKit::TextCheckerRequestID"); | ||
IPCobjectIdentifiers.push("WebKit::RemoteCDMIdentifier"); | ||
IPCobjectIdentifiers.push("WebKit::RemoteCDMInstanceIdentifier"); | ||
IPCobjectIdentifiers.push("WebKit::RemoteCDMInstanceSessionIdentifier"); | ||
IPCobjectIdentifiers.push("WebKit::RemoteSourceBufferIdentifier"); | ||
|
||
const IPCserializedTypeInfo = JSON.parse(JSON.stringify(IPC.serializedTypeInfo)); | ||
const IPCserializedEnumInfo = JSON.parse(JSON.stringify(IPC.serializedEnumInfo)); | ||
|
||
const processQualified = ["WebCore::FrameIdentifier","WebCore::ScriptExecutionContextIdentifier","WebCore::PolicyCheckIdentifier","WebCore::WebLockIdentifier","WebCore::PlatformLayerIdentifier","WebCore::BackForwardItemIdentifier","WebCore::SharedWorkerObjectIdentifier"]; | ||
|
||
$F.GPUOutgoingHandler = {}; | ||
$F.UIOutgoingHandler = {}; | ||
$F.UIIncomingHandler = {}; | ||
$F.GPUIncomingHandler = {}; | ||
$F.NetworkingOutgoingHandler = {}; | ||
$F.NetworkingIncomingHandler = {}; | ||
|
||
function shouldDiscard(args) { | ||
for(let a of args) { | ||
if(Array.isArray(a)) { | ||
if(shouldDiscard(a)) return true; | ||
} else { | ||
if(a['type']) { | ||
if(a['type'] == 'FrameID') { | ||
if(!Array.isArray(a['value'])) return true; | ||
} else if(a['type'] == 'Vector') { | ||
if(shouldDiscard(a['value'])) return true; | ||
} | ||
} | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
$F.sendMessage = (process, connId, name, args) => { | ||
if(shouldDiscard(args)) return; | ||
if(window.$F) $F.enableListener = false; | ||
try{ | ||
return IPC.sendMessage(process, connId, name, args); | ||
}catch(e) { | ||
$vm.print("[-] send exception: " + e); | ||
} | ||
finally { | ||
$F.enableListener = true; | ||
} | ||
} | ||
$F.sendSyncMessage = (process, connId, name, timeout, args) => { | ||
if(shouldDiscard(args)) return; | ||
if(window.$F) $F.enableListener = false; | ||
try{ | ||
return IPC.sendSyncMessage(process, connId, name, timeout, args); | ||
}catch(e) { | ||
$vm.print("[-] sync send exception: " + e); | ||
} | ||
finally { | ||
$F.enableListener = true; | ||
} | ||
} | ||
|
||
IPC.addOutgoingMessageListener("GPU", (msg) => { | ||
if(window.$F && $F.enableListener) { | ||
let name = msg.name; | ||
if (name in $F.GPUOutgoingHandler) { | ||
let func = $F.GPUOutgoingHandler[name]; | ||
delete $F.GPUOutgoingHandler[name]; | ||
func(msg); | ||
} | ||
} | ||
}); | ||
|
||
IPC.addOutgoingMessageListener("UI", (msg) => { | ||
if(window.$F && $F.enableListener) { | ||
let name = msg.name; | ||
if (name in $F.UIOutgoingHandler) { | ||
let func = $F.UIOutgoingHandler[name]; | ||
delete $F.UIOutgoingHandler[name]; | ||
func(msg); | ||
} | ||
} | ||
}); | ||
|
||
IPC.addIncomingMessageListener("GPU", (msg) => { | ||
if(window.$F && $F.enableListener) { | ||
let name = msg.name; | ||
if (name in $F.GPUIncomingHandler) { | ||
let func = $F.GPUIncomingHandler[name]; | ||
delete $F.GPUIncomingHandler[name]; | ||
func(msg); | ||
} | ||
} | ||
}); | ||
|
||
IPC.addIncomingMessageListener("UI", (msg) => { | ||
if(window.$F && $F.enableListener) { | ||
let name = msg.name; | ||
if (name in $F.UIIncomingHandler) { | ||
let func = $F.UIIncomingHandler[name]; | ||
delete $F.UIIncomingHandler[name]; | ||
func(msg); | ||
} | ||
} | ||
}); | ||
|
||
IPC.addOutgoingMessageListener("Networking", (msg) => { | ||
if(window.$F && $F.enableListener) { | ||
let name = msg.name; | ||
if (name in $F.NetworkingOutgoingHandler) { | ||
let func = $F.NetworkingOutgoingHandler[name]; | ||
delete $F.NetworkingOutgoingHandler[name]; | ||
func(msg); | ||
} | ||
} | ||
}); | ||
|
||
IPC.addIncomingMessageListener("Networking", (msg) => { | ||
if(window.$F && $F.enableListener) { | ||
let name = msg.name; | ||
if (name in $F.NetworkingIncomingHandler) { | ||
let func = $F.NetworkingIncomingHandler[name]; | ||
delete $F.NetworkingIncomingHandler[name]; | ||
func(msg); | ||
} | ||
} | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
This test passes if it does not crash. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
<!DOCTYPE html><!-- webkit-test-runner [ IPCTestingAPIEnabled=true ] --> | ||
<html><head> | ||
<script src="fuzz_tools.js"></script> | ||
<script src="argumentParser.js"></script> | ||
<script> | ||
if (window.testRunner) { | ||
testRunner.waitUntilDone(); | ||
setTimeout(() => { | ||
testRunner.notifyDone(); | ||
}, 2000); | ||
testRunner.dumpAsText(); | ||
} | ||
|
||
function fuzz() { | ||
if (window.IPC && IPC) { | ||
$F.GPUOutgoingHandler[IPC.messages.RemoteMediaPlayerManagerProxy_CreateMediaPlayer.name]=parseMessage; | ||
video=document.createElement('video'); | ||
video.src='abc'; | ||
} | ||
} | ||
function parseMessage(msg) { | ||
let parseResults=ArgumentParser.parseMessage(msg,'GPU'); | ||
o17=parseResults['WebCore::MediaPlayerIdentifier'][0]; | ||
o19=parseResults['GPUConnection'][0]; | ||
o20=parseResults['clz_RemoteMediaPlayerManagerProxyConnection'][0]; | ||
IPC.sendMessage('GPU',o19,IPCmessages.GPUConnectionToWebProcess_EnableMockMediaSource.name,[]); | ||
window.setTimeout(timeout_159,200); | ||
} | ||
function timeout_159() { | ||
IPC.sendMessage('GPU',o20,IPCmessages.RemoteMediaPlayerManagerProxy_CreateMediaPlayer.name,[{type: 'uint64_t',value: o17},{type: 'uint8_t',value: 8},{type: 'String',value: ''},{type: 'String',value: ''},{type: 'String',value: ''},{type: 'String',value: ''},{type: 'Vector',value: [[{type: 'String',value: "pageUp:"}],[{type: 'String',value: ''}]]},{type: 'bool',value: 1},{type: 'Vector',value: [[{type: 'String',value: ''}],[{type: 'String',value: ''}],[{type: 'String',value: ''}],[{type: 'String',value: "video/mpeg"}],[{type: 'String',value: ''}],[{type: 'String',value: "http"}],[{type: 'String',value: "a"}],[{type: 'String',value: ''}],[{type: 'String',value: ''}]]},{type: 'bool',value: 0},{type: 'bool',value: 1},{type: 'Vector',value: []},{type: 'bool',value: 1},{type: 'Vector',value: [[{type: 'uint32_t',value: 476}],[{type: 'uint32_t',value: 555}]]},{type: 'bool',value: 0},{type: 'uint32_t',value: 697},{type: 'uint32_t',value: 644},{type: 'uint32_t',value: 543},{type: 'uint32_t',value: 460},{type: 'Vector',value: [[{type: 'String',value: "page-6"}],[{type: 'String',value: ''}]]},{type: 'Vector',value: []},{type: 'uint8_t',value: 0},{type: 'String',value: "file:///tmp/ipcfuzz"},{type: 'String',value: "file:///etc/passwd"},{type: 'bool',value: 1},{type: 'uint16_t',value: 47385},{type: 'uint32_t',value: 174},{type: 'uint32_t',value: 632},{type: 'float',value: 341},{type: 'float',value: 1316.9076250987036},{type: 'uint64_t',value: 1009},{type: 'bool',value: 1},{type: 'bool',value: 1},{type: 'bool',value: 0},{type: 'bool',value: 0},{type: 'bool',value: 1}]); | ||
o112=2395; | ||
IPC.sendMessage("GPU",o17,IPC.messages.RemoteMediaPlayerProxy_LoadMediaSource.name, [{type:"String", value: ''},{type:"String", value: ''},{type: "bool", value: 0},{type: "uint64_t", value: o112}]); | ||
IPC.sendMessage('GPU',o20,IPC.messages.RemoteMediaPlayerManagerProxy_DeleteMediaPlayer.name,[{type: 'uint64_t',value: o17}]); | ||
IPC.sendMessage('GPU',o112,IPCmessages.RemoteMediaSourceProxy_MarkEndOfStream.name,[{type: 'bool',value: 0}]); | ||
} | ||
</script></head> | ||
<body onload='fuzz()'> | ||
This test passes if it does not crash. | ||
</body> | ||
</html> |
Oops, something went wrong.