WebAssembly / interface-types

Other
641 stars 57 forks source link

add defer-call-export instruction to explainer #63

Closed lukewagner closed 4 years ago

lukewagner commented 4 years ago

As discussed in #60 and the video call today.

PoignardAzur commented 4 years ago

Have you considered the case of nested defer calls? Eg, what happens when the following adapter code is run:

(@interface func (export "foobar")
    defer-call-export "free"
)
(@interface implement (import "foobar")
    defer-call-export "foobar"
)

I assume deferred calls would create a new "scope" with its own LIFO defer stack.

lukewagner commented 4 years ago

As the explainer is currently written, with only defer-call-export, the export that is called is necessarily an export of the core wasm module (just as call-export can only synchronously call an export of the core wasm module), and since core wasm doesn't have the defer-call-export instruction, nested defer calls are not possible.

There's a separate topic that should be discussed in a separate issue of adding a call instruction that allows one adapter function to call another adapter function (in a limited, non-recursive manner). This would raise the question of having a defer-call, which would then raise the nested-defer issue you've raised here. That might be a good reason to avoid having a defer-call.

fgmccabe commented 4 years ago

Actually, if you export memory then you export it. It is optional to use the interface types

On Wed, Sep 4, 2019 at 12:10 PM Luke Wagner notifications@github.com wrote:

@lukewagner commented on this pull request.

In proposals/interface-types/Explainer.md https://github.com/WebAssembly/interface-types/pull/63#discussion_r320927554 :

@@ -346,7 +369,8 @@ used in the same adapter function: arg.get $str string-to-memory "mem" "malloc" call-export "frob_"

  • memory-to-string "mem" "free"

As answered above: only from the core module, not the adapted module. The core module is 100% encapsulated by the adapted module, so there is no issue, I think. There's also no other way, that I know of, if we don't want to change core wasm semantics.

— You are receiving this because your review was requested.

Reply to this email directly, view it on GitHub https://github.com/WebAssembly/interface-types/pull/63?email_source=notifications&email_token=AAQAXUG5ULQ4JJH2GGPKBG3QIAB3LA5CNFSM4ISIFDW2YY3PNVWWK3TUL52HS4DFWFIHK3DMKJSXC5LFON2FEZLWNFSXPKTDN5WW2ZLOORPWSZGOCDVPPWI#discussion_r320927554, or mute the thread https://github.com/notifications/unsubscribe-auth/AAQAXUGDSPKG33LKUB6J7LTQIAB3LANCNFSM4ISIFDWQ .

-- Francis McCabe SWE

lukewagner commented 4 years ago

@fgmccabe There seems to be some confusion here, so let me try to be more clear: if an interface adapter custom section is present and the host implements Interface Types, than an export from the core module only shows up as an export from the adapted module if it is explicitly re-exported via the adapter. The adapted module is the only module the outside world sees with the core module an encapsulated implementation detail.

fgmccabe commented 4 years ago

I understand that. However, someone can still access the wasm module ignoring the interface adapters. If they do, or even without that, they can directly access the now-shared memory. Or, am I missing something? Francis

On Wed, Sep 4, 2019 at 2:19 PM Luke Wagner notifications@github.com wrote:

@fgmccabe https://github.com/fgmccabe There seems to be some confusion here, so let me try to be more clear: if an interface adapter custom section is present and the host implements Interface Types, than an export from the core module only shows up as an export from the adapted module if it is explicitly re-exported via the adapter. The adapted module is the only module the outside world sees with the core module an encapsulated implementation detail.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/WebAssembly/interface-types/pull/63?email_source=notifications&email_token=AAQAXUEKCSYM3EWIG56UBM3QIAQ5PA5CNFSM4ISIFDW2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD55ATGI#issuecomment-528091545, or mute the thread https://github.com/notifications/unsubscribe-auth/AAQAXUCTMLQRHVLJ7T46SFLQIAQ5PANCNFSM4ISIFDWQ .

-- Francis McCabe SWE

jgravelle-google commented 4 years ago

However, someone can still access the wasm module ignoring the interface adapters.

How? Walk me through the specific way you're thinking of where you can run a wasm module and ignore the interface adapters.

I can think of a couple ways to do it, I just don't think they're problems. Off the top of my head:

  1. you run two modules in a host that doesn't support interface types.
    1. you polyfill it, and that hides the export, and there's no problem
    2. you don't, so the ABIs don't line up and the module either fails to execute or fails to instantiate
  2. you run a module in a host that supports interface types but does sneaky things with the boundaries. This was already a problem because you don't trust your host, and your host can do much worse things to mess with you
  3. you download a 3rd party module, include it in your application in a host that doesn't support interface types, and subvert the expected interface by providing your own polyfill that doesn't hide exports. This is equivalent to dynamic linking with an undocumented ABI. It's subject to break, but works at the moment. You can read memory in ways the library author didn't intend.

3) is probably the most problematic, but least probable because it relies on a host that ignores the adapters. If the host implements interface types at instantiate time there's no room to do it.

fgmccabe commented 4 years ago

What happens when a wasm module references another wasm module and claims it does not need the help of interface adapters? (C++ talking to C++ e.g.) Dynamic linking etc. I want to be able to access a credit card processing module without giving it my memory (or my allocator) The only way that this may work is if interfaces are 'optional but enforced'; i.e., a host is non-conforming if it can understand interface adapters but allows them to be ignored.

On Wed, Sep 4, 2019 at 2:40 PM Jacob Gravelle notifications@github.com wrote:

However, someone can still access the wasm module ignoring the interface adapters.

How? Walk me through the specific way you're thinking of where you can run a wasm module and ignore the interface adapters.

I can think of a couple ways to do it, I just don't think they're problems. Off the top of my head:

  1. you run two modules in a host that doesn't support interface types.
    1. you polyfill it, and that hides the export, and there's no problem
    2. you don't, so the ABIs don't line up and the module either fails to execute or fails to instantiate
  2. you run a module in a host that supports interface types but does sneaky things with the boundaries. This was already a problem because you don't trust your host, and your host can do much worse things to mess with you
  3. you download a 3rd party module, include it in your application in a host that doesn't support interface types, and subvert the expected interface by providing your own polyfill that doesn't hide exports. This is equivalent to dynamic linking with an undocumented ABI. It's subject to break, but works at the moment. You can read memory in ways the library author didn't intend.

3) is probably the most problematic, but least probable because it relies on a host that ignores the adapters. If the host implements interface types at instantiate time there's no room to do it.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/WebAssembly/interface-types/pull/63?email_source=notifications&email_token=AAQAXUDBQE3SP2C4FNLWK4LQIATONA5CNFSM4ISIFDW2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD55CJXA#issuecomment-528098524, or mute the thread https://github.com/notifications/unsubscribe-auth/AAQAXUG3H5AC3GNFKWZWJPLQIATONANCNFSM4ISIFDWQ .

-- Francis McCabe SWE

PoignardAzur commented 4 years ago

I think there's some confusion here as to what threat model wasm is supposed to guard against.

AFAICT, there is nothing that WebAssembly can (or should) do to protect against misuse by a malicious host. Even if we added a "you are not allowed to use the export directly" boolean field, malicious hosts could always manually edit that field out before compiling (or just plain ingore that field).

My understanding of interface types was that they would provide two types of security:

Both of those can be enforced as long as a host links adapted modules imports to adapted module exports, and doesn't link bare module imports/exports together. Making sure the host handles these cases correctly doesn't seem like something that could or should be enforced by the language.

EDIT: Never mind. I misunderstood what @fgmccabe was saying.

I think what it comes down to is what is the "default" linking model we want wasm to have.

I'm not sure how to resolve this. Though I'm thinking even the esm-integration model should probably have some way to differentiate between things you want to export to the host, and things you want to export to importing modules.

lukewagner commented 4 years ago

As a follow-up from some offline discussion: I think the source of the confusion here is resolved by the observation that, once a host has implemented the interface types feature, when an interface adapter custom section is present in a module:

  1. it cannot be optionally ignored; the engine necessarily encapsulates the core module with an adapted module
  2. all core module imports/exports must be explicitly forwarded to show up in the adapted module's imports/exports

(This is briefly covered in the walkthrough which explicitly notes that the greeting_ and mem core exports do not show up in the adapted module's exports.)

As a corollary to (2), adding a single @interface definition will cause all core imports/exports to be hidden by default, requiring explicit re-export (perhaps with some syntactic sugar to explicitly request core imports/exports be present in the adapted module by default).