gecko-dev/third_party/rust/rlbox_lucet_sandbox
shravanrn@gmail.com d475a75904 Bug 1670878: Instantiating a large number of wasm library sandboxes crashes due to overuse of file descriptors r=tjr
Instantiating a wasm library duplicates a file descriptor for /dev/null 3 times to be used as input, output and error streams for the wasm sandboxed code. When a lot of sandboxes are created and destroyed, a lot of descriptors are duplicated and closed. While this should be fine, POSIX does not seem to happy with the opening and closing of many file descriptors --- this could perhaps be some strange interaction with Firefox's seccomp filters and cross-process file descriptor handling as it is difficult to repro this outside of firefox.

However, the simpler fix here was to just eliminate the duplication of /dev/null and return an error when input, output or error streams are accessed by wasm sandboxed code. This means calls to printf will fail, but no code I know off actually checks the int error code returned by printf and this change is certainly compatible with existing sandboxed components.

Differential Revision: https://phabricator.services.mozilla.com/D99160
2020-12-09 21:54:03 +00:00
..
c_src
include Bug 1670878: Instantiating a large number of wasm library sandboxes crashes due to overuse of file descriptors r=tjr 2020-12-09 21:54:03 +00:00
src
test
.cargo-checksum.json Bug 1670878: Instantiating a large number of wasm library sandboxes crashes due to overuse of file descriptors r=tjr 2020-12-09 21:54:03 +00:00
.clang-format
.clang-tidy
.travis.yml
CMakeLists.txt
Cargo.toml Bug 1670878: Instantiating a large number of wasm library sandboxes crashes due to overuse of file descriptors r=tjr 2020-12-09 21:54:03 +00:00
LICENSE
README.md Bug 1670878: Instantiating a large number of wasm library sandboxes crashes due to overuse of file descriptors r=tjr 2020-12-09 21:54:03 +00:00

README.md

Build Status

RLBOX Lucet Sandbox Integration

Integration with RLBox sandboxing API to leverage the sandboxing in WASM modules compiled with lucet compiler.

For details about the RLBox sandboxing APIs, see here.

This code has been tested on 64-bit versions of Ubuntu and Mac OSX. The lucet compiler does not currently support Windows.

Reporting security bugs

If you find a security bug, please do not create a public issue. Instead, file a security bug on bugzilla using the following template link.

Building/Running the tests

You can build and run the tests using cmake with the following commands.

cmake -S . -B ./build
cmake --build ./build --target all
cmake --build ./build --target test

On Arch Linux you'll need to install ncurses5-compat-libs.

Using this library

First, build the rlbox_lucet_sandbox repo with

cmake -S . -B ./build
cmake --build ./build --target all

(Note: The parallel build is currently broken for first build. Incremental parallel build works fine.)

This lucet/wasm integration with RLBox depends on 3 external tools/libraries that are pulled in automatically to run the tests included in this repo.

  1. A clang compiler with support for WASM/WASI backend, and the WASI sysroot. This allows you to compile C/C++ code to WASM modules usable outside of web browsers (in desktop applications).
  2. The modified lucet compiler that compiles the produced WASM/WASI module to a native binary.
  3. The RLBox APIs - A set of APIs that allow easy use of sandboxed libraries.

In the below steps, you can either use the automatically pulled in versions as described below, or download the tools yourself.

In order to sandbox a library of your choice.

  • Build the sources of your library along with the file c_src/lucet_sandbox_wrapper.c and passing the flag --export-all to the linker using the clang compiler described above. This will produce a wasm module. The required clang compiler is available in the path build/_deps/wasiclang-src/opt/wasi-sdk/bin/clang. For instance, to edit an existing make based build system, you can run the commmand.
build/_deps/wasiclang-src/opt/wasi-sdk/bin/clang --sysroot build/_deps/wasiclang-src/opt/wasi-sdk/share/wasi-sysroot/ c_src/lucet_sandbox_wrapper.c -c -o c_src/lucet_sandbox_wrapper.o

CC=build/_deps/wasiclang-src/opt/wasi-sdk/bin/clang                            \
CXX=build/_deps/wasiclang-src/opt/wasi-sdk/bin/clang++                         \
CFLAGS="--sysroot build/_deps/wasiclang-src/opt/wasi-sdk/share/wasi-sysroot/"  \
LD=build/_deps/wasiclang-src/opt/wasi-sdk/bin/wasm-ld                          \
LDLIBS=lucet_sandbox_wrapper.o                                                 \
LDFLAGS=-Wl,--export-all                                                       \
make
  • Assuming the above command produced the wasm module libFoo, compile this to an ELF shared library using the modified lucetc compiler as shown below.
build/cargo/release/lucetc                                        \
    --bindings build/_deps/mod_lucet-src/lucet-wasi/bindings.json \
    --guard-size "4GiB"                                           \
    --min-reserved-size "4GiB"                                    \
    --max-reserved-size "4GiB"                                    \
    libFoo                                                        \
    -o libWasmFoo.so
  • Finally you can write sandboxed code, just as you would with any other RLBox sandbox, such as in the short example below. For more detailed examples, please refer to the tutorial in the RLBox Repo.
#include "rlbox_lucet_sandbox.hpp"
#include "rlbox.hpp"

int main()
{
    rlbox_sandbox<rlbox_lucet_sandbox> sandbox;
    sandbox.create_sandbox("libWasmFoo.so");
    // Invoke function bar with parameter 1
    sandbox.invoke_sandbox_function(bar, 1);
    sandbox.destroy_sandbox();
    return 0;
}
  • To compile the above example, you must include the rlbox header files in build/_deps/rlbox-src/code/include, the integration header files in include/ and the lucet_sandbox library in build/cargo/{debug or release}/librlbox_lucet_sandbox.a (make sure to use the whole archive and the rdynamic linker options). For instance, you can compile the above with
g++ -std=c++17 example.cpp -o example -I build/_deps/rlbox-src/code/include -I include -Wl,--whole-archive -l:build/cargo/debug/librlbox_lucet_sandbox.a -Wl,--no-whole-archive -Wl,-rdynamic

Contributing Code

  1. To contribute code, it is recommended you install clang-tidy which the build uses if available. Install using:

    On Ubuntu:

sudo apt install clang-tidy

On Arch Linux:

sudo pacman -S clang-tidy
  1. It is recommended you use the dev mode for building during development. This treat warnings as errors, enables clang-tidy checks, runs address sanitizer etc. Also, you probably want to use the debug build. To do this, adjust your build settings as shown below
cmake -DCMAKE_BUILD_TYPE=Debug -DDEV=ON -S . -B ./build
  1. After making changes to the source, add any new required tests and run all tests as described earlier.

  2. To make sure all code/docs are formatted with, we use clang-format. Install using:

    On Ubuntu:

sudo apt install clang-format

On Arch Linux:

sudo pacman -S clang-format
  1. Format code with the format-source target:
cmake --build ./build --target format-source
  1. Submit the pull request.