-
Notifications
You must be signed in to change notification settings - Fork 16.4k
fix: crash due to race between attach and destruction of webview #24344
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test? :)
@nornagon hence the draft state 😄 , hopefully I can get a minimal test suite from the vscode team. |
I spent a few days trying to get a minimal reproduce on vanilla Electron but I found the test is simply about removing the webview shortly after the webview is created (sequence For example, I wrote a test like below and I can only crash the process 1-2 out of 100 times on some bad days (I'm guessing it's when my machine is on heavy loads) const v8Util = process.electronBinding('v8_util');
const ipcRendererInternal = v8Util.getHiddenValue(global, 'ipc-internal');
const { ipc } = process.electronBinding('ipc');
function timeoutAsync(n) {
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, n);
});
}
const loadWebView = async (id, container, webview, attributes = {}) => {
for (const [name, value] of Object.entries(attributes)) {
webview.setAttribute(name, value);
}
container.appendChild(webview);
setTimeout(() => {
ipcRendererInternal.sendSync('ELECTRON_GUEST_VIEW_MANAGER_DETACH_GUEST', id + 1);
}, 2);
};
async function test() {
for (let i = 0; i < 500; i++) {
let webview = new WebView();
const container = document.createElement('div');
document.body.appendChild(container);
loadWebView(i + 1, container, webview, {
src: `https://s3.amazonaws.com/duhaime/blog/visualizations/isolation-forests.html`
});
await timeoutAsync(10);
}
}
window.onload = function () {
test()
} Even on our CI https://dev.azure.com/vscode/VSCode/_build/results?buildId=48185&view=logs&j=a5e52b91-c83f-5429-4a68-c246fc63a4f7&t=855ed636-0983-5316-9b28-7efa8f10a65b, on which we are seeing most of the crashes, we only saw crashes 1 out of 5 to 10 times. It made me think that if we are going to have a test, which can crash the process 100% of the time, we need to either
but none of above sounds valuable. I'm wondering if there is any other approach that we can take to move this forward? |
I'm good without a test in this case. |
0f6fc57
to
b01f7fa
Compare
I'm a little uneasy that this fixes a UAF by shuffling some JavaScript around. It should be impossible to cause a UAF from JS. Can we address this on the C++ side? |
For webview it becomes possible because its backing
any ideas ? |
@deepak1556 can you please rebase on top of latest master? |
b01f7fa
to
9caadd2
Compare
We now have ASan tests enabled in master (on Linux only). That might make it easier to create a reliably-failing test. |
5d4636d
to
9eb6ba0
Compare
9eb6ba0
to
091139f
Compare
I am not seeing those crashes anymore. |
@zcbenz, @codebytere can you please review? |
Failing tests are unrelated, merging. |
Release Notes Persisted
|
Description of Change
This is an edge case that was discovered in ci when a page holding webview is created and destroyed rapidly but after some debugging this is possible to trigger by users too depending on usage.
Thanks @rebornix for help with the detailed debugging.
Refs microsoft/vscode#99408 , microsoft/vscode#100321
The sequence of action before this PR were as follows:
<webview>
DOM element is created and attached to DOM tree by the usersrc
attribute which inturn signals the browser process via an async ipc to create the backing webcontents viaCreateGuest
inguest-view-manager
<webview>
is removed from the DOM tree by the user this will signal a sync ipc to cleanup stuff on the browser process.All this works well most of the time, but there can be situations where a page holding the webview is destroyed between step 3) and 4) , which causes the attach ipc call to cause UAF crashes in
electron::WebViewGuestDelegate::AttachToIframe
This patch fixes the scenario by combining the creation and attaching of backing webcontents in a single ipc call that will avoid the race.
Checklist
npm test
passesRelease Notes
Notes: Fixed crash in webview creation casued by UAF in the browser process