summaryrefslogtreecommitdiffstats
path: root/third_party/rust/rlbox_lucet_sandbox
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/rlbox_lucet_sandbox
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/rlbox_lucet_sandbox')
-rw-r--r--third_party/rust/rlbox_lucet_sandbox/.cargo-checksum.json1
-rw-r--r--third_party/rust/rlbox_lucet_sandbox/.clang-format121
-rw-r--r--third_party/rust/rlbox_lucet_sandbox/.clang-tidy3
-rw-r--r--third_party/rust/rlbox_lucet_sandbox/.travis.yml12
-rw-r--r--third_party/rust/rlbox_lucet_sandbox/CMakeLists.txt275
-rw-r--r--third_party/rust/rlbox_lucet_sandbox/Cargo.toml22
-rw-r--r--third_party/rust/rlbox_lucet_sandbox/LICENSE21
-rw-r--r--third_party/rust/rlbox_lucet_sandbox/README.md140
-rw-r--r--third_party/rust/rlbox_lucet_sandbox/c_src/CMakeLists.txt69
-rw-r--r--third_party/rust/rlbox_lucet_sandbox/c_src/lucet_sandbox_wrapper.c138
-rw-r--r--third_party/rust/rlbox_lucet_sandbox/include/lucet_sandbox.h71
-rw-r--r--third_party/rust/rlbox_lucet_sandbox/include/rlbox_lucet_sandbox.hpp881
-rw-r--r--third_party/rust/rlbox_lucet_sandbox/src/callback.rs51
-rw-r--r--third_party/rust/rlbox_lucet_sandbox/src/create.rs94
-rw-r--r--third_party/rust/rlbox_lucet_sandbox/src/invoke.rs29
-rw-r--r--third_party/rust/rlbox_lucet_sandbox/src/lib.rs5
-rw-r--r--third_party/rust/rlbox_lucet_sandbox/src/memory.rs35
-rw-r--r--third_party/rust/rlbox_lucet_sandbox/src/types.rs160
-rw-r--r--third_party/rust/rlbox_lucet_sandbox/test/test_lucet_sandbox_glue.cpp17
-rw-r--r--third_party/rust/rlbox_lucet_sandbox/test/test_lucet_sandbox_glue_embedder_vars.cpp19
-rw-r--r--third_party/rust/rlbox_lucet_sandbox/test/test_lucet_sandbox_glue_main.cpp2
-rw-r--r--third_party/rust/rlbox_lucet_sandbox/test/test_lucet_sandbox_glue_preload.cpp27
22 files changed, 2193 insertions, 0 deletions
diff --git a/third_party/rust/rlbox_lucet_sandbox/.cargo-checksum.json b/third_party/rust/rlbox_lucet_sandbox/.cargo-checksum.json
new file mode 100644
index 0000000000..5b3fe66ba0
--- /dev/null
+++ b/third_party/rust/rlbox_lucet_sandbox/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{".clang-format":"ff4e345608f7674dd1ee1f37b24d4030b260d82516a747093af141b3076a4164",".clang-tidy":"861bc5b367dc85f5fa103f2de9460e158de97f48c59c51a26784b7c2c481e3b7",".travis.yml":"a49b61a394520c39bb20c420b587e92ea9c8008764fef0368c4747b71b8f1561","CMakeLists.txt":"161ff8596a347890a6448cfe5881e298a76b01da1e1080ec383368de0e1f280a","Cargo.toml":"66ff60962b9b5cfb6b3bf0967d62d12cbdb70214ad310ba3f7201ae6b99f2955","LICENSE":"891d419ba95ab39090775820f4178421dbdcd241c080003aa44f62445a48615a","README.md":"d64cc632f6dc9178efe63cb717a9af3728e5536cc49d977dd2ddb126b6fe28e5","c_src/CMakeLists.txt":"7208135bf7f2ca1443fec1ca0a3f992932f5b0635e6eb7da07b126b8520e5ef5","c_src/lucet_sandbox_wrapper.c":"08b2ab265127aca42b02c8a36e5450284d6794d86867a5808f854588183ab9d9","include/lucet_sandbox.h":"8d24bd5fbd4f717f0bb90b238a7b7fbdd212207297ddf1a723cc98ee13180c5b","include/rlbox_lucet_sandbox.hpp":"b58ffed66d8b3e516c9847ef8da512dd4249b3d6f5ac01b062080b1564c9cddc","src/callback.rs":"c40f92e017bc8f2f3136304c1f2d3ca683fe80a1bb505c0fa750cc372305020d","src/create.rs":"5d620a050c1990e7215346fe144a7be7c0e4bb396068ac81ae8b21fb1fdb3dca","src/invoke.rs":"d47b167c6048a3221f5e66a4acb5154bc5306bd1053acee56bfb87bb66c78879","src/lib.rs":"677f45b275101c116ea7acf2dafa77f9f1c5e3f379d4da3a9512c71a71878595","src/memory.rs":"8b27396ec4ddba18ac760052e9d11564fdc8c4e68271b817dfd13cefc97cf1a3","src/types.rs":"85907840c233aae0e234bcb5c1e107e76231b6518cc70a1c18be73edc2720742","test/test_lucet_sandbox_glue.cpp":"ea4eb3ace8e9a87550db44f61d065b45f31f1f5b774b4a3e0383e62962c0abf2","test/test_lucet_sandbox_glue_embedder_vars.cpp":"be6abfae367719b12edc5fd8f1de840abed9bb4a2efdebb19ed59e8796fb47b8","test/test_lucet_sandbox_glue_main.cpp":"fde2081cd8b0df3fd73fee1e36dfa5eccfb5bc825072c55a57fcf3048858dbd9","test/test_lucet_sandbox_glue_preload.cpp":"c986ac617327305fcc3ea33114667d4c833ee685c740e482ffde97de4f203e35"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/rlbox_lucet_sandbox/.clang-format b/third_party/rust/rlbox_lucet_sandbox/.clang-format
new file mode 100644
index 0000000000..c0c3137a82
--- /dev/null
+++ b/third_party/rust/rlbox_lucet_sandbox/.clang-format
@@ -0,0 +1,121 @@
+---
+Language: Cpp
+# BasedOnStyle: Mozilla
+AccessModifierOffset: -2
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlines: Right
+AlignOperands: true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: false
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: Inline
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: Yes
+BinPackArguments: false
+BinPackParameters: false
+BraceWrapping:
+ AfterClass: true
+ AfterControlStatement: false
+ AfterEnum: true
+ AfterFunction: true
+ AfterNamespace: false
+ AfterObjCDeclaration: false
+ AfterStruct: true
+ AfterUnion: true
+ AfterExternBlock: true
+ BeforeCatch: false
+ BeforeElse: false
+ IndentBraces: false
+ SplitEmptyFunction: true
+ SplitEmptyRecord: false
+ SplitEmptyNamespace: true
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Mozilla
+BreakBeforeInheritanceComma: false
+BreakInheritanceList: BeforeComma
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: false
+BreakConstructorInitializers: BeforeComma
+BreakAfterJavaFieldAnnotations: false
+BreakStringLiterals: true
+ColumnLimit: 80
+CommentPragmas: '^ IWYU pragma:'
+CompactNamespaces: false
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 2
+ContinuationIndentWidth: 2
+Cpp11BracedListStyle: false
+DerivePointerAlignment: false
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+FixNamespaceComments: false
+ForEachMacros:
+ - foreach
+ - Q_FOREACH
+ - BOOST_FOREACH
+IncludeBlocks: Preserve
+IncludeCategories:
+ - Regex: '^"'
+ Priority: 3
+ - Regex: '^<'
+ Priority: 2
+ - Regex: '.*'
+ Priority: 1
+IncludeIsMainRegex: '(Test)?$'
+IndentCaseLabels: true
+IndentPPDirectives: AfterHash
+IndentWidth: 2
+IndentWrappedFunctionNames: false
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: true
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: Inner
+ObjCBinPackProtocolList: Auto
+ObjCBlockIndentWidth: 2
+ObjCSpaceAfterProperty: true
+ObjCSpaceBeforeProtocolList: false
+PenaltyBreakAssignment: 2
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyBreakTemplateDeclaration: 10
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 200
+PointerAlignment: Left
+ReflowComments: true
+SortIncludes: true
+SortUsingDeclarations: true
+SpaceAfterCStyleCast: false
+SpaceAfterTemplateKeyword: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeCpp11BracedList: false
+SpaceBeforeCtorInitializerColon: true
+SpaceBeforeInheritanceColon: true
+SpaceBeforeParens: ControlStatements
+SpaceBeforeRangeBasedForLoopColon: true
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Cpp11
+StatementMacros:
+ - Q_UNUSED
+ - QT_REQUIRE_VERSION
+TabWidth: 8
+UseTab: Never
+...
+
diff --git a/third_party/rust/rlbox_lucet_sandbox/.clang-tidy b/third_party/rust/rlbox_lucet_sandbox/.clang-tidy
new file mode 100644
index 0000000000..54ca78e7d4
--- /dev/null
+++ b/third_party/rust/rlbox_lucet_sandbox/.clang-tidy
@@ -0,0 +1,3 @@
+Checks: '*,-modernize-use-trailing-return-type'
+HeaderFilterRegex: '*'
+WarningsAsErrors: '*' \ No newline at end of file
diff --git a/third_party/rust/rlbox_lucet_sandbox/.travis.yml b/third_party/rust/rlbox_lucet_sandbox/.travis.yml
new file mode 100644
index 0000000000..0c4a38fc28
--- /dev/null
+++ b/third_party/rust/rlbox_lucet_sandbox/.travis.yml
@@ -0,0 +1,12 @@
+dist: bionic
+language: rust
+
+script:
+ # Install a more recent cmake
+ - wget https://cmake.org/files/v3.16/cmake-3.16.0-Linux-x86_64.tar.gz
+ - tar xzvf cmake-3.16.0-Linux-x86_64.tar.gz
+ - mkdir ./build
+ - cd ./build
+ - ../cmake-3.16.0-Linux-x86_64/bin/cmake -S ..
+ - make
+ - make test
diff --git a/third_party/rust/rlbox_lucet_sandbox/CMakeLists.txt b/third_party/rust/rlbox_lucet_sandbox/CMakeLists.txt
new file mode 100644
index 0000000000..014680ee98
--- /dev/null
+++ b/third_party/rust/rlbox_lucet_sandbox/CMakeLists.txt
@@ -0,0 +1,275 @@
+cmake_minimum_required(VERSION 3.13)
+
+project(rlbox_lucet
+ VERSION 0.1
+ DESCRIPTION "RLBox integration with WASM modules compiled with lucet")
+
+# Project Settings ###################
+
+# set(CMAKE_VERBOSE_MAKEFILE ON)
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS OFF)
+
+option(DEV "Use settings suitable for dev contributions to rlbox" OFF)
+
+file(GLOB_RECURSE
+ ALL_CXX_SOURCE_FILES
+ ${CMAKE_SOURCE_DIR}/include/*.[chi]pp
+ ${CMAKE_SOURCE_DIR}/include/*.[chi]xx
+ ${CMAKE_SOURCE_DIR}/include/*.cc
+ ${CMAKE_SOURCE_DIR}/include/*.hh
+ ${CMAKE_SOURCE_DIR}/include/*.ii
+ ${CMAKE_SOURCE_DIR}/include/*.[CHI]
+ ${CMAKE_SOURCE_DIR}/test/*.[chi]pp
+ ${CMAKE_SOURCE_DIR}/test/*.[chi]xx
+ ${CMAKE_SOURCE_DIR}/test/*.cc
+ ${CMAKE_SOURCE_DIR}/test/*.hh
+ ${CMAKE_SOURCE_DIR}/test/*.ii
+ ${CMAKE_SOURCE_DIR}/test/*.[CHI]
+ ${CMAKE_SOURCE_DIR}/c_src/*.[chi]pp
+ ${CMAKE_SOURCE_DIR}/c_src/*.[chi]xx
+ ${CMAKE_SOURCE_DIR}/c_src/*.cc
+ ${CMAKE_SOURCE_DIR}/c_src/*.hh
+ ${CMAKE_SOURCE_DIR}/c_src/*.ii
+ ${CMAKE_SOURCE_DIR}/c_src/*.[CHI])
+
+# Dev Tools ###################
+
+if(DEV)
+ if(MSVC)
+ add_compile_options(/W4) # warnings
+ add_compile_options(/WX) # warnings as errors
+ else()
+ add_compile_options(-Wall -Wextra -pedantic) # warnings
+ add_compile_options(-Werror) # warnings as errors
+ add_compile_options(-fsanitize=address)
+ add_link_options(-fsanitize=address)
+ add_compile_options(-fsanitize=undefined)
+ add_link_options(-fsanitize=undefined)
+ endif()
+
+ find_program(CLANG_TIDY "clang-tidy")
+ if(CLANG_TIDY)
+ # Config in .clang-tidy
+ set(CMAKE_CXX_CLANG_TIDY clang-tidy)
+ endif()
+
+ find_program(CLANG_FORMAT "clang-format")
+ if(CLANG_FORMAT)
+ # Config in .clang-format
+ add_custom_target(format-source
+ COMMAND clang-format
+ -i
+ -style=file
+ ${ALL_CXX_SOURCE_FILES})
+ endif()
+
+endif()
+
+# Dependencies ###################
+
+find_program(CARGO "cargo")
+if(!CARGO)
+ message(
+ FATAL_ERROR
+ "Could not find cargo. Please install cargo as it is needed to build rust libraries."
+ )
+endif()
+
+include(FetchContent)
+
+FetchContent_Declare(
+ rlbox
+ GIT_REPOSITORY https://github.com/PLSysSec/rlbox_api_cpp17.git)
+FetchContent_GetProperties(rlbox)
+if(NOT rlbox_POPULATED)
+ FetchContent_Populate(rlbox)
+endif()
+
+FetchContent_Declare(catch2
+ GIT_REPOSITORY https://github.com/catchorg/Catch2.git
+ GIT_TAG v2.9.1)
+FetchContent_GetProperties(catch2)
+if(NOT catch2_POPULATED)
+ FetchContent_Populate(catch2)
+endif()
+
+add_subdirectory("${catch2_SOURCE_DIR}")
+list(APPEND CMAKE_MODULE_PATH "${catch2_SOURCE_DIR}/contrib")
+
+if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ FetchContent_Declare(
+ wasiclang
+ URL
+ https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-11/wasi-sdk-11.0-macos.tar.gz
+ )
+else()
+ FetchContent_Declare(
+ wasiclang
+ URL
+ https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-11/wasi-sdk-11.0-linux.tar.gz
+ )
+endif()
+FetchContent_GetProperties(wasiclang)
+if(NOT wasiclang_POPULATED)
+ FetchContent_Populate(wasiclang)
+endif()
+
+FetchContent_Declare(
+ mod_lucet
+ GIT_REPOSITORY https://github.com/PLSysSec/lucet_sandbox_compiler)
+FetchContent_GetProperties(mod_lucet)
+if(NOT mod_lucet_POPULATED)
+ FetchContent_Populate(mod_lucet)
+endif()
+
+# Rust Lib ###################
+
+if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ set(DYLIB_EXT "dylib")
+else()
+ set(DYLIB_EXT "so")
+endif()
+set(LUCET_DIR "${CMAKE_BINARY_DIR}/cargo/release/")
+set(LUCET_PATH "${LUCET_DIR}/lucetc")
+file(GLOB_RECURSE LUCET_SOURCE_FILES ${mod_lucet_SOURCE_DIR}/*.rs ${mod_lucet_SOURCE_DIR}/*.S)
+
+add_custom_command(OUTPUT ${LUCET_PATH}
+ DEPENDS ${LUCET_SOURCE_FILES}
+ ${mod_lucet_SOURCE_DIR}/Cargo.toml
+ COMMAND CARGO_TARGET_DIR=${CMAKE_BINARY_DIR}/cargo
+ ${CARGO}
+ build
+ --release
+ WORKING_DIRECTORY ${mod_lucet_SOURCE_DIR}
+ COMMENT "Building customized lucet compiler")
+add_custom_target(lucet_release ALL DEPENDS ${LUCET_PATH})
+
+# set(mod_lucet_SOURCE_DIR "${CMAKE_SOURCE_DIR}/../lucet_sandbox_compiler")
+# set(LUCET_DIR "${mod_lucet_SOURCE_DIR}/target/debug/")
+# set(LUCET_PATH "${LUCET_DIR}/lucetc")
+
+file(GLOB_RECURSE RUST_SOURCE_FILES ${CMAKE_SOURCE_DIR}/src/*.rs)
+
+set(RUST_LIB_DEBUG_PATH
+ "${CMAKE_BINARY_DIR}/cargo/debug/librlbox_lucet_sandbox.a")
+add_custom_command(OUTPUT ${RUST_LIB_DEBUG_PATH}
+ DEPENDS ${RUST_SOURCE_FILES} ${LUCET_SOURCE_FILES} Cargo.toml
+ COMMAND CARGO_TARGET_DIR=${CMAKE_BINARY_DIR}/cargo ${CARGO}
+ build
+ COMMENT "Building librlbox_lucet_sandbox debug")
+add_custom_target(lucet_sandbox_rustlib_debug ALL
+ DEPENDS ${RUST_LIB_DEBUG_PATH})
+
+set(RUST_LIB_RELEASE_PATH
+ "${CMAKE_BINARY_DIR}/cargo/release/librlbox_lucet_sandbox.a")
+add_custom_command(OUTPUT ${RUST_LIB_RELEASE_PATH}
+ DEPENDS ${RUST_SOURCE_FILES} ${LUCET_SOURCE_FILES} Cargo.toml
+ COMMAND CARGO_TARGET_DIR=${CMAKE_BINARY_DIR}/cargo
+ ${CARGO}
+ build
+ --release
+ COMMENT "Building librlbox_lucet_sandbox release")
+add_custom_target(lucet_sandbox_rustlib_release ALL
+ DEPENDS ${RUST_LIB_RELEASE_PATH})
+
+add_library(lucet_sandbox_rustlib SHARED IMPORTED)
+set_target_properties(lucet_sandbox_rustlib
+ PROPERTIES IMPORTED_LOCATION ${RUST_LIB_DEBUG_PATH})
+set_target_properties(lucet_sandbox_rustlib
+ PROPERTIES IMPORTED_LOCATION_DEBUG ${RUST_LIB_DEBUG_PATH})
+set_target_properties(lucet_sandbox_rustlib
+ PROPERTIES IMPORTED_LOCATION_RELEASE
+ ${RUST_LIB_RELEASE_PATH})
+# The wasi symbols needed by the wasm module are in this static lib, but must
+# be part of the symbol table (locatable through dlsym). We need the following
+# flag for this.
+if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+target_link_options(lucet_sandbox_rustlib INTERFACE "-framework" "Security" "-rdynamic")
+else()
+target_link_options(lucet_sandbox_rustlib INTERFACE "-rdynamic")
+endif()
+# Tests ###################
+
+include(CTest)
+include(Catch)
+
+find_program(WASMCLANG "clang")
+
+if(!WASMCLANG)
+ message(
+ FATAL_ERROR
+ "Require clang with support for target 'wasm32-wasi' to build the WASM module"
+ )
+endif()
+
+file(GLOB_RECURSE C_SOURCE_FILES ${CMAKE_SOURCE_DIR}/c_src/*)
+set(GLUE_LIB_WASM "${CMAKE_BINARY_DIR}/wasm/glue_lib_lucet.wasm")
+set(GLUE_LIB_SO "${CMAKE_BINARY_DIR}/wasm/glue_lib_lucet.${DYLIB_EXT}")
+
+add_custom_command(OUTPUT ${GLUE_LIB_WASM} ${GLUE_LIB_SO}
+ DEPENDS ${C_SOURCE_FILES}
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/c_src
+ COMMAND rlbox_SOURCE_DIR=${rlbox_SOURCE_DIR}
+ wasiclang_SOURCE_DIR=${wasiclang_SOURCE_DIR}
+ LUCET_DIR=${LUCET_DIR}
+ LUCET_WASI_DIR=${mod_lucet_SOURCE_DIR}/lucet-wasi
+ ${CMAKE_COMMAND}
+ -S
+ .
+ -B
+ ${CMAKE_BINARY_DIR}/wasm
+ COMMAND VERBOSE=1
+ ${CMAKE_COMMAND}
+ --build
+ ${CMAKE_BINARY_DIR}/wasm
+ --target
+ all
+ COMMENT "Building wasm library")
+
+add_custom_target(glue_lib_wasm ALL DEPENDS lucet_release ${GLUE_LIB_WASM} ${GLUE_LIB_SO})
+
+add_executable(test_rlbox_glue test/test_lucet_sandbox_glue_main.cpp
+ test/test_lucet_sandbox_glue.cpp
+ test/test_lucet_sandbox_glue_preload.cpp
+ test/test_lucet_sandbox_glue_embedder_vars.cpp)
+target_include_directories(test_rlbox_glue PUBLIC include)
+target_include_directories(test_rlbox_glue
+ PUBLIC ${rlbox_SOURCE_DIR}/code/include)
+target_include_directories(test_rlbox_glue
+ PUBLIC ${rlbox_SOURCE_DIR}/code/tests/rlbox_glue)
+target_include_directories(test_rlbox_glue
+ PUBLIC ${rlbox_SOURCE_DIR}/code/tests/rlbox_glue/lib)
+
+find_package(Threads REQUIRED)
+
+target_compile_definitions(test_rlbox_glue PUBLIC
+ GLUE_LIB_LUCET_PATH="${GLUE_LIB_SO}")
+
+add_dependencies(test_rlbox_glue lucet_sandbox_rustlib_debug lucet_sandbox_rustlib_release)
+
+if(MSVC)
+ set(LINK_LUCET_LIB -WHOLEARCHIVE lucet_sandbox_rustlib)
+else()
+ set(LINK_LUCET_LIB -Wl,--whole-archive lucet_sandbox_rustlib -Wl,--no-whole-archive)
+endif()
+
+target_link_libraries(test_rlbox_glue
+ Catch2::Catch2
+ ${LINK_LUCET_LIB}
+ ${CMAKE_THREAD_LIBS_INIT}
+ ${CMAKE_DL_LIBS}
+ # glue_lib_lucet
+ )
+
+if(UNIX AND NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin"))
+ target_link_libraries(test_rlbox_glue rt)
+endif()
+catch_discover_tests(test_rlbox_glue)
+
+# Shortcuts ###################
+
+add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} -V)
+add_dependencies(check test_rlbox_glue)
+
diff --git a/third_party/rust/rlbox_lucet_sandbox/Cargo.toml b/third_party/rust/rlbox_lucet_sandbox/Cargo.toml
new file mode 100644
index 0000000000..444d03f4f0
--- /dev/null
+++ b/third_party/rust/rlbox_lucet_sandbox/Cargo.toml
@@ -0,0 +1,22 @@
+[package]
+name = "rlbox_lucet_sandbox"
+version = "0.1.0"
+authors = ["shravanrn@gmail.com <shravanrn@gmail.com>"]
+edition = "2018"
+license = "MIT"
+
+[dependencies]
+failure = ">=0.1.3" # Experimental error handling abstraction.
+goblin = ">=0.0.17" # An impish, cross-platform, ELF, Mach-o, and PE binary parsing and loading crate
+lucet-wasi = { git = "https://github.com/PLSysSec/lucet_sandbox_compiler", rev="cd07861d1c92147b35b538e6f94fde7d1986f9ad", package = "lucet-wasi-wasmsbx" }
+lucet-runtime = { git = "https://github.com/PLSysSec/lucet_sandbox_compiler", rev="cd07861d1c92147b35b538e6f94fde7d1986f9ad", package = "lucet-runtime-wasmsbx" }
+lucet-runtime-internals = { git = "https://github.com/PLSysSec/lucet_sandbox_compiler", rev="cd07861d1c92147b35b538e6f94fde7d1986f9ad", package = "lucet-runtime-internals-wasmsbx" }
+lucet-module = { git = "https://github.com/PLSysSec/lucet_sandbox_compiler", rev="cd07861d1c92147b35b538e6f94fde7d1986f9ad", package = "lucet-module-wasmsbx" }
+# lucet-wasi = { path = "../lucet_sandbox_compiler/lucet-wasi", package = "lucet-wasi-wasmsbx" }
+# lucet-runtime = { path = "../lucet_sandbox_compiler/lucet-runtime", package = "lucet-runtime-wasmsbx" }
+# lucet-runtime-internals = { path = "../lucet_sandbox_compiler/lucet-runtime/lucet-runtime-internals", package = "lucet-runtime-internals-wasmsbx" }
+# lucet-module = { path = "../lucet_sandbox_compiler/lucet-module", package = "lucet-module-wasmsbx" }
+
+[lib]
+name = "rlbox_lucet_sandbox"
+crate-type = ["rlib", "staticlib"] \ No newline at end of file
diff --git a/third_party/rust/rlbox_lucet_sandbox/LICENSE b/third_party/rust/rlbox_lucet_sandbox/LICENSE
new file mode 100644
index 0000000000..87e0ce55af
--- /dev/null
+++ b/third_party/rust/rlbox_lucet_sandbox/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 UCSD PLSysSec
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/third_party/rust/rlbox_lucet_sandbox/README.md b/third_party/rust/rlbox_lucet_sandbox/README.md
new file mode 100644
index 0000000000..bcab639582
--- /dev/null
+++ b/third_party/rust/rlbox_lucet_sandbox/README.md
@@ -0,0 +1,140 @@
+[![Build Status](https://travis-ci.com/PLSysSec/rlbox_lucet_sandbox.svg?branch=master)](https://travis-ci.com/PLSysSec/rlbox_lucet_sandbox)
+
+# 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](https://github.com/PLSysSec/rlbox_api_cpp17).
+
+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](https://bugzilla.mozilla.org/enter_bug.cgi?cc=tom%40mozilla.com&cc=nfroyd%40mozilla.com&cc=deian%40cs.ucsd.edu&cc=shravanrn%40gmail.com&component=Security%3A%20Process%20Sandboxing&defined_groups=1&groups=core-security&product=Core&bug_type=defect).
+
+## Building/Running the tests
+
+You can build and run the tests using cmake with the following commands.
+
+```bash
+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](https://aur.archlinux.org/packages/ncurses5-compat-libs/).
+
+## Using this library
+
+First, build the rlbox_lucet_sandbox repo with
+
+```bash
+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](https://github.com/CraneStation/wasi-sdk). This allows you to compile C/C++ code to WASM modules usable outside of web browsers (in desktop applications).
+2. [The **modified** lucet compiler](https://github.com/shravanrn/lucet/) that compiles the produced WASM/WASI module to a native binary.
+3. [The RLBox APIs]((https://github.com/PLSysSec/rlbox_api_cpp17)) - 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.
+
+```bash
+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.
+
+```bash
+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]((https://github.com/PLSysSec/rlbox_api_cpp17)).
+
+
+```c++
+#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
+
+```bash
+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:
+```bash
+sudo apt install clang-tidy
+```
+ On Arch Linux:
+```bash
+sudo pacman -S clang-tidy
+```
+
+2. 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
+
+```bash
+cmake -DCMAKE_BUILD_TYPE=Debug -DDEV=ON -S . -B ./build
+```
+
+3. After making changes to the source, add any new required tests and run all
+tests as described earlier.
+
+4. To make sure all code/docs are formatted with, we use clang-format.
+Install using:
+
+ On Ubuntu:
+```bash
+sudo apt install clang-format
+```
+ On Arch Linux:
+```bash
+sudo pacman -S clang-format
+```
+
+5. Format code with the format-source target:
+```bash
+cmake --build ./build --target format-source
+```
+
+6. Submit the pull request.
diff --git a/third_party/rust/rlbox_lucet_sandbox/c_src/CMakeLists.txt b/third_party/rust/rlbox_lucet_sandbox/c_src/CMakeLists.txt
new file mode 100644
index 0000000000..7e2d60a830
--- /dev/null
+++ b/third_party/rust/rlbox_lucet_sandbox/c_src/CMakeLists.txt
@@ -0,0 +1,69 @@
+cmake_minimum_required(VERSION 3.13)
+
+# Mac adds extra flags
+set(HAVE_FLAG_SEARCH_PATHS_FIRST 0)
+
+project(rlbox_lucet_testlib
+ VERSION 0.1
+ DESCRIPTION "RLBox integration with WASM modules compiled with lucet")
+
+if(NOT DEFINED ENV{rlbox_SOURCE_DIR})
+ message(FATAL_ERROR "Set rlbox_SOURCE_DIR environment variable")
+endif()
+
+if(NOT DEFINED ENV{wasiclang_SOURCE_DIR})
+ message(FATAL_ERROR "Set wasiclang_SOURCE_DIR environment variable")
+endif()
+
+if(NOT DEFINED ENV{LUCET_WASI_DIR})
+ message(FATAL_ERROR "Set LUCET_WASI_DIR environment variable")
+endif()
+
+if(NOT DEFINED ENV{LUCET_DIR})
+ message(FATAL_ERROR "Set LUCET_DIR environment variable")
+endif()
+
+set(rlbox_SOURCE_DIR $ENV{rlbox_SOURCE_DIR})
+set(wasiclang_SOURCE_DIR $ENV{wasiclang_SOURCE_DIR})
+set(LUCET_WASI_DIR $ENV{LUCET_WASI_DIR})
+set(LUCET_DIR $ENV{LUCET_DIR})
+
+set(CMAKE_C_COMPILER ${wasiclang_SOURCE_DIR}/bin/clang)
+set(CMAKE_CXX_COMPILER ${wasiclang_SOURCE_DIR}/bin/clang++)
+set(CMAKE_BUILD_TYPE Release)
+
+# Apply settings suitable for wasm module compilation
+set(CMAKE_C_FLAGS
+ "--sysroot ${wasiclang_SOURCE_DIR}/share/wasi-sysroot/")
+# Link flags are set by default on Mac - clearing this
+set(CMAKE_C_LINK_FLAGS "")
+set(CMAKE_EXE_LINKER_FLAGS "-Wl,--export-all")
+
+add_executable(glue_lib_lucet.wasm
+ lucet_sandbox_wrapper.c
+ ${rlbox_SOURCE_DIR}/code/tests/rlbox_glue/lib/libtest.c)
+
+if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ set(DYLIB_EXT "dylib")
+else()
+ set(DYLIB_EXT "so")
+endif()
+set(GLUE_LIB_PATH "${CMAKE_BINARY_DIR}/glue_lib_lucet.${DYLIB_EXT}")
+
+add_custom_command(OUTPUT ${GLUE_LIB_PATH}
+ DEPENDS glue_lib_lucet.wasm
+ COMMAND ${LUCET_DIR}/lucetc
+ --bindings
+ ${LUCET_WASI_DIR}/bindings.json
+ --guard-size
+ "4GiB"
+ --min-reserved-size
+ "4GiB"
+ --max-reserved-size
+ "4GiB"
+ glue_lib_lucet.wasm
+ -o
+ ${GLUE_LIB_PATH}
+ COMMENT "Compiling wasm file to native")
+
+add_custom_target(glue_lib_so ALL DEPENDS ${GLUE_LIB_PATH})
diff --git a/third_party/rust/rlbox_lucet_sandbox/c_src/lucet_sandbox_wrapper.c b/third_party/rust/rlbox_lucet_sandbox/c_src/lucet_sandbox_wrapper.c
new file mode 100644
index 0000000000..5250748885
--- /dev/null
+++ b/third_party/rust/rlbox_lucet_sandbox/c_src/lucet_sandbox_wrapper.c
@@ -0,0 +1,138 @@
+#include <stdlib.h>
+#include <stdint.h>
+
+int main(int argc, char *argv[]) {
+ (void) argc;
+ (void) argv;
+ abort();
+}
+
+void* sandboxReservedCallbackSlot1 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot1; }
+void* sandboxReservedCallbackSlot2 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot2; }
+void* sandboxReservedCallbackSlot3 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot3; }
+void* sandboxReservedCallbackSlot4 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot4; }
+void* sandboxReservedCallbackSlot5 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot5; }
+void* sandboxReservedCallbackSlot6 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot6; }
+void* sandboxReservedCallbackSlot7 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot7; }
+void* sandboxReservedCallbackSlot8 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot8; }
+void* sandboxReservedCallbackSlot9 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot9; }
+void* sandboxReservedCallbackSlot10 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot10; }
+void* sandboxReservedCallbackSlot11 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot11; }
+void* sandboxReservedCallbackSlot12 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot12; }
+void* sandboxReservedCallbackSlot13 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot13; }
+void* sandboxReservedCallbackSlot14 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot14; }
+void* sandboxReservedCallbackSlot15 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot15; }
+void* sandboxReservedCallbackSlot16 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot16; }
+void* sandboxReservedCallbackSlot17 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot17; }
+void* sandboxReservedCallbackSlot18 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot18; }
+void* sandboxReservedCallbackSlot19 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot19; }
+void* sandboxReservedCallbackSlot20 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot20; }
+void* sandboxReservedCallbackSlot21 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot21; }
+void* sandboxReservedCallbackSlot22 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot22; }
+void* sandboxReservedCallbackSlot23 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot23; }
+void* sandboxReservedCallbackSlot24 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot24; }
+void* sandboxReservedCallbackSlot25 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot25; }
+void* sandboxReservedCallbackSlot26 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot26; }
+void* sandboxReservedCallbackSlot27 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot27; }
+void* sandboxReservedCallbackSlot28 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot28; }
+void* sandboxReservedCallbackSlot29 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot29; }
+void* sandboxReservedCallbackSlot30 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot30; }
+void* sandboxReservedCallbackSlot31 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot31; }
+void* sandboxReservedCallbackSlot32 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot32; }
+void* sandboxReservedCallbackSlot33 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot33; }
+void* sandboxReservedCallbackSlot34 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot34; }
+void* sandboxReservedCallbackSlot35 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot35; }
+void* sandboxReservedCallbackSlot36 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot36; }
+void* sandboxReservedCallbackSlot37 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot37; }
+void* sandboxReservedCallbackSlot38 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot38; }
+void* sandboxReservedCallbackSlot39 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot39; }
+void* sandboxReservedCallbackSlot40 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot40; }
+void* sandboxReservedCallbackSlot41 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot41; }
+void* sandboxReservedCallbackSlot42 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot42; }
+void* sandboxReservedCallbackSlot43 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot43; }
+void* sandboxReservedCallbackSlot44 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot44; }
+void* sandboxReservedCallbackSlot45 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot45; }
+void* sandboxReservedCallbackSlot46 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot46; }
+void* sandboxReservedCallbackSlot47 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot47; }
+void* sandboxReservedCallbackSlot48 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot48; }
+void* sandboxReservedCallbackSlot49 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot49; }
+void* sandboxReservedCallbackSlot50 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot50; }
+void* sandboxReservedCallbackSlot51 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot51; }
+void* sandboxReservedCallbackSlot52 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot52; }
+void* sandboxReservedCallbackSlot53 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot53; }
+void* sandboxReservedCallbackSlot54 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot54; }
+void* sandboxReservedCallbackSlot55 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot55; }
+void* sandboxReservedCallbackSlot56 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot56; }
+void* sandboxReservedCallbackSlot57 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot57; }
+void* sandboxReservedCallbackSlot58 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot58; }
+void* sandboxReservedCallbackSlot59 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot59; }
+void* sandboxReservedCallbackSlot60 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot60; }
+void* sandboxReservedCallbackSlot61 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot61; }
+void* sandboxReservedCallbackSlot62 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot62; }
+void* sandboxReservedCallbackSlot63 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot63; }
+void* sandboxReservedCallbackSlot64 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot64; }
+
+void* sandboxReservedCallbackSlot65 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot65; }
+void* sandboxReservedCallbackSlot66 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot66; }
+void* sandboxReservedCallbackSlot67 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot67; }
+void* sandboxReservedCallbackSlot68 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot68; }
+void* sandboxReservedCallbackSlot69 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot69; }
+void* sandboxReservedCallbackSlot70 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot70; }
+void* sandboxReservedCallbackSlot71 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot71; }
+void* sandboxReservedCallbackSlot72 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot72; }
+void* sandboxReservedCallbackSlot73 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot73; }
+void* sandboxReservedCallbackSlot74 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot74; }
+void* sandboxReservedCallbackSlot75 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot75; }
+void* sandboxReservedCallbackSlot76 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot76; }
+void* sandboxReservedCallbackSlot77 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot77; }
+void* sandboxReservedCallbackSlot78 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot78; }
+void* sandboxReservedCallbackSlot79 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot79; }
+void* sandboxReservedCallbackSlot80 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot80; }
+void* sandboxReservedCallbackSlot81 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot81; }
+void* sandboxReservedCallbackSlot82 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot82; }
+void* sandboxReservedCallbackSlot83 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot83; }
+void* sandboxReservedCallbackSlot84 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot84; }
+void* sandboxReservedCallbackSlot85 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot85; }
+void* sandboxReservedCallbackSlot86 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot86; }
+void* sandboxReservedCallbackSlot87 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot87; }
+void* sandboxReservedCallbackSlot88 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot88; }
+void* sandboxReservedCallbackSlot89 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot89; }
+void* sandboxReservedCallbackSlot90 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot90; }
+void* sandboxReservedCallbackSlot91 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot91; }
+void* sandboxReservedCallbackSlot92 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot92; }
+void* sandboxReservedCallbackSlot93 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot93; }
+void* sandboxReservedCallbackSlot94 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot94; }
+void* sandboxReservedCallbackSlot95 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot95; }
+void* sandboxReservedCallbackSlot96 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot96; }
+void* sandboxReservedCallbackSlot97 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot97; }
+void* sandboxReservedCallbackSlot98 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot98; }
+void* sandboxReservedCallbackSlot99 () { return (void*)(uintptr_t)&sandboxReservedCallbackSlot99; }
+void* sandboxReservedCallbackSlot100() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot100; }
+void* sandboxReservedCallbackSlot101() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot101; }
+void* sandboxReservedCallbackSlot102() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot102; }
+void* sandboxReservedCallbackSlot103() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot103; }
+void* sandboxReservedCallbackSlot104() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot104; }
+void* sandboxReservedCallbackSlot105() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot105; }
+void* sandboxReservedCallbackSlot106() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot106; }
+void* sandboxReservedCallbackSlot107() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot107; }
+void* sandboxReservedCallbackSlot108() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot108; }
+void* sandboxReservedCallbackSlot109() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot109; }
+void* sandboxReservedCallbackSlot110() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot110; }
+void* sandboxReservedCallbackSlot111() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot111; }
+void* sandboxReservedCallbackSlot112() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot112; }
+void* sandboxReservedCallbackSlot113() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot113; }
+void* sandboxReservedCallbackSlot114() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot114; }
+void* sandboxReservedCallbackSlot115() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot115; }
+void* sandboxReservedCallbackSlot116() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot116; }
+void* sandboxReservedCallbackSlot117() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot117; }
+void* sandboxReservedCallbackSlot118() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot118; }
+void* sandboxReservedCallbackSlot119() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot119; }
+void* sandboxReservedCallbackSlot120() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot120; }
+void* sandboxReservedCallbackSlot121() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot121; }
+void* sandboxReservedCallbackSlot122() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot122; }
+void* sandboxReservedCallbackSlot123() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot123; }
+void* sandboxReservedCallbackSlot124() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot124; }
+void* sandboxReservedCallbackSlot125() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot125; }
+void* sandboxReservedCallbackSlot126() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot126; }
+void* sandboxReservedCallbackSlot127() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot127; }
+void* sandboxReservedCallbackSlot128() { return (void*)(uintptr_t)&sandboxReservedCallbackSlot128; } \ No newline at end of file
diff --git a/third_party/rust/rlbox_lucet_sandbox/include/lucet_sandbox.h b/third_party/rust/rlbox_lucet_sandbox/include/lucet_sandbox.h
new file mode 100644
index 0000000000..822a862d0f
--- /dev/null
+++ b/third_party/rust/rlbox_lucet_sandbox/include/lucet_sandbox.h
@@ -0,0 +1,71 @@
+#ifndef LUCET_SANDBOX_H
+#define LUCET_SANDBOX_H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct LucetSandboxInstance;
+typedef struct LucetSandboxInstance LucetSandboxInstance;
+
+enum LucetValueType {
+ LucetValueType_I32,
+ LucetValueType_I64,
+ LucetValueType_F32,
+ LucetValueType_F64,
+ LucetValueType_Void
+};
+
+typedef struct {
+ enum LucetValueType val_type;
+ union {
+ uint32_t u32;
+ uint64_t u64;
+ float f32;
+ double f64;
+ };
+} LucetValue;
+
+typedef struct {
+ enum LucetValueType ret;
+ uint32_t parameter_cnt;
+ LucetValueType *parameters;
+} LucetFunctionSignature;
+
+typedef struct {
+ uint64_t ty;
+ uint64_t rf;
+} LucetFunctionTableElement;
+
+typedef struct {
+ LucetFunctionTableElement *data;
+ size_t length;
+} LucetFunctionTable;
+
+void lucet_ensure_linked();
+LucetSandboxInstance *lucet_load_module(const char *lucet_module_path,
+ bool allow_stdio);
+void lucet_drop_module(LucetSandboxInstance *inst);
+
+void* lucet_lookup_function(LucetSandboxInstance *inst,
+ const char *fn_name);
+void lucet_set_curr_instance(LucetSandboxInstance *inst);
+void lucet_clear_curr_instance(LucetSandboxInstance *inst);
+
+uintptr_t lucet_get_reserved_callback_slot_val(void *inst,
+ uint32_t slot_number);
+LucetFunctionTable lucet_get_function_pointer_table(void *inst);
+int32_t lucet_get_function_type_index(void *inst, LucetFunctionSignature csig);
+
+void *lucet_get_heap_base(LucetSandboxInstance *inst);
+size_t lucet_get_heap_size(LucetSandboxInstance *inst);
+uint32_t lucet_get_export_function_id(void *inst, void *unsandboxed_ptr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif \ No newline at end of file
diff --git a/third_party/rust/rlbox_lucet_sandbox/include/rlbox_lucet_sandbox.hpp b/third_party/rust/rlbox_lucet_sandbox/include/rlbox_lucet_sandbox.hpp
new file mode 100644
index 0000000000..43d6e3715e
--- /dev/null
+++ b/third_party/rust/rlbox_lucet_sandbox/include/rlbox_lucet_sandbox.hpp
@@ -0,0 +1,881 @@
+#pragma once
+
+#include "lucet_sandbox.h"
+
+#include <cstdint>
+#include <iostream>
+#include <limits>
+#include <map>
+#include <memory>
+#include <mutex>
+// RLBox allows applications to provide a custom shared lock implementation
+#ifndef RLBOX_USE_CUSTOM_SHARED_LOCK
+# include <shared_mutex>
+#endif
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#define RLBOX_LUCET_UNUSED(...) (void)__VA_ARGS__
+
+// Use the same convention as rlbox to allow applications to customize the
+// shared lock
+#ifndef RLBOX_USE_CUSTOM_SHARED_LOCK
+# define RLBOX_SHARED_LOCK(name) std::shared_timed_mutex name
+# define RLBOX_ACQUIRE_SHARED_GUARD(name, ...) \
+ std::shared_lock<std::shared_timed_mutex> name(__VA_ARGS__)
+# define RLBOX_ACQUIRE_UNIQUE_GUARD(name, ...) \
+ std::unique_lock<std::shared_timed_mutex> name(__VA_ARGS__)
+#else
+# if !defined(RLBOX_SHARED_LOCK) || !defined(RLBOX_ACQUIRE_SHARED_GUARD) || \
+ !defined(RLBOX_ACQUIRE_UNIQUE_GUARD)
+# error \
+ "RLBOX_USE_CUSTOM_SHARED_LOCK defined but missing definitions for RLBOX_SHARED_LOCK, RLBOX_ACQUIRE_SHARED_GUARD, RLBOX_ACQUIRE_UNIQUE_GUARD"
+# endif
+#endif
+
+namespace rlbox {
+
+namespace detail {
+ // relying on the dynamic check settings (exception vs abort) in the rlbox lib
+ inline void dynamic_check(bool check, const char* const msg);
+}
+
+namespace lucet_detail {
+
+ template<typename T>
+ constexpr bool false_v = false;
+
+ // https://stackoverflow.com/questions/6512019/can-we-get-the-type-of-a-lambda-argument
+ namespace return_argument_detail {
+ template<typename Ret, typename... Rest>
+ Ret helper(Ret (*)(Rest...));
+
+ template<typename Ret, typename F, typename... Rest>
+ Ret helper(Ret (F::*)(Rest...));
+
+ template<typename Ret, typename F, typename... Rest>
+ Ret helper(Ret (F::*)(Rest...) const);
+
+ template<typename F>
+ decltype(helper(&F::operator())) helper(F);
+ } // namespace return_argument_detail
+
+ template<typename T>
+ using return_argument =
+ decltype(return_argument_detail::helper(std::declval<T>()));
+
+ ///////////////////////////////////////////////////////////////
+
+ // https://stackoverflow.com/questions/37602057/why-isnt-a-for-loop-a-compile-time-expression
+ namespace compile_time_for_detail {
+ template<std::size_t N>
+ struct num
+ {
+ static const constexpr auto value = N;
+ };
+
+ template<class F, std::size_t... Is>
+ inline void compile_time_for_helper(F func, std::index_sequence<Is...>)
+ {
+ (func(num<Is>{}), ...);
+ }
+ } // namespace compile_time_for_detail
+
+ template<std::size_t N, typename F>
+ inline void compile_time_for(F func)
+ {
+ compile_time_for_detail::compile_time_for_helper(
+ func, std::make_index_sequence<N>());
+ }
+
+ ///////////////////////////////////////////////////////////////
+
+ template<typename T, typename = void>
+ struct convert_type_to_wasm_type
+ {
+ static_assert(std::is_void_v<T>, "Missing specialization");
+ using type = void;
+ static constexpr enum LucetValueType lucet_type = LucetValueType_Void;
+ };
+
+ template<typename T>
+ struct convert_type_to_wasm_type<
+ T,
+ std::enable_if_t<(std::is_integral_v<T> || std::is_enum_v<T>)&&sizeof(T) <=
+ sizeof(uint32_t)>>
+ {
+ using type = uint32_t;
+ static constexpr enum LucetValueType lucet_type = LucetValueType_I32;
+ };
+
+ template<typename T>
+ struct convert_type_to_wasm_type<
+ T,
+ std::enable_if_t<(std::is_integral_v<T> ||
+ std::is_enum_v<T>)&&sizeof(uint32_t) < sizeof(T) &&
+ sizeof(T) <= sizeof(uint64_t)>>
+ {
+ using type = uint64_t;
+ static constexpr enum LucetValueType lucet_type = LucetValueType_I64;
+ };
+
+ template<typename T>
+ struct convert_type_to_wasm_type<T,
+ std::enable_if_t<std::is_same_v<T, float>>>
+ {
+ using type = T;
+ static constexpr enum LucetValueType lucet_type = LucetValueType_F32;
+ };
+
+ template<typename T>
+ struct convert_type_to_wasm_type<T,
+ std::enable_if_t<std::is_same_v<T, double>>>
+ {
+ using type = T;
+ static constexpr enum LucetValueType lucet_type = LucetValueType_F64;
+ };
+
+ template<typename T>
+ struct convert_type_to_wasm_type<
+ T,
+ std::enable_if_t<std::is_pointer_v<T> || std::is_class_v<T>>>
+ {
+ // pointers are 32 bit indexes in wasm
+ // class paramters are passed as a pointer to an object in the stack or heap
+ using type = uint32_t;
+ static constexpr enum LucetValueType lucet_type = LucetValueType_I32;
+ };
+
+ ///////////////////////////////////////////////////////////////
+
+ namespace prepend_arg_type_detail {
+ template<typename T, typename T_ArgNew>
+ struct helper;
+
+ template<typename T_ArgNew, typename T_Ret, typename... T_Args>
+ struct helper<T_Ret(T_Args...), T_ArgNew>
+ {
+ using type = T_Ret(T_ArgNew, T_Args...);
+ };
+ }
+
+ template<typename T_Func, typename T_ArgNew>
+ using prepend_arg_type =
+ typename prepend_arg_type_detail::helper<T_Func, T_ArgNew>::type;
+
+ ///////////////////////////////////////////////////////////////
+
+ namespace change_return_type_detail {
+ template<typename T, typename T_RetNew>
+ struct helper;
+
+ template<typename T_RetNew, typename T_Ret, typename... T_Args>
+ struct helper<T_Ret(T_Args...), T_RetNew>
+ {
+ using type = T_RetNew(T_Args...);
+ };
+ }
+
+ template<typename T_Func, typename T_RetNew>
+ using change_return_type =
+ typename change_return_type_detail::helper<T_Func, T_RetNew>::type;
+
+ ///////////////////////////////////////////////////////////////
+
+ namespace change_class_arg_types_detail {
+ template<typename T, typename T_ArgNew>
+ struct helper;
+
+ template<typename T_ArgNew, typename T_Ret, typename... T_Args>
+ struct helper<T_Ret(T_Args...), T_ArgNew>
+ {
+ using type =
+ T_Ret(std::conditional_t<std::is_class_v<T_Args>, T_ArgNew, T_Args>...);
+ };
+ }
+
+ template<typename T_Func, typename T_ArgNew>
+ using change_class_arg_types =
+ typename change_class_arg_types_detail::helper<T_Func, T_ArgNew>::type;
+
+} // namespace lucet_detail
+
+class rlbox_lucet_sandbox;
+
+struct rlbox_lucet_sandbox_thread_data
+{
+ rlbox_lucet_sandbox* sandbox;
+ uint32_t last_callback_invoked;
+};
+
+#ifdef RLBOX_EMBEDDER_PROVIDES_TLS_STATIC_VARIABLES
+
+rlbox_lucet_sandbox_thread_data* get_rlbox_lucet_sandbox_thread_data();
+# define RLBOX_LUCET_SANDBOX_STATIC_VARIABLES() \
+ thread_local rlbox::rlbox_lucet_sandbox_thread_data \
+ rlbox_lucet_sandbox_thread_info{ 0, 0 }; \
+ namespace rlbox { \
+ rlbox_lucet_sandbox_thread_data* get_rlbox_lucet_sandbox_thread_data() \
+ { \
+ return &rlbox_lucet_sandbox_thread_info; \
+ } \
+ } \
+ static_assert(true, "Enforce semi-colon")
+
+#endif
+
+class rlbox_lucet_sandbox
+{
+public:
+ using T_LongLongType = int32_t;
+ using T_LongType = int32_t;
+ using T_IntType = int32_t;
+ using T_PointerType = uint32_t;
+ using T_ShortType = int16_t;
+
+private:
+ LucetSandboxInstance* sandbox = nullptr;
+ uintptr_t heap_base;
+ void* malloc_index = 0;
+ void* free_index = 0;
+ size_t return_slot_size = 0;
+ T_PointerType return_slot = 0;
+
+ static const size_t MAX_CALLBACKS = 128;
+ RLBOX_SHARED_LOCK(callback_mutex);
+ void* callback_unique_keys[MAX_CALLBACKS]{ 0 };
+ void* callbacks[MAX_CALLBACKS]{ 0 };
+ uint32_t callback_slot_assignment[MAX_CALLBACKS]{ 0 };
+
+ using TableElementRef = LucetFunctionTableElement*;
+ struct FunctionTable
+ {
+ TableElementRef elements[MAX_CALLBACKS];
+ uint32_t slot_number[MAX_CALLBACKS];
+ };
+ inline static std::mutex callback_table_mutex;
+ // We need to share the callback slot info across multiple sandbox instances
+ // that may load the same sandboxed library. Thus if the sandboxed library is
+ // already in the memory space, we should just use the previously saved info
+ // as the load is destroys the callback info. Once all instances of the
+ // library is unloaded, the sandboxed library is removed from the address
+ // space and thus we can "reset" our state. The semantics of shared and weak
+ // pointers ensure this and will automatically release the memory after all
+ // instances are released.
+ inline static std::map<void*, std::weak_ptr<FunctionTable>>
+ shared_callback_slots;
+ std::shared_ptr<FunctionTable> callback_slots = nullptr;
+ // However, if the library is also loaded externally in the application, then
+ // we don't know when we can ever "reset". In such scenarios, we are better of
+ // never throwing away the callback info, rather than figuring out
+ // what/why/when the application is loading or unloading the sandboxed
+ // library. An extra reference to the shared_ptr will ensure this.
+ inline static std::vector<std::shared_ptr<FunctionTable>>
+ saved_callback_slot_info;
+
+#ifndef RLBOX_EMBEDDER_PROVIDES_TLS_STATIC_VARIABLES
+ thread_local static inline rlbox_lucet_sandbox_thread_data thread_data{ 0,
+ 0 };
+#endif
+
+ template<typename T_FormalRet, typename T_ActualRet>
+ inline auto serialize_to_sandbox(T_ActualRet arg)
+ {
+ if constexpr (std::is_class_v<T_FormalRet>) {
+ // structs returned as pointers into wasm memory/wasm stack
+ auto ptr = reinterpret_cast<T_FormalRet*>(
+ impl_get_unsandboxed_pointer<T_FormalRet*>(arg));
+ T_FormalRet ret = *ptr;
+ return ret;
+ } else {
+ return arg;
+ }
+ }
+
+ inline std::shared_ptr<FunctionTable> get_callback_ref_data(
+ LucetFunctionTable& functionPointerTable)
+ {
+ auto callback_slots = std::make_shared<FunctionTable>();
+
+ for (size_t i = 0; i < MAX_CALLBACKS; i++) {
+ uintptr_t reservedVal =
+ lucet_get_reserved_callback_slot_val(sandbox, i + 1);
+
+ bool found = false;
+ for (size_t j = 0; j < functionPointerTable.length; j++) {
+ if (functionPointerTable.data[j].rf == reservedVal) {
+ functionPointerTable.data[j].rf = 0;
+ callback_slots->elements[i] = &(functionPointerTable.data[j]);
+ callback_slots->slot_number[i] = static_cast<uint32_t>(j);
+ found = true;
+ break;
+ }
+ }
+
+ detail::dynamic_check(found, "Unable to intialize callback tables");
+ }
+
+ return callback_slots;
+ }
+
+ inline void reinit_callback_ref_data(
+ LucetFunctionTable& functionPointerTable,
+ std::shared_ptr<FunctionTable>& callback_slots)
+ {
+ for (size_t i = 0; i < MAX_CALLBACKS; i++) {
+ uintptr_t reservedVal =
+ lucet_get_reserved_callback_slot_val(sandbox, i + 1);
+
+ for (size_t j = 0; j < functionPointerTable.length; j++) {
+ if (functionPointerTable.data[j].rf == reservedVal) {
+ functionPointerTable.data[j].rf = 0;
+
+ detail::dynamic_check(
+ callback_slots->elements[i] == &(functionPointerTable.data[j]) &&
+ callback_slots->slot_number[i] == static_cast<uint32_t>(j),
+ "Sandbox creation error: Error when checking the values of "
+ "callback slot data");
+
+ break;
+ }
+ }
+ }
+ }
+
+ inline void set_callbacks_slots_ref(bool external_loads_exist)
+ {
+ LucetFunctionTable functionPointerTable =
+ lucet_get_function_pointer_table(sandbox);
+ void* key = functionPointerTable.data;
+
+ std::lock_guard<std::mutex> lock(callback_table_mutex);
+ std::weak_ptr<FunctionTable> slots = shared_callback_slots[key];
+
+ if (auto shared_slots = slots.lock()) {
+ // pointer exists
+ callback_slots = shared_slots;
+ // Sometimes, dlopen and process forking seem to act a little weird.
+ // Writes to the writable page of the dynamic lib section seem to not
+ // always be propagated (possibly when the dynamic library is opened
+ // externally - "external_loads_exist")). This occurred in when RLBox was
+ // used in ASAN builds of Firefox. In general, we take the precaution of
+ // rechecking this on each sandbox creation.
+ reinit_callback_ref_data(functionPointerTable, callback_slots);
+ return;
+ }
+
+ callback_slots = get_callback_ref_data(functionPointerTable);
+ shared_callback_slots[key] = callback_slots;
+ if (external_loads_exist) {
+ saved_callback_slot_info.push_back(callback_slots);
+ }
+ }
+
+ template<uint32_t N, typename T_Ret, typename... T_Args>
+ static typename lucet_detail::convert_type_to_wasm_type<T_Ret>::type
+ callback_interceptor(
+ void* /* vmContext */,
+ typename lucet_detail::convert_type_to_wasm_type<T_Args>::type... params)
+ {
+#ifdef RLBOX_EMBEDDER_PROVIDES_TLS_STATIC_VARIABLES
+ auto& thread_data = *get_rlbox_lucet_sandbox_thread_data();
+#endif
+ thread_data.last_callback_invoked = N;
+ using T_Func = T_Ret (*)(T_Args...);
+ T_Func func;
+ {
+ RLBOX_ACQUIRE_SHARED_GUARD(lock, thread_data.sandbox->callback_mutex);
+ func = reinterpret_cast<T_Func>(thread_data.sandbox->callbacks[N]);
+ }
+ // Callbacks are invoked through function pointers, cannot use std::forward
+ // as we don't have caller context for T_Args, which means they are all
+ // effectively passed by value
+ return func(thread_data.sandbox->serialize_to_sandbox<T_Args>(params)...);
+ }
+
+ template<uint32_t N, typename T_Ret, typename... T_Args>
+ static void callback_interceptor_promoted(
+ void* /* vmContext */,
+ typename lucet_detail::convert_type_to_wasm_type<T_Ret>::type ret,
+ typename lucet_detail::convert_type_to_wasm_type<T_Args>::type... params)
+ {
+#ifdef RLBOX_EMBEDDER_PROVIDES_TLS_STATIC_VARIABLES
+ auto& thread_data = *get_rlbox_lucet_sandbox_thread_data();
+#endif
+ thread_data.last_callback_invoked = N;
+ using T_Func = T_Ret (*)(T_Args...);
+ T_Func func;
+ {
+ RLBOX_ACQUIRE_SHARED_GUARD(lock, thread_data.sandbox->callback_mutex);
+ func = reinterpret_cast<T_Func>(thread_data.sandbox->callbacks[N]);
+ }
+ // Callbacks are invoked through function pointers, cannot use std::forward
+ // as we don't have caller context for T_Args, which means they are all
+ // effectively passed by value
+ auto ret_val =
+ func(thread_data.sandbox->serialize_to_sandbox<T_Args>(params)...);
+ // Copy the return value back
+ auto ret_ptr = reinterpret_cast<T_Ret*>(
+ thread_data.sandbox->template impl_get_unsandboxed_pointer<T_Ret*>(ret));
+ *ret_ptr = ret_val;
+ }
+
+ template<typename T_Ret, typename... T_Args>
+ inline T_PointerType get_lucet_type_index(
+ T_Ret (*/* dummy for template inference */)(T_Args...) = nullptr) const
+ {
+ // Class return types as promoted to args
+ constexpr bool promoted = std::is_class_v<T_Ret>;
+ int32_t type_index;
+
+ if constexpr (promoted) {
+ LucetValueType ret_type = LucetValueType::LucetValueType_Void;
+ LucetValueType param_types[] = {
+ lucet_detail::convert_type_to_wasm_type<T_Ret>::lucet_type,
+ lucet_detail::convert_type_to_wasm_type<T_Args>::lucet_type...
+ };
+ LucetFunctionSignature signature{ ret_type,
+ sizeof(param_types) /
+ sizeof(LucetValueType),
+ &(param_types[0]) };
+ type_index = lucet_get_function_type_index(sandbox, signature);
+ } else {
+ LucetValueType ret_type =
+ lucet_detail::convert_type_to_wasm_type<T_Ret>::lucet_type;
+ LucetValueType param_types[] = {
+ lucet_detail::convert_type_to_wasm_type<T_Args>::lucet_type...
+ };
+ LucetFunctionSignature signature{ ret_type,
+ sizeof(param_types) /
+ sizeof(LucetValueType),
+ &(param_types[0]) };
+ type_index = lucet_get_function_type_index(sandbox, signature);
+ }
+
+ return type_index;
+ }
+
+ void ensure_return_slot_size(size_t size)
+ {
+ if (size > return_slot_size) {
+ if (return_slot_size) {
+ impl_free_in_sandbox(return_slot);
+ }
+ return_slot = impl_malloc_in_sandbox(size);
+ detail::dynamic_check(
+ return_slot != 0,
+ "Error initializing return slot. Sandbox may be out of memory!");
+ return_slot_size = size;
+ }
+ }
+
+protected:
+ // Set external_loads_exist to true, if the host application loads the
+ // library lucet_module_path outside of rlbox_lucet_sandbox such as via dlopen
+ // or the Windows equivalent
+ inline void impl_create_sandbox(const char* lucet_module_path,
+ bool external_loads_exist,
+ bool allow_stdio)
+ {
+ detail::dynamic_check(sandbox == nullptr, "Sandbox already initialized");
+ sandbox = lucet_load_module(lucet_module_path, allow_stdio);
+ detail::dynamic_check(sandbox != nullptr, "Sandbox could not be created");
+
+ heap_base = reinterpret_cast<uintptr_t>(impl_get_memory_location());
+ // Check that the address space is larger than the sandbox heap i.e. 4GB
+ // sandbox heap, host has to have more than 4GB
+ static_assert(sizeof(uintptr_t) > sizeof(T_PointerType));
+ // Check that the heap is aligned to the pointer size i.e. 32-bit pointer =>
+ // aligned to 4GB. The implementations of
+ // impl_get_unsandboxed_pointer_no_ctx and impl_get_sandboxed_pointer_no_ctx
+ // below rely on this.
+ uintptr_t heap_offset_mask = std::numeric_limits<T_PointerType>::max();
+ detail::dynamic_check((heap_base & heap_offset_mask) == 0,
+ "Sandbox heap not aligned to 4GB");
+
+ // cache these for performance
+ malloc_index = impl_lookup_symbol("malloc");
+ free_index = impl_lookup_symbol("free");
+
+ set_callbacks_slots_ref(external_loads_exist);
+ }
+
+ inline void impl_create_sandbox(const char* lucet_module_path)
+ {
+ // Default is to assume that no external code will load the wasm library as
+ // this is usually the case
+ const bool external_loads_exist = false;
+ const bool allow_stdio = true;
+ impl_create_sandbox(lucet_module_path, external_loads_exist, allow_stdio);
+ }
+
+ inline void impl_destroy_sandbox() {
+ if (return_slot_size) {
+ impl_free_in_sandbox(return_slot);
+ }
+ lucet_drop_module(sandbox);
+ }
+
+ template<typename T>
+ inline void* impl_get_unsandboxed_pointer(T_PointerType p) const
+ {
+ if constexpr (std::is_function_v<std::remove_pointer_t<T>>) {
+ LucetFunctionTable functionPointerTable =
+ lucet_get_function_pointer_table(sandbox);
+ if (p >= functionPointerTable.length) {
+ // Received out of range function pointer
+ return nullptr;
+ }
+ auto ret = functionPointerTable.data[p].rf;
+ return reinterpret_cast<void*>(static_cast<uintptr_t>(ret));
+ } else {
+ return reinterpret_cast<void*>(heap_base + p);
+ }
+ }
+
+ template<typename T>
+ inline T_PointerType impl_get_sandboxed_pointer(const void* p) const
+ {
+ if constexpr (std::is_function_v<std::remove_pointer_t<T>>) {
+ // p is a pointer to a function internal to the lucet module
+ // we need to either
+ // 1) find the indirect function slot this is registered and return the
+ // slot number. For this we need to scan the full indirect function table,
+ // not just the portion we have reserved for callbacks.
+ // 2) in the scenario this function has not ever been listed as an
+ // indirect function, we need to register this like a normal callback.
+ // However, unlike callbacks, we will not require the user to unregister
+ // this. Instead, this permenantly takes up a callback slot.
+ LucetFunctionTable functionPointerTable =
+ lucet_get_function_pointer_table(sandbox);
+ std::lock_guard<std::mutex> lock(callback_table_mutex);
+
+ // Scenario 1 described above
+ ssize_t empty_slot = -1;
+ for (size_t i = 0; i < functionPointerTable.length; i++) {
+ if (functionPointerTable.data[i].rf == reinterpret_cast<uintptr_t>(p)) {
+ return static_cast<T_PointerType>(i);
+ } else if (functionPointerTable.data[i].rf == 0 && empty_slot == -1) {
+ // found an empty slot. Save it, as we may use it later.
+ empty_slot = i;
+ }
+ }
+
+ // Scenario 2 described above
+ detail::dynamic_check(
+ empty_slot != -1,
+ "Could not find an empty slot in sandbox function table. This would "
+ "happen if you have registered too many callbacks, or unsandboxed "
+ "too many function pointers. You can file a bug if you want to "
+ "increase the maximum allowed callbacks or unsadnboxed functions "
+ "pointers");
+ T dummy = nullptr;
+ int32_t type_index = get_lucet_type_index(dummy);
+ functionPointerTable.data[empty_slot].ty = type_index;
+ functionPointerTable.data[empty_slot].rf = reinterpret_cast<uintptr_t>(p);
+ return empty_slot;
+
+ } else {
+ return static_cast<T_PointerType>(reinterpret_cast<uintptr_t>(p));
+ }
+ }
+
+ template<typename T>
+ static inline void* impl_get_unsandboxed_pointer_no_ctx(
+ T_PointerType p,
+ const void* example_unsandboxed_ptr,
+ rlbox_lucet_sandbox* (*expensive_sandbox_finder)(
+ const void* example_unsandboxed_ptr))
+ {
+ if constexpr (std::is_function_v<std::remove_pointer_t<T>>) {
+ // swizzling function pointers needs access to the function pointer tables
+ // and thus cannot be done without context
+ auto sandbox = expensive_sandbox_finder(example_unsandboxed_ptr);
+ return sandbox->impl_get_unsandboxed_pointer<T>(p);
+ } else {
+ // grab the memory base from the example_unsandboxed_ptr
+ uintptr_t heap_base_mask =
+ std::numeric_limits<uintptr_t>::max() &
+ ~(static_cast<uintptr_t>(std::numeric_limits<T_PointerType>::max()));
+ uintptr_t computed_heap_base =
+ reinterpret_cast<uintptr_t>(example_unsandboxed_ptr) & heap_base_mask;
+ uintptr_t ret = computed_heap_base | p;
+ return reinterpret_cast<void*>(ret);
+ }
+ }
+
+ template<typename T>
+ static inline T_PointerType impl_get_sandboxed_pointer_no_ctx(
+ const void* p,
+ const void* example_unsandboxed_ptr,
+ rlbox_lucet_sandbox* (*expensive_sandbox_finder)(
+ const void* example_unsandboxed_ptr))
+ {
+ if constexpr (std::is_function_v<std::remove_pointer_t<T>>) {
+ // swizzling function pointers needs access to the function pointer tables
+ // and thus cannot be done without context
+ auto sandbox = expensive_sandbox_finder(example_unsandboxed_ptr);
+ return sandbox->impl_get_sandboxed_pointer<T>(p);
+ } else {
+ // Just clear the memory base to leave the offset
+ RLBOX_LUCET_UNUSED(example_unsandboxed_ptr);
+ uintptr_t ret = reinterpret_cast<uintptr_t>(p) &
+ std::numeric_limits<T_PointerType>::max();
+ return static_cast<T_PointerType>(ret);
+ }
+ }
+
+ static inline bool impl_is_in_same_sandbox(const void* p1, const void* p2)
+ {
+ uintptr_t heap_base_mask = std::numeric_limits<uintptr_t>::max() &
+ ~(std::numeric_limits<T_PointerType>::max());
+ return (reinterpret_cast<uintptr_t>(p1) & heap_base_mask) ==
+ (reinterpret_cast<uintptr_t>(p2) & heap_base_mask);
+ }
+
+ inline bool impl_is_pointer_in_sandbox_memory(const void* p)
+ {
+ size_t length = impl_get_total_memory();
+ uintptr_t p_val = reinterpret_cast<uintptr_t>(p);
+ return p_val >= heap_base && p_val < (heap_base + length);
+ }
+
+ inline bool impl_is_pointer_in_app_memory(const void* p)
+ {
+ return !(impl_is_pointer_in_sandbox_memory(p));
+ }
+
+ inline size_t impl_get_total_memory() { return lucet_get_heap_size(sandbox); }
+
+ inline void* impl_get_memory_location()
+ {
+ return lucet_get_heap_base(sandbox);
+ }
+
+ void* impl_lookup_symbol(const char* func_name)
+ {
+ return lucet_lookup_function(sandbox, func_name);
+ }
+
+ template<typename T, typename T_Converted, typename... T_Args>
+ auto impl_invoke_with_func_ptr(T_Converted* func_ptr, T_Args&&... params)
+ {
+#ifdef RLBOX_EMBEDDER_PROVIDES_TLS_STATIC_VARIABLES
+ auto& thread_data = *get_rlbox_lucet_sandbox_thread_data();
+#endif
+ thread_data.sandbox = this;
+ lucet_set_curr_instance(sandbox);
+
+ // WASM functions are mangled in the following manner
+ // 1. All primitive types are left as is and follow an LP32 machine model
+ // (as opposed to the possibly 64-bit application)
+ // 2. All pointers are changed to u32 types
+ // 3. Returned class are returned as an out parameter before the actual
+ // function parameters
+ // 4. All class parameters are passed as pointers (u32 types)
+ // 5. The heap address is passed in as the first argument to the function
+ //
+ // RLBox accounts for the first 2 differences in T_Converted type, but we
+ // need to handle the rest
+
+ // Handle point 3
+ using T_Ret = lucet_detail::return_argument<T_Converted>;
+ if constexpr (std::is_class_v<T_Ret>) {
+ using T_Conv1 = lucet_detail::change_return_type<T_Converted, void>;
+ using T_Conv2 = lucet_detail::prepend_arg_type<T_Conv1, T_PointerType>;
+ auto func_ptr_conv =
+ reinterpret_cast<T_Conv2*>(reinterpret_cast<uintptr_t>(func_ptr));
+ ensure_return_slot_size(sizeof(T_Ret));
+ impl_invoke_with_func_ptr<T>(func_ptr_conv, return_slot, params...);
+
+ auto ptr = reinterpret_cast<T_Ret*>(
+ impl_get_unsandboxed_pointer<T_Ret*>(return_slot));
+ T_Ret ret = *ptr;
+ return ret;
+ }
+
+ // Handle point 4
+ constexpr size_t alloc_length = [&] {
+ if constexpr (sizeof...(params) > 0) {
+ return ((std::is_class_v<T_Args> ? 1 : 0) + ...);
+ } else {
+ return 0;
+ }
+ }();
+
+ // 0 arg functions create 0 length arrays which is not allowed
+ T_PointerType allocations_buff[alloc_length == 0 ? 1 : alloc_length];
+ T_PointerType* allocations = allocations_buff;
+
+ auto serialize_class_arg =
+ [&](auto arg) -> std::conditional_t<std::is_class_v<decltype(arg)>,
+ T_PointerType,
+ decltype(arg)> {
+ using T_Arg = decltype(arg);
+ if constexpr (std::is_class_v<T_Arg>) {
+ auto slot = impl_malloc_in_sandbox(sizeof(T_Arg));
+ auto ptr =
+ reinterpret_cast<T_Arg*>(impl_get_unsandboxed_pointer<T_Arg*>(slot));
+ *ptr = arg;
+ allocations[0] = slot;
+ allocations++;
+ return slot;
+ } else {
+ return arg;
+ }
+ };
+
+ // 0 arg functions don't use serialize
+ RLBOX_LUCET_UNUSED(serialize_class_arg);
+
+ using T_ConvNoClass =
+ lucet_detail::change_class_arg_types<T_Converted, T_PointerType>;
+
+ // Handle Point 5
+ using T_ConvHeap = lucet_detail::prepend_arg_type<T_ConvNoClass, uint64_t>;
+
+ // Function invocation
+ auto func_ptr_conv =
+ reinterpret_cast<T_ConvHeap*>(reinterpret_cast<uintptr_t>(func_ptr));
+
+ using T_NoVoidRet =
+ std::conditional_t<std::is_void_v<T_Ret>, uint32_t, T_Ret>;
+ T_NoVoidRet ret;
+
+ if constexpr (std::is_void_v<T_Ret>) {
+ RLBOX_LUCET_UNUSED(ret);
+ func_ptr_conv(heap_base, serialize_class_arg(params)...);
+ } else {
+ ret = func_ptr_conv(heap_base, serialize_class_arg(params)...);
+ }
+
+ for (size_t i = 0; i < alloc_length; i++) {
+ impl_free_in_sandbox(allocations_buff[i]);
+ }
+
+ if constexpr (!std::is_void_v<T_Ret>) {
+ return ret;
+ }
+ }
+
+ inline T_PointerType impl_malloc_in_sandbox(size_t size)
+ {
+ detail::dynamic_check(size <= std::numeric_limits<uint32_t>::max(),
+ "Attempting to malloc more than the heap size");
+ using T_Func = void*(size_t);
+ using T_Converted = T_PointerType(uint32_t);
+ T_PointerType ret = impl_invoke_with_func_ptr<T_Func, T_Converted>(
+ reinterpret_cast<T_Converted*>(malloc_index),
+ static_cast<uint32_t>(size));
+ return ret;
+ }
+
+ inline void impl_free_in_sandbox(T_PointerType p)
+ {
+ using T_Func = void(void*);
+ using T_Converted = void(T_PointerType);
+ impl_invoke_with_func_ptr<T_Func, T_Converted>(
+ reinterpret_cast<T_Converted*>(free_index), p);
+ }
+
+ template<typename T_Ret, typename... T_Args>
+ inline T_PointerType impl_register_callback(void* key, void* callback)
+ {
+ int32_t type_index = get_lucet_type_index<T_Ret, T_Args...>();
+
+ detail::dynamic_check(
+ type_index != -1,
+ "Could not find lucet type for callback signature. This can "
+ "happen if you tried to register a callback whose signature "
+ "does not correspond to any callbacks used in the library.");
+
+ bool found = false;
+ uint32_t found_loc = 0;
+ uint32_t slot_number = 0;
+
+ {
+ std::lock_guard<std::mutex> lock(callback_table_mutex);
+
+ // need a compile time for loop as we we need I to be a compile time value
+ // this is because we are setting the I'th callback ineterceptor
+ lucet_detail::compile_time_for<MAX_CALLBACKS>([&](auto I) {
+ constexpr auto i = I.value;
+ if (!found && callback_slots->elements[i]->rf == 0) {
+ found = true;
+ found_loc = i;
+ slot_number = callback_slots->slot_number[i];
+
+ void* chosen_interceptor;
+ if constexpr (std::is_class_v<T_Ret>) {
+ chosen_interceptor = reinterpret_cast<void*>(
+ callback_interceptor_promoted<i, T_Ret, T_Args...>);
+ } else {
+ chosen_interceptor = reinterpret_cast<void*>(
+ callback_interceptor<i, T_Ret, T_Args...>);
+ }
+ callback_slots->elements[i]->ty = type_index;
+ callback_slots->elements[i]->rf =
+ reinterpret_cast<uintptr_t>(chosen_interceptor);
+ }
+ });
+ }
+
+ detail::dynamic_check(
+ found,
+ "Could not find an empty slot in sandbox function table. This would "
+ "happen if you have registered too many callbacks, or unsandboxed "
+ "too many function pointers. You can file a bug if you want to "
+ "increase the maximum allowed callbacks or unsadnboxed functions "
+ "pointers");
+
+ {
+ RLBOX_ACQUIRE_UNIQUE_GUARD(lock, callback_mutex);
+ callback_unique_keys[found_loc] = key;
+ callbacks[found_loc] = callback;
+ callback_slot_assignment[found_loc] = slot_number;
+ }
+
+ return static_cast<T_PointerType>(slot_number);
+ }
+
+ static inline std::pair<rlbox_lucet_sandbox*, void*>
+ impl_get_executed_callback_sandbox_and_key()
+ {
+#ifdef RLBOX_EMBEDDER_PROVIDES_TLS_STATIC_VARIABLES
+ auto& thread_data = *get_rlbox_lucet_sandbox_thread_data();
+#endif
+ auto sandbox = thread_data.sandbox;
+ auto callback_num = thread_data.last_callback_invoked;
+ void* key = sandbox->callback_unique_keys[callback_num];
+ return std::make_pair(sandbox, key);
+ }
+
+ template<typename T_Ret, typename... T_Args>
+ inline void impl_unregister_callback(void* key)
+ {
+ bool found = false;
+ uint32_t i = 0;
+ {
+ RLBOX_ACQUIRE_UNIQUE_GUARD(lock, callback_mutex);
+ for (; i < MAX_CALLBACKS; i++) {
+ if (callback_unique_keys[i] == key) {
+ callback_unique_keys[i] = nullptr;
+ callbacks[i] = nullptr;
+ callback_slot_assignment[i] = 0;
+ found = true;
+ break;
+ }
+ }
+ }
+
+ detail::dynamic_check(
+ found, "Internal error: Could not find callback to unregister");
+
+ std::lock_guard<std::mutex> shared_lock(callback_table_mutex);
+ callback_slots->elements[i]->rf = 0;
+ return;
+ }
+};
+
+} // namespace rlbox \ No newline at end of file
diff --git a/third_party/rust/rlbox_lucet_sandbox/src/callback.rs b/third_party/rust/rlbox_lucet_sandbox/src/callback.rs
new file mode 100644
index 0000000000..b9f42aab47
--- /dev/null
+++ b/third_party/rust/rlbox_lucet_sandbox/src/callback.rs
@@ -0,0 +1,51 @@
+use crate::types::{LucetFunctionSignature, LucetSandboxInstance, SizedBuffer};
+
+use lucet_module::Signature;
+use lucet_runtime_internals::instance::InstanceInternal;
+
+use std::convert::TryFrom;
+use std::ffi::c_void;
+
+#[no_mangle]
+pub extern "C" fn lucet_get_reserved_callback_slot_val(
+ inst_ptr: *mut c_void,
+ slot_number: u32,
+) -> usize {
+ let inst = unsafe { &mut *(inst_ptr as *mut LucetSandboxInstance) };
+
+ let name = format!("sandboxReservedCallbackSlot{}", slot_number);
+ let func = inst
+ .instance_handle
+ .module()
+ .get_export_func(&name)
+ .unwrap();
+ return func.ptr.as_usize();
+}
+
+#[no_mangle]
+pub extern "C" fn lucet_get_function_pointer_table(inst_ptr: *mut c_void) -> SizedBuffer {
+ let inst = unsafe { &mut *(inst_ptr as *mut LucetSandboxInstance) };
+
+ let elems = inst.instance_handle.module().table_elements().unwrap();
+
+ SizedBuffer {
+ data: elems.as_ptr() as *mut c_void,
+ length: elems.len(),
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn lucet_get_function_type_index(
+ inst_ptr: *mut c_void,
+ csig: LucetFunctionSignature,
+) -> i32 {
+ let inst = unsafe { &mut *(inst_ptr as *mut LucetSandboxInstance) };
+
+ let conv_sig: Signature = csig.into();
+ let index = inst.signatures.iter().position(|r| *r == conv_sig);
+
+ match index {
+ Some(x) => i32::try_from(x).unwrap_or(-1),
+ _ => -1,
+ }
+}
diff --git a/third_party/rust/rlbox_lucet_sandbox/src/create.rs b/third_party/rust/rlbox_lucet_sandbox/src/create.rs
new file mode 100644
index 0000000000..e7701003e8
--- /dev/null
+++ b/third_party/rust/rlbox_lucet_sandbox/src/create.rs
@@ -0,0 +1,94 @@
+use crate::types::{Error, LucetSandboxInstance};
+
+use lucet_runtime::{DlModule, Limits, MmapRegion, Module, Region};
+use lucet_runtime_internals::{module::ModuleInternal};
+
+use lucet_wasi::WasiCtxBuilder;
+
+use std::ffi::{c_void, CStr};
+use std::os::raw::c_char;
+use std::ptr;
+use std::sync::Arc;
+
+#[no_mangle]
+pub extern "C" fn lucet_ensure_linked() {
+ lucet_runtime::lucet_internal_ensure_linked();
+ lucet_wasi::hostcalls::ensure_linked();
+}
+
+#[no_mangle]
+pub extern "C" fn lucet_load_module(lucet_module_path: *const c_char, allow_stdio: bool) -> *mut c_void {
+ let module_path;
+ unsafe {
+ module_path = CStr::from_ptr(lucet_module_path)
+ .to_string_lossy()
+ .into_owned();
+ }
+
+ let result = lucet_load_module_helper(&module_path, allow_stdio);
+
+ let r = match result {
+ Ok(inst) => Box::into_raw(Box::new(inst)) as *mut c_void,
+ Err(e) => {
+ println!("Error {:?}!", e);
+ ptr::null_mut()
+ }
+ };
+
+ return r;
+}
+
+#[no_mangle]
+pub extern "C" fn lucet_drop_module(inst_ptr: *mut c_void) {
+ // Need to invoke the destructor
+ let _inst = unsafe {
+ Box::from_raw(inst_ptr as *mut LucetSandboxInstance)
+ };
+
+}
+
+fn lucet_load_module_helper(module_path: &String, allow_stdio: bool) -> Result<LucetSandboxInstance, Error> {
+ let module = DlModule::load(module_path)?;
+
+ //Replicating calculations used in lucet examples
+ let min_globals_size = module.globals().len() * std::mem::size_of::<u64>();
+ // Nearest 4k
+ let globals_size = ((min_globals_size + 4096 - 1) / 4096) * 4096;
+
+ let region = MmapRegion::create_aligned(
+ 1,
+ &Limits {
+ heap_memory_size: 4 * 1024 * 1024 * 1024, // 4GB
+ heap_address_space_size: 8 * 1024 * 1024 * 1024, // 8GB
+ stack_size: 8 * 1024 * 1024, // 8MB - pthread default
+ globals_size: globals_size,
+ ..Limits::default()
+ },
+ 4 * 1024 * 1024 * 1024, // 4GB heap alignment
+ )?;
+
+ let sig = module.get_signatures().to_vec();
+
+ // put the path to the module on the front for argv[0]
+ let mut builder = WasiCtxBuilder::new()
+ .args(&[&module_path]);
+
+ if allow_stdio {
+ builder = builder.inherit_stdio_no_syscall();
+ }
+
+ let ctx = builder.build()?;
+
+ let instance_handle = region
+ .new_instance_builder(module as Arc<dyn Module>)
+ .with_embed_ctx(ctx)
+ .build()?;
+
+ let opaque_instance = LucetSandboxInstance {
+ region: region,
+ instance_handle: instance_handle,
+ signatures: sig,
+ };
+
+ return Ok(opaque_instance);
+}
diff --git a/third_party/rust/rlbox_lucet_sandbox/src/invoke.rs b/third_party/rust/rlbox_lucet_sandbox/src/invoke.rs
new file mode 100644
index 0000000000..a335aa4ea1
--- /dev/null
+++ b/third_party/rust/rlbox_lucet_sandbox/src/invoke.rs
@@ -0,0 +1,29 @@
+use crate::types::LucetSandboxInstance;
+
+use lucet_runtime_internals::instance::InstanceInternal;
+
+use std::ffi::{c_void, CStr};
+use std::os::raw::c_char;
+
+#[no_mangle]
+pub extern "C" fn lucet_lookup_function(
+ inst_ptr: *mut c_void,
+ fn_name: *const c_char,
+) -> *mut c_void {
+ let inst = unsafe { &mut *(inst_ptr as *mut LucetSandboxInstance) };
+ let name = unsafe { CStr::from_ptr(fn_name).to_string_lossy() };
+ let func = inst
+ .instance_handle
+ .module()
+ .get_export_func(&name)
+ .unwrap();
+ let ret = func.ptr.as_usize();
+ return ret as *mut c_void;
+}
+
+#[no_mangle]
+pub extern "C" fn lucet_set_curr_instance(inst_ptr: *mut c_void)
+{
+ let inst = unsafe { &mut *(inst_ptr as *mut LucetSandboxInstance) };
+ inst.instance_handle.set_current_instance();
+}
diff --git a/third_party/rust/rlbox_lucet_sandbox/src/lib.rs b/third_party/rust/rlbox_lucet_sandbox/src/lib.rs
new file mode 100644
index 0000000000..52d30d4c72
--- /dev/null
+++ b/third_party/rust/rlbox_lucet_sandbox/src/lib.rs
@@ -0,0 +1,5 @@
+pub mod callback;
+pub mod create;
+pub mod invoke;
+pub mod memory;
+mod types;
diff --git a/third_party/rust/rlbox_lucet_sandbox/src/memory.rs b/third_party/rust/rlbox_lucet_sandbox/src/memory.rs
new file mode 100644
index 0000000000..53b99c6527
--- /dev/null
+++ b/third_party/rust/rlbox_lucet_sandbox/src/memory.rs
@@ -0,0 +1,35 @@
+use crate::types::LucetSandboxInstance;
+
+use lucet_module::FunctionPointer;
+use lucet_runtime_internals::instance::InstanceInternal;
+
+use std::ffi::c_void;
+
+#[no_mangle]
+pub extern "C" fn lucet_get_heap_base(inst_ptr: *mut c_void) -> *mut c_void {
+ let inst = unsafe { &mut *(inst_ptr as *mut LucetSandboxInstance) };
+ let heap_view = inst.instance_handle.heap_mut();
+ let heap_base = heap_view.as_mut_ptr() as *mut c_void;
+ return heap_base;
+}
+
+#[no_mangle]
+pub extern "C" fn lucet_get_heap_size(inst_ptr: *mut c_void) -> usize {
+ let inst = unsafe { &mut *(inst_ptr as *mut LucetSandboxInstance) };
+ let heap_view = inst.instance_handle.heap_mut();
+ return heap_view.len();
+}
+
+#[no_mangle]
+pub extern "C" fn lucet_get_export_function_id(
+ inst_ptr: *mut c_void,
+ unsandboxed_ptr: *mut c_void,
+) -> u32 {
+ let inst = unsafe { &mut *(inst_ptr as *mut LucetSandboxInstance) };
+ let func = FunctionPointer::from_usize(unsandboxed_ptr as usize);
+ let func_handle = inst
+ .instance_handle
+ .module()
+ .function_handle_from_ptr(func);
+ return func_handle.id.as_u32();
+} \ No newline at end of file
diff --git a/third_party/rust/rlbox_lucet_sandbox/src/types.rs b/third_party/rust/rlbox_lucet_sandbox/src/types.rs
new file mode 100644
index 0000000000..908b433950
--- /dev/null
+++ b/third_party/rust/rlbox_lucet_sandbox/src/types.rs
@@ -0,0 +1,160 @@
+use lucet_module::{Signature, ValueType};
+use lucet_runtime::{InstanceHandle, MmapRegion};
+use lucet_runtime_internals::val::Val;
+
+use std::convert::TryFrom;
+use std::ffi::c_void;
+use std::sync::Arc;
+
+pub struct LucetSandboxInstance {
+ pub region: Arc<MmapRegion>,
+ pub instance_handle: InstanceHandle,
+ pub signatures: Vec<Signature>,
+}
+
+#[derive(Debug)]
+pub enum Error {
+ GoblinError(goblin::error::Error),
+ WasiError(failure::Error),
+ LucetRuntimeError(lucet_runtime_internals::error::Error),
+ LucetModuleError(lucet_module::Error),
+}
+
+impl From<goblin::error::Error> for Error {
+ fn from(e: goblin::error::Error) -> Self {
+ Error::GoblinError(e)
+ }
+}
+
+impl From<failure::Error> for Error {
+ fn from(e: failure::Error) -> Self {
+ Error::WasiError(e)
+ }
+}
+
+impl From<lucet_runtime_internals::error::Error> for Error {
+ fn from(e: lucet_runtime_internals::error::Error) -> Self {
+ Error::LucetRuntimeError(e)
+ }
+}
+
+impl From<lucet_module::Error> for Error {
+ fn from(e: lucet_module::Error) -> Self {
+ Error::LucetModuleError(e)
+ }
+}
+
+#[repr(C)]
+#[derive(Clone, Copy, Debug)]
+pub enum LucetValueType {
+ I32,
+ I64,
+ F32,
+ F64,
+ Void,
+}
+
+impl From<Option<ValueType>> for LucetValueType {
+ fn from(value_type: Option<ValueType>) -> Self {
+ match value_type {
+ Some(value_type_val) => match value_type_val {
+ ValueType::I32 => LucetValueType::I32,
+ ValueType::I64 => LucetValueType::I64,
+ ValueType::F32 => LucetValueType::F32,
+ ValueType::F64 => LucetValueType::F64,
+ },
+ _ => LucetValueType::Void,
+ }
+ }
+}
+
+impl From<ValueType> for LucetValueType {
+ fn from(value_type: ValueType) -> Self {
+ match value_type {
+ ValueType::I32 => LucetValueType::I32,
+ ValueType::I64 => LucetValueType::I64,
+ ValueType::F32 => LucetValueType::F32,
+ ValueType::F64 => LucetValueType::F64,
+ }
+ }
+}
+
+impl Into<Option<ValueType>> for LucetValueType {
+ fn into(self) -> Option<ValueType> {
+ match self {
+ LucetValueType::I32 => Some(ValueType::I32),
+ LucetValueType::I64 => Some(ValueType::I64),
+ LucetValueType::F32 => Some(ValueType::F32),
+ LucetValueType::F64 => Some(ValueType::F64),
+ _ => None,
+ }
+ }
+}
+
+impl Into<ValueType> for LucetValueType {
+ fn into(self) -> ValueType {
+ match self {
+ LucetValueType::I32 => ValueType::I32,
+ LucetValueType::I64 => ValueType::I64,
+ LucetValueType::F32 => ValueType::F32,
+ LucetValueType::F64 => ValueType::F64,
+ _ => panic!("Unexpected!"),
+ }
+ }
+}
+
+#[repr(C)]
+#[derive(Clone, Copy)]
+pub union LucetValueUnion {
+ as_u32: u32,
+ as_u64: u64,
+ as_f32: f32,
+ as_f64: f64,
+}
+
+#[repr(C)]
+#[derive(Clone, Copy)]
+pub struct LucetValue {
+ val_type: LucetValueType,
+ val : LucetValueUnion,
+}
+
+impl From<&LucetValue> for Val {
+ fn from(val: &LucetValue) -> Val {
+ match val.val_type {
+ LucetValueType::I32 => Val::U32(unsafe { val.val.as_u32 }),
+ LucetValueType::I64 => Val::U64(unsafe { val.val.as_u64 }),
+ LucetValueType::F32 => Val::F32(unsafe { val.val.as_f32 }),
+ LucetValueType::F64 => Val::F64(unsafe { val.val.as_f64 }),
+ _ => panic!("Unexpected!"),
+ }
+ }
+}
+
+#[repr(C)]
+#[derive(Clone, Copy, Debug)]
+pub struct LucetFunctionSignature {
+ ret: LucetValueType,
+ parameter_cnt: u32,
+ parameters: *mut LucetValueType,
+}
+
+impl Into<Signature> for LucetFunctionSignature {
+ fn into(self) -> Signature {
+ let len = usize::try_from(self.parameter_cnt).unwrap();
+ let vec = unsafe { Vec::from_raw_parts(self.parameters, len, len) };
+ let p: Vec<ValueType> = vec.iter().map(|x| x.clone().into()).collect();
+ std::mem::forget(vec);
+ Signature {
+ params: p,
+ ret_ty: self.ret.into(),
+ }
+ }
+}
+
+#[repr(C)]
+#[derive(Clone, Copy, Debug)]
+pub struct SizedBuffer {
+ pub data: *mut c_void,
+ pub length: usize,
+}
diff --git a/third_party/rust/rlbox_lucet_sandbox/test/test_lucet_sandbox_glue.cpp b/third_party/rust/rlbox_lucet_sandbox/test/test_lucet_sandbox_glue.cpp
new file mode 100644
index 0000000000..2d49067216
--- /dev/null
+++ b/third_party/rust/rlbox_lucet_sandbox/test/test_lucet_sandbox_glue.cpp
@@ -0,0 +1,17 @@
+#define RLBOX_USE_EXCEPTIONS
+#define RLBOX_ENABLE_DEBUG_ASSERTIONS
+#define RLBOX_SINGLE_THREADED_INVOCATIONS
+#include "rlbox_lucet_sandbox.hpp"
+
+// NOLINTNEXTLINE
+#define TestName "rlbox_lucet_sandbox"
+// NOLINTNEXTLINE
+#define TestType rlbox::rlbox_lucet_sandbox
+
+#ifndef GLUE_LIB_LUCET_PATH
+# error "Missing definition for GLUE_LIB_LUCET_PATH"
+#endif
+
+// NOLINTNEXTLINE
+#define CreateSandbox(sandbox) sandbox.create_sandbox(GLUE_LIB_LUCET_PATH)
+#include "test_sandbox_glue.inc.cpp"
diff --git a/third_party/rust/rlbox_lucet_sandbox/test/test_lucet_sandbox_glue_embedder_vars.cpp b/third_party/rust/rlbox_lucet_sandbox/test/test_lucet_sandbox_glue_embedder_vars.cpp
new file mode 100644
index 0000000000..5b6fc79d3b
--- /dev/null
+++ b/third_party/rust/rlbox_lucet_sandbox/test/test_lucet_sandbox_glue_embedder_vars.cpp
@@ -0,0 +1,19 @@
+#define RLBOX_USE_EXCEPTIONS
+#define RLBOX_ENABLE_DEBUG_ASSERTIONS
+#define RLBOX_SINGLE_THREADED_INVOCATIONS
+#define RLBOX_EMBEDDER_PROVIDES_TLS_STATIC_VARIABLES
+#include "rlbox_lucet_sandbox.hpp"
+RLBOX_LUCET_SANDBOX_STATIC_VARIABLES();
+
+// NOLINTNEXTLINE
+#define TestName "rlbox_lucet_sandbox embedder"
+// NOLINTNEXTLINE
+#define TestType rlbox::rlbox_lucet_sandbox
+
+#ifndef GLUE_LIB_LUCET_PATH
+# error "Missing definition for GLUE_LIB_LUCET_PATH"
+#endif
+
+// NOLINTNEXTLINE
+#define CreateSandbox(sandbox) sandbox.create_sandbox(GLUE_LIB_LUCET_PATH)
+#include "test_sandbox_glue.inc.cpp"
diff --git a/third_party/rust/rlbox_lucet_sandbox/test/test_lucet_sandbox_glue_main.cpp b/third_party/rust/rlbox_lucet_sandbox/test/test_lucet_sandbox_glue_main.cpp
new file mode 100644
index 0000000000..62bf7476a1
--- /dev/null
+++ b/third_party/rust/rlbox_lucet_sandbox/test/test_lucet_sandbox_glue_main.cpp
@@ -0,0 +1,2 @@
+#define CATCH_CONFIG_MAIN
+#include "catch2/catch.hpp"
diff --git a/third_party/rust/rlbox_lucet_sandbox/test/test_lucet_sandbox_glue_preload.cpp b/third_party/rust/rlbox_lucet_sandbox/test/test_lucet_sandbox_glue_preload.cpp
new file mode 100644
index 0000000000..de957c8dce
--- /dev/null
+++ b/third_party/rust/rlbox_lucet_sandbox/test/test_lucet_sandbox_glue_preload.cpp
@@ -0,0 +1,27 @@
+#define RLBOX_USE_EXCEPTIONS
+#define RLBOX_ENABLE_DEBUG_ASSERTIONS
+#define RLBOX_SINGLE_THREADED_INVOCATIONS
+#include "rlbox_lucet_sandbox.hpp"
+
+// NOLINTNEXTLINE
+#define TestName "rlbox_lucet_sandbox preload"
+// NOLINTNEXTLINE
+#define TestType rlbox::rlbox_lucet_sandbox
+
+#ifndef GLUE_LIB_LUCET_PATH
+# error "Missing definition for GLUE_LIB_LUCET_PATH"
+#endif
+
+// Test simulating the application preloading the sandboxed library
+// Applications such as Firefox sometimes preload dynamic libraries to ensure it
+// plays well with the content (filepaths) sandbox
+
+#include <dlfcn.h>
+
+#undef CreateSandbox
+// NOLINTNEXTLINE
+#define CreateSandbox(sandbox) \
+ dlopen(GLUE_LIB_LUCET_PATH, RTLD_LAZY); \
+ (sandbox).create_sandbox( \
+ GLUE_LIB_LUCET_PATH, true /* external loads */, false /* allow_stdio */)
+#include "test_sandbox_glue.inc.cpp"