lucet icon indicating copy to clipboard operation
lucet copied to clipboard

Allow use of per sandbox instance mutable callback tables

Open shravanrn opened this issue 4 years ago • 3 comments

Context This is part of a series of bugs that I spoke to @tyler @pchickey about. We are currently using Lucet to sandbox libraries in C++ applications. The idea behind this is that using a wasm sandboxed version of the library allows ensuring that a memory safety issue in the library does not automatically result in a memory safety vulnerability in the full application. One of the consumers of this work is the Firefox web browser.

Problem The security model behind the library sandboxing relies on an application being able to use multiple instances of the same sandboxed library. Thus, we need to be able to spin up multiple completely isolated sandbox instances for the same wasm. At this time, the wasm table that holds the list of exposed host calls is shared when creating multiple sandbox instances for the same library. This also means that the set of host calls exposed by the application cannot support mutation by the application (which is supported by the WASM standard). This also significantly weakens security for library sandboxing.

Actions @pchickey mentioned that there is already some work on this, which is fantastic. I have just opened this bug so that we can easily track this request/progress. In case you already have a bug for this (I had a quick look, but couldn't find it) feel free to close it. Also, if there is something I can help with re this bug, please let me know.

shravanrn avatar Sep 05 '19 02:09 shravanrn

@shravanrn just to clarify, is this issue about being able to change the Wasm module's import functions (what we mostly call hostcalls) between instances, or about being able to mutate the Wasm tables within an instance? If it's the latter, I'm currently working on that in service of implementing the reference-types proposal in https://github.com/fastly/lucet/issues/272. We are thinking that a similar mechanism might be used to address the former problem as well, but that is currently further down the line in our planning.

acfoltzer avatar Sep 05 '19 18:09 acfoltzer

Well its kind of both in a way... This is basically the latter (mutation of wasm tables), but is being used for host calls in the library sandboxing use case. I have a description of why in Bug #280, (which I realize I should have included here as well :smiley: ) Quoting from that

The reason we are using the function indirection table for host calls is that, we cannot use the same approach as is used in the Lucet code base. I believe lucet specifies all host calls at compile time in a "bindings.json" file. However, in our case, the set of allowed host calls

  1. Can change dynamically
  2. Are not static calls, but are indirect calls (invoked via a function pointer)

In case it helps the use case needs to support examples such as below

// Library
int add(int a, int(*callback)()) {
    return a + callback();
}
// Application
int five() { return 5; }

int test_add(lib) {
    indirection_table_index = lucet_add_to_function_table(lib, five);
    ret = lucet_invoke_function(lib, "add", 2, indirection_table_index);
    lucet_remove_from_table(lib, indirection_table_index);
    assert(ret == 7);
}

int main()
{
    for (i = 0, i < 5; i++) {
            lib = lucet_load("Library.so");
            thread_start(test_add, lib);
    }
}

@acfoltzer - Hope the example clarifies things. Do you think the above scenario would be supported as a part of #272?

shravanrn avatar Sep 05 '19 18:09 shravanrn

Yes, definitely. And in fact, the example you provided is similar to one potential approach we have for overhauling hostcalls altogether; calls to Wasm imports would be transformed into call_indirects targeting an imported table that the runtime populates with pointers to the hostcalls.

acfoltzer avatar Sep 05 '19 20:09 acfoltzer