emscripten-core/emscripten

Fix emrun for COOP/COEP/CORP

Closed this issue · 16 comments

Firefox has recently added restrictions on WebAssembly.Memory objects shared between webworkers. (see here). Chrome is also planning on adding that in the near future.
Unfortunately this means that pthreads builds no longer work with Firefox, and will soon start failing in Chrome.

Some examples of projects that no longer work in Firefox:
https://rustwasm.github.io/wasm-bindgen/exbuild/raytrace-parallel/
https://www.qt.io/web-assembly-example-mandelbrot
https://brianotto.github.io/ui-builder/web/

These now throw: TypeError: The WebAssembly.Memory object cannot be serialized. The Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy HTTP headers will enable this in the future.

Currently I'm working around this by setting the preference: dom.postMessage.sharedArrayBuffer.bypassCOOP_COEP.insecure.enabled (the Emscripten tests do the same), but obviously this is not a proper solution.

I tried adding the following headers to emrun:

Cross-Origin-Resource-Policy: same-site
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

however this appeared to have no effect.

Anyone know what we're actually supposed to do? Ideally we should fix emrun, and update the wiki so people know the server requirements for serving wasm.

More information is available here.

juj commented

Hmm, when running a page with emrun, there is only one origin in play (and no iframes even), so any cross-origin restrictions should not apply there?

Or I suppose is this due to the use of Object URLs to load the worker.js?

It's not yet enabled on Nightly: https://bugzilla.mozilla.org/show_bug.cgi?id=1594748. The flags mentioned in comment 0 there can be used to experiment.

I'm using Firefox 72.0b4 (Firefox Developer) on Windows, and without setting anything in about:config I get the mentioned error.
My about:config:

dom.postMessage.sharedArrayBuffer.withCOOP_COEP == false (default)
browser.tabs.remote.useCORP == false (default)
browser.tabs.remote.useCrossOriginOpenerPolicy == false (default)
browser.tabs.remote.useCrossOriginEmbedderPolicy == false (default)

In Firefox 71.0 (Latest Release) on Windows I get the error: TypeError: WebAssembly.Memory cannot be cloned in this context (I believe that's the same issue, the error text was changed to be more descriptive in an update).
This of course required javascript.options.shared_memory to be set to true.

Do the example projects work for you in Firefox Developer or Release+javascript.options.shared_memory?

Yeah, that's expected, as postMessage() is guarded now.

So if I'm understanding you right, Firefox Developer edition, without any flags set, doesn't not work with webassembly and webworkers?
So when this bug is closed what do I need to set on a server to enable this to work?

Y0QIN commented

I have the same problem,that means Firefox will no longer support webassembly pthreads?

Y0QIN commented

MeanWhile I set dom.postMessage.sharedArrayBuffer.withCOOP_COEP and javascript.options.shared_memory,but it didn't work

We shouldn't set dom.postMessage.sharedArrayBuffer.withCOOP_COEP, because it enables the browser feature that blocks postMessage if we don't set the headers.

Or I suppose is this due to the use of Object URLs to load the worker.js?

I'd say yes. I could get it to work with this flag:
dom.postMessage.sharedArrayBuffer.bypassCOOP_COEP.insecure.enabled
but it is only available on Nightlies. I agree with @VirtualTim, we should set the correct headers in the generated page + workers. + serve the page securely (https)

dom.postMessage.sharedArrayBuffer.bypassCOOP_COEP.insecure.enabled will never come to release line, as it's there to disable a security feature but make development easier. And we shouldn't be asking our users to disable security features anyway.

Y0QIN commented

I got it,and I agree that Asking users to disable safety features is dangerous.
Thank you all

dom.postMessage.sharedArrayBuffer.bypassCOOP_COEP.insecure.enabled will never come to release line, as it's there to disable a security feature but make development easier. And we shouldn't be asking our users to disable security features anyway.

I agree, I just meant that the flag "dom.postMessage.sharedArrayBuffer.withCOOP_COEP" won't magically make things work. But I don't get why unsetting it makes postMessage throw.

Setting the flags :
browser.tabs.remote.useCORP
browser.tabs.remote.useCrossOriginOpenerPolicy
browser.tabs.remote.useCrossOriginEmbedderPolicy
dom.postMessage.sharedArrayBuffer.withCOOP_COEP
and adding this to emrun:

diff --git a/emrun.py b/emrun.py
index fd036b3bb..847aee0eb 100755
--- a/emrun.py
+++ b/emrun.py
@@ -596,6 +596,9 @@ class HTTPHandler(SimpleHTTPRequestHandler):
     self.send_header('Connection', 'close')
     self.send_header('Expires', '-1')
     self.send_header('Access-Control-Allow-Origin', '*')
+    self.send_header('Cross-Origin-Opener-Policy', 'same-origin');
+    self.send_header('Cross-Origin-Embedder-Policy', 'require-corp');
+    self.send_header('Cross-Origin-Resource-Policy', 'cross-origin');
     self.end_headers()
     page_last_served_time = tick()
     return f

makes it work for me.

juj commented

Both the config and heaers are ok to be added to emrun, if someone wants to put up a PR. (emrun is a dev/testing tool, not an end user tool, so any user guards don't apply)

Both the config and heaers are ok to be added to emrun, if someone wants to put up a PR. (emrun is a dev/testing tool, not an end user tool, so any user guards don't apply)

True. I am a noob, but I think this is not for production right?:
self.send_header('Access-Control-Allow-Origin', '*')

I can send a PR.

juj commented

Yeah, emrun is not a prodution server, but a local testing/development/test harness server.