You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@teaclave.apache.org by ms...@apache.org on 2021/06/15 22:46:04 UTC
[incubator-teaclave] branch master updated: Add WebAssembly
Executor (#504)
This is an automated email from the ASF dual-hosted git repository.
mssun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-teaclave.git
The following commit(s) were added to refs/heads/master by this push:
new 90e7231 Add WebAssembly Executor (#504)
90e7231 is described below
commit 90e7231d8eed601b84d91633c58f9b2452157c95
Author: Hongbo <12...@users.noreply.github.com>
AuthorDate: Tue Jun 15 18:45:56 2021 -0400
Add WebAssembly Executor (#504)
- MVP implementation
- Simple add exmaple
---
.github/workflows/ci.yml | 8 +-
.gitmodules | 3 +
CMakeLists.txt | 28 +
LICENSE | 1 +
cmake/TeaclaveGenVars.cmake | 3 +
cmake/TeaclaveUtils.cmake | 12 +-
cmake/scripts/sgx_link_sign.sh | 2 +-
cmake/scripts/test.sh | 1 +
docs/adding-custom-executor.md | 46 ++
examples/python/wasm_simple_add.py | 100 ++++
.../python/wasm_simple_add_payload/simple_add.c | 65 ++
.../python/wasm_simple_add_payload/simple_add.wasm | Bin 0 -> 1594 bytes
executor/src/lib.rs | 3 +
executor/src/wamr.rs | 202 +++++++
LICENSE => licenses/LICENSE-wasm-micro-runtime.txt | 35 +-
rpc/src/protocol.rs | 2 +-
sdk/rust/src/bindings.rs | 156 +++--
sdk/rust/src/lib.rs | 1 +
services/proto/proto_gen/main.rs | 2 -
third_party/wamr.patch | 651 +++++++++++++++++++++
third_party/wasm-micro-runtime | 1 +
types/src/worker.rs | 6 +
worker/src/worker.rs | 6 +-
23 files changed, 1236 insertions(+), 98 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6be2c85..ef1363f 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -29,8 +29,6 @@ jobs:
container: teaclave/teaclave-build-ubuntu-1804-sgx-2.9.1:0.1.2
steps:
- uses: actions/checkout@v2
- with:
- submodules: 'true'
- name: Setting up $HOME
run: |
cp /root/.bashrc $HOME/.bashrc &&
@@ -45,6 +43,7 @@ jobs:
cmake -DCMAKE_BUILD_TYPE=Debug -DSGX_SIM_MODE=ON -DTEST_MODE=ON ..
- name: Building
run: |
+ . /opt/sgxsdk/environment &&
. ~/.cargo/env &&
cd build &&
make VERBOSE=1
@@ -63,8 +62,6 @@ jobs:
container: teaclave/teaclave-build-ubuntu-1804-sgx-2.9.1:0.1.2
steps:
- uses: actions/checkout@v2
- with:
- submodules: 'true'
- name: Setting up $HOME
run: |
cp /root/.bashrc $HOME/.bashrc &&
@@ -86,8 +83,6 @@ jobs:
container: teaclave/teaclave-build-ubuntu-1804-sgx-2.9.1:0.1.2
steps:
- uses: actions/checkout@v2
- with:
- submodules: 'true'
- name: Setting up $HOME
run: |
cp /root/.bashrc $HOME/.bashrc &&
@@ -102,5 +97,6 @@ jobs:
cmake -DRUSTFLAGS="-D warnings" -DTEST_MODE=ON ..
- name: Code linting with Clippy
run: |
+ . /opt/sgxsdk/environment &&
. /root/.cargo/env &&
cd build && make CLP=1
diff --git a/.gitmodules b/.gitmodules
index d913305..489b426 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -13,3 +13,6 @@
path = third_party/crates-io
url = https://github.com/mesalock-linux/crates-io.git
ignore = dirty
+[submodule "third_party/wasm-micro-runtime"]
+ path = third_party/wasm-micro-runtime
+ url = https://github.com/bytecodealliance/wasm-micro-runtime
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8b8ec62..b3ddba1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -151,6 +151,13 @@ set(MESAPY_OUTPUTS
${TEACLAVE_OUT_DIR}/libsgx_ulibc.a
${TEACLAVE_OUT_DIR}/ffi.o
)
+
+# WAMR library
+
+set(WAMR_OUTPUTS
+ ${TEACLAVE_OUT_DIR}/libvmlib.a
+)
+
if(USE_PREBUILT_MESAPY)
add_custom_command(
OUTPUT ${MESAPY_OUTPUTS}
@@ -172,10 +179,30 @@ else()
${TEACLAVE_OUT_DIR}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/third_party/mesapy)
endif()
+
+ExternalProject_Add(wamr_teaclave
+ SOURCE_DIR ${WAMR_TEACLAVE_ROOT_DIR}
+ BINARY_DIR ${WAMR_TEACLAVE_ROOT_DIR}/build
+ INSTALL_COMMAND ""
+ LOG_BUILD 1
+)
+
+add_custom_command(
+ OUTPUT ${WAMR_OUTPUTS}
+ DEPENDS wamr_teaclave
+ COMMAND
+ cp ${WAMR_TEACLAVE_ROOT_DIR}/build/libvmlib.a ${TEACLAVE_OUT_DIR}
+ WORKING_DIRECTORY ${WAMR_TEACLAVE_ROOT_DIR}/build
+ )
+
add_custom_target(mesapy
DEPENDS ${MESAPY_OUTPUTS}
)
+add_custom_target(wamr
+ DEPENDS $(WAMR_TEACLAVE_ROOT_DIR)/CMakeLists.txt ${WAMR_OUTPUTS}
+ )
+
# mesapy components
add_custom_command(
OUTPUT ${TEACLAVE_OUT_DIR}/acs_py_enclave.c
@@ -213,6 +240,7 @@ foreach(_i RANGE ${SGX_LIB_LAST_INDEX})
DEPENDS
prep
mesapy
+ wamr
pycomponent
INSTALL_DIR
${TEACLAVE_INSTALL_DIR}/${_category}
diff --git a/LICENSE b/LICENSE
index 310ee62..74412ab 100644
--- a/LICENSE
+++ b/LICENSE
@@ -213,6 +213,7 @@ Apache License, Version 2.0
third-party/crates-io
third-party/crates-sgx
+third_party/wasm-micro-runtime
BSD 3-Clause License
diff --git a/cmake/TeaclaveGenVars.cmake b/cmake/TeaclaveGenVars.cmake
index 8a00491..107e61e 100644
--- a/cmake/TeaclaveGenVars.cmake
+++ b/cmake/TeaclaveGenVars.cmake
@@ -42,6 +42,9 @@ set(THIRD_PARTY_DIR ${PROJECT_SOURCE_DIR}/third_party)
set(UNTRUSTED_TARGET_DIR ${TEACLAVE_TARGET_DIR}/untrusted)
set(UNIX_TARGET_DIR ${TEACLAVE_TARGET_DIR}/unix)
set(TRUSTED_TARGET_DIR ${TEACLAVE_TARGET_DIR}/trusted)
+set(WAMR_TEACLAVE_ROOT_DIR
+ ${PROJECT_SOURCE_DIR}/third_party/wasm-micro-runtime/product-mini/platforms/teaclave-sgx
+)
# build.rs will read ENV{ENCLAVE_OUT_DIR} for linking
set(ENCLAVE_OUT_DIR ${TEACLAVE_OUT_DIR})
set(RUST_SGX_SDK ${PROJECT_SOURCE_DIR}/third_party/rust-sgx-sdk)
diff --git a/cmake/TeaclaveUtils.cmake b/cmake/TeaclaveUtils.cmake
index 8271dd8..83cee77 100644
--- a/cmake/TeaclaveUtils.cmake
+++ b/cmake/TeaclaveUtils.cmake
@@ -57,13 +57,23 @@ function(init_submodules)
"git submodule update --init failed with ${GIT_SUBMOD_RESULT}, please checkout submodules"
)
endif()
+ # Patch WAMR after pulling
+ if(NOT EXISTS "${PROJECT_SOURCE_DIR}/third_party/wasm-micro-runtime/product-mini/platforms/teaclave/CMakeLists.txt")
+ execute_process(
+ COMMAND
+ patch -N -p1
+ INPUT_FILE "../wamr.patch"
+ WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/third_party/wasm-micro-runtime
+ )
+ endif()
endif()
endif()
if(NOT EXISTS "${PROJECT_SOURCE_DIR}/third_party/crates-io"
OR NOT EXISTS "${PROJECT_SOURCE_DIR}/third_party/crates-sgx"
OR NOT EXISTS "${PROJECT_SOURCE_DIR}/third_party/mesapy"
- OR NOT EXISTS "${PROJECT_SOURCE_DIR}/third_party/rust-sgx-sdk")
+ OR NOT EXISTS "${PROJECT_SOURCE_DIR}/third_party/rust-sgx-sdk"
+ OR NOT EXISTS "${PROJECT_SOURCE_DIR}/third_party/wasm-micro-runtime")
message(
FATAL_ERROR
"The submodules were not downloaded! GIT_SUBMODULE was turned off or failed. Please update submodules and try again."
diff --git a/cmake/scripts/sgx_link_sign.sh b/cmake/scripts/sgx_link_sign.sh
index ca82c9e..670e7b6 100755
--- a/cmake/scripts/sgx_link_sign.sh
+++ b/cmake/scripts/sgx_link_sign.sh
@@ -52,7 +52,7 @@ ${CMAKE_C_COMPILER} "lib${edl_lib_name}.o" -o \
-Wl,--no-whole-archive -Wl,--start-group \
-l${Service_Library_Name} -lsgx_tprotected_fs -lsgx_tkey_exchange \
-lsgx_tstdc -lsgx_tcxx -lsgx_tservice -lsgx_tcrypto \
- -L${TEACLAVE_OUT_DIR} -lpycomponent ffi.o -lpypy-c -lsgx_tlibc_ext -lffi \
+ -L${TEACLAVE_OUT_DIR} -lpycomponent ffi.o -lpypy-c -lsgx_tlibc_ext -lffi -lvmlib\
-L${TRUSTED_TARGET_DIR}/${TARGET} -l${CUR_PKG_NAME} -Wl,--end-group \
-Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \
-Wl,-pie,-eenclave_entry -Wl,--export-dynamic \
diff --git a/cmake/scripts/test.sh b/cmake/scripts/test.sh
index feb93b7..1fe6282 100755
--- a/cmake/scripts/test.sh
+++ b/cmake/scripts/test.sh
@@ -230,6 +230,7 @@ run_examples() {
python3 builtin_rsa_sign.py
python3 builtin_face_detection.py
python3 builtin_password_check.py
+ python3 wasm_simple_add.py
popd
pushd ${TEACLAVE_PROJECT_ROOT}/examples/c
diff --git a/docs/adding-custom-executor.md b/docs/adding-custom-executor.md
new file mode 100644
index 0000000..da53abc
--- /dev/null
+++ b/docs/adding-custom-executor.md
@@ -0,0 +1,46 @@
+---
+permalink: /docs/adding-custom-executor
+---
+
+# Source Code of the Executor
+
+The source code of the new executor should be at `executor/src/`.
+
+1. Create a public executor unit struct.
+2. Implement `TeaclaveExecutor` trait and `execute` function for the new struct.
+3. Re-export your new executor in `executor/src/lib.rs` to make it callable.
+4. Optionally, add unit test code to test your executor, and add a line calling your test in `executor/src/lib.rs`.
+
+## Extern Function
+
+Usually the new executor for other language or bytecode cannot be supported by this single rust source file,
+and the embedded execution environment is ported from another project, which can be written in another
+language. Therefore some extern functions should be imported to the rust source code and a **static** library
+is needed in linking.
+
+You may add this library in the linking command located at `cmake/scripts/sgx_link_sign.sh`, and such library
+should be in `${TEACLAVE_OUT_DIR}`, which will be parsed to `build/intermediate` in build phase.
+
+# Add the Interface
+
+You also need to add some auxillary code for teaclave and tell it when and how to invoked the new executor.
+
+## `types/src/worker.rs`
+
+1. Add a new enum value in `ExecutorType`;
+2. Add a match case in `ExecutorType::try_from` to get the `ExecutorType` from a string;
+3. Add a match case in `ExecutorType::fmt` for printing;
+4. Besides, add a enum in `Executor`;
+5. Add match cases in `Executor::try_from` and `Executor::fmt` just like what you've done in step 3 and 4.
+
+## `worker/src/worker.rs`
+
+1. Import the executor in `use teaclave_executor::{...}`
+2. Register the new executor in `Worker::Default`
+
+# Invoke the New Executor
+
+Just call the API and remember to set `executor_type` to your new executor type's name (the string used in
+`ExecutorType::try_from` match case) when calling `register_function`, and set the `executor` to the executor's
+name correspondingly.
+
diff --git a/examples/python/wasm_simple_add.py b/examples/python/wasm_simple_add.py
new file mode 100644
index 0000000..7663616
--- /dev/null
+++ b/examples/python/wasm_simple_add.py
@@ -0,0 +1,100 @@
+#!/usr/bin/env python3
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import sys
+
+from teaclave import (AuthenticationService, FrontendService,
+ AuthenticationClient, FrontendClient)
+from utils import (AUTHENTICATION_SERVICE_ADDRESS, FRONTEND_SERVICE_ADDRESS,
+ AS_ROOT_CA_CERT_PATH, ENCLAVE_INFO_PATH, USER_ID,
+ USER_PASSWORD)
+
+
+class WASMAddExample:
+ def __init__(self, user_id, user_password):
+ self.user_id = user_id
+ self.user_password = user_password
+
+ def add(self,
+ payload_file="wasm_simple_add_payload/simple_add.wasm",
+ adder1="3",
+ adder2="4"):
+ client = AuthenticationService(
+ AUTHENTICATION_SERVICE_ADDRESS, AS_ROOT_CA_CERT_PATH,
+ ENCLAVE_INFO_PATH).connect().get_client()
+
+ print("[+] registering user")
+ client.user_register(self.user_id, self.user_password)
+
+ print("[+] login")
+ token = client.user_login(self.user_id, self.user_password)
+
+ client = FrontendService(FRONTEND_SERVICE_ADDRESS,
+ AS_ROOT_CA_CERT_PATH,
+ ENCLAVE_INFO_PATH).connect().get_client()
+ metadata = {"id": self.user_id, "token": token}
+ client.metadata = metadata
+
+ print("[+] registering function")
+
+ with open(payload_file, "rb") as f:
+ payload = f.read()
+
+ function_id = client.register_function(name="entrypoint",
+ description="test of wasm",
+ executor_type="wamr",
+ payload=list(payload),
+ arguments=["adder1", "adder2"])
+
+ print("[+] creating task")
+ task_id = client.create_task(function_id=function_id,
+ function_arguments={
+ "adder1": adder1,
+ "adder2": adder2
+ },
+ executor="wamr")
+
+ print("[+] invoking task")
+ client.invoke_task(task_id)
+
+ print("[+] getting result")
+ result = client.get_task_result(task_id)
+ print("[+] done")
+
+ return bytes(result)
+
+
+def main():
+ example = WASMAddExample(USER_ID, USER_PASSWORD)
+ if len(sys.argv) == 2:
+ adder1 = sys.argv[1]
+ rt = example.add(adder1=adder1)
+ elif len(sys.argv) == 3:
+ adder1 = sys.argv[1]
+ adder2 = sys.argv[2]
+
+ rt = example.add(adder1=adder1, adder2=adder2)
+ else:
+ rt = example.add()
+
+ print("[+] function return: ", rt)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/examples/python/wasm_simple_add_payload/simple_add.c b/examples/python/wasm_simple_add_payload/simple_add.c
new file mode 100644
index 0000000..ddb39dc
--- /dev/null
+++ b/examples/python/wasm_simple_add_payload/simple_add.c
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+
+int
+atoi(const char *str)
+{
+ int result = 0;
+ int sign = 0;
+ // proc whitespace characters
+ while (*str == ' ' || *str == '\t' || *str == '\n')
+ ++str;
+
+ // proc sign character
+ if (*str == '-') {
+ sign = 1;
+ ++str;
+ }
+ else if (*str == '+') {
+ ++str;
+ }
+
+ // proc numbers
+ while (*str >= '0' && *str <= '9') {
+ result = result * 10 + *str - '0';
+ ++str;
+ }
+
+ // return result
+ if (sign == 1)
+ return -result;
+ else
+ return result;
+}
+
+int
+entrypoint(int argc, char *argv[])
+{
+ if (argc < 4) {
+ return -1;
+ }
+
+ if ((argv[0] == 0) || argv[2] == 0) {
+ return -1;
+ }
+
+ return atoi(argv[1]) + atoi(argv[3]);
+}
diff --git a/examples/python/wasm_simple_add_payload/simple_add.wasm b/examples/python/wasm_simple_add_payload/simple_add.wasm
new file mode 100755
index 0000000..dacab0b
Binary files /dev/null and b/examples/python/wasm_simple_add_payload/simple_add.wasm differ
diff --git a/executor/src/lib.rs b/executor/src/lib.rs
index e9e6cb0..31e566e 100644
--- a/executor/src/lib.rs
+++ b/executor/src/lib.rs
@@ -28,9 +28,11 @@ extern crate log;
mod builtin;
mod context;
mod mesapy;
+mod wamr;
pub use builtin::BuiltinFunctionExecutor;
pub use mesapy::MesaPy;
+pub use wamr::WAMicroRuntime;
#[cfg(feature = "enclave_unit_test")]
pub mod tests {
@@ -42,6 +44,7 @@ pub mod tests {
context::tests::run_tests(),
mesapy::tests::run_tests(),
builtin::tests::run_tests(),
+ wamr::tests::run_tests(),
)
}
}
diff --git a/executor/src/wamr.rs b/executor/src/wamr.rs
new file mode 100644
index 0000000..b37bb3f
--- /dev/null
+++ b/executor/src/wamr.rs
@@ -0,0 +1,202 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use std::prelude::v1::*;
+
+use crate::context::reset_thread_context;
+use crate::context::set_thread_context;
+use crate::context::Context;
+
+use std::ffi::{c_void, CString};
+
+use teaclave_types::{FunctionArguments, FunctionRuntime, TeaclaveExecutor};
+
+const DEFAULT_HEAP_SIZE: u32 = 8092;
+const DEFAULT_STACK_SIZE: u32 = 8092;
+const DEFAULT_ERROR_BUF_SIZE: usize = 128;
+
+extern "C" {
+
+ fn wasm_runtime_init() -> bool;
+
+ fn wasm_runtime_load(
+ buf: *const u8,
+ size: u32,
+ error_buf: *mut u8,
+ error_buf_size: u32,
+ ) -> *const c_void;
+
+ fn wasm_runtime_instantiate(
+ module: *const c_void,
+ stack_size: u32,
+ heap_size: u32,
+ error_buf: *mut u8,
+ error_buf_size: u32,
+ ) -> *const c_void;
+
+ fn wasm_runtime_lookup_function(
+ module_inst: *const c_void,
+ name: *const i8,
+ signature: *const u8,
+ ) -> *const c_void;
+
+ fn wasm_runtime_create_exec_env(module_inst: *const c_void, stack_size: u32) -> *const c_void;
+
+ fn wasm_runtime_call_wasm(
+ exec_env: *const c_void,
+ function: *const c_void,
+ argc: u32,
+ argv: *const u32,
+ ) -> bool;
+
+ fn wasm_runtime_module_dup_data(module_inst: *const c_void, src: *const u8, size: u32) -> u32;
+
+ fn wasm_runtime_module_free(module_inst: *const c_void, ptr: u32);
+}
+
+#[derive(Default)]
+pub struct WAMicroRuntime;
+
+impl TeaclaveExecutor for WAMicroRuntime {
+ fn execute(
+ &self,
+ _name: String,
+ arguments: FunctionArguments,
+ payload: Vec<u8>,
+ runtime: FunctionRuntime,
+ ) -> anyhow::Result<String> {
+ let wa_argv: Vec<_> = arguments.into_vec();
+
+ let mut error_buf = [0u8; DEFAULT_ERROR_BUF_SIZE];
+ let entry_name = CString::new("entrypoint").expect("CString::new failed");
+
+ set_thread_context(Context::new(runtime))?;
+
+ unsafe { wasm_runtime_init() };
+ let module = unsafe {
+ wasm_runtime_load(
+ payload.as_ptr(),
+ payload.len() as u32,
+ error_buf.as_mut_ptr(),
+ error_buf.len() as u32,
+ )
+ };
+
+ assert!((module as usize) != 0);
+
+ error_buf = [0u8; DEFAULT_ERROR_BUF_SIZE];
+ let module_instance = unsafe {
+ wasm_runtime_instantiate(
+ module,
+ DEFAULT_STACK_SIZE,
+ DEFAULT_HEAP_SIZE,
+ error_buf.as_mut_ptr(),
+ error_buf.len() as u32,
+ )
+ };
+ assert!((module_instance as usize) != 0);
+
+ let entry_func = unsafe {
+ wasm_runtime_lookup_function(module_instance, entry_name.as_ptr(), std::ptr::null())
+ };
+ assert!((entry_func as usize) != 0);
+
+ let exec_env = unsafe { wasm_runtime_create_exec_env(module_instance, DEFAULT_STACK_SIZE) };
+ assert!((exec_env as usize) != 0);
+
+ // prepare the arguments
+ // for best compatibility with Teaclave, the function signature is `int entrypoint(int argc, char* argv[])`
+ let cstr_argv: Vec<_> = wa_argv
+ .iter()
+ .map(|arg| CString::new(arg.as_str()).unwrap())
+ .collect();
+ let wasm_argc = 2;
+ let p_argv: Vec<u32> = cstr_argv
+ .iter() // do NOT into_iter()
+ .map(|arg| unsafe {
+ wasm_runtime_module_dup_data(
+ module_instance,
+ arg.as_ptr() as *const u8,
+ arg.to_bytes_with_nul().len() as u32,
+ )
+ })
+ .collect();
+ let func_argv = unsafe {
+ wasm_runtime_module_dup_data(
+ module_instance,
+ p_argv.as_ptr() as *const u8,
+ (p_argv.len() * 4) as u32,
+ )
+ };
+ let wasm_argv: [u32; 2] = [p_argv.len() as u32, func_argv];
+
+ if unsafe { wasm_runtime_call_wasm(exec_env, entry_func, wasm_argc, wasm_argv.as_ptr()) } {
+ reset_thread_context()?;
+ log::debug!(
+ "IN WAMicroRuntime::execute after `wasm_runtime_call_wasm`, {:?}",
+ wasm_argv[0]
+ );
+ // clean WAMR allocated memory
+ let _ = p_argv
+ .iter()
+ .map(|addr| unsafe { wasm_runtime_module_free(module_instance, *addr) });
+ unsafe { wasm_runtime_module_free(module_instance, func_argv) };
+ Ok(wasm_argv[0].to_string())
+ } else {
+ Ok("WAMR Error".to_string())
+ }
+ }
+}
+
+#[cfg(feature = "enclave_unit_test")]
+pub mod tests {
+ use super::*;
+ use std::collections::HashMap;
+ use teaclave_runtime::*;
+ use teaclave_test_utils::*;
+ use teaclave_types::*;
+
+ pub fn run_tests() -> bool {
+ run_tests!(test_wamr,)
+ }
+
+ fn test_wamr() {
+ let mut args = HashMap::new();
+
+ args.insert("adder 1".to_string(), "3".to_string());
+ args.insert("adder 2".to_string(), "4".to_string());
+ let args = FunctionArguments::from(args);
+
+ let wa_payload =
+ include_bytes!("../../examples/python/wasm_simple_add_payload/simple_add.wasm");
+
+ let wa_payload = wa_payload.to_vec();
+
+ let input_files = StagedFiles::default();
+ let output_files = StagedFiles::default();
+
+ let runtime = Box::new(RawIoRuntime::new(input_files, output_files));
+
+ let function = WAMicroRuntime::default();
+ let summary = function
+ .execute("".to_string(), args, wa_payload, runtime)
+ .unwrap();
+ log::debug!("IN TEST test_wamr: AFTER execution, summary: {:?}", summary);
+
+ assert_eq!(summary, "7");
+ }
+}
diff --git a/LICENSE b/licenses/LICENSE-wasm-micro-runtime.txt
similarity index 92%
copy from LICENSE
copy to licenses/LICENSE-wasm-micro-runtime.txt
index 310ee62..c6bd7e0 100644
--- a/LICENSE
+++ b/licenses/LICENSE-wasm-micro-runtime.txt
@@ -1,4 +1,3 @@
-
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
@@ -202,27 +201,19 @@
limitations under the License.
--------------------------------------------------------------------------------
-This product bundles various third-party components under other open source
-licenses. This section summarizes those components and their licenses. See
-licenses/ for text of these licenses.
-
-
-Apache License, Version 2.0
----------------------------
-
-third-party/crates-io
-third-party/crates-sgx
-
-
-BSD 3-Clause License
---------------------
-
-common/protected_fs_rs/protected_fs_c
+--- LLVM Exceptions to the Apache 2.0 License ----
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
-MIT License
------------
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
-third_party/mesapy
-common/rusty_leveldb_sgx
diff --git a/rpc/src/protocol.rs b/rpc/src/protocol.rs
index aa73b4e..c8496af 100644
--- a/rpc/src/protocol.rs
+++ b/rpc/src/protocol.rs
@@ -103,7 +103,7 @@ where
let buf_len = send_buf.len() as u64;
let header = buf_len.to_be_bytes();
- self.transport.write(&header)?;
+ self.transport.write_all(&header)?;
self.transport.write_all(&send_buf)?;
self.transport.flush()?;
diff --git a/sdk/rust/src/bindings.rs b/sdk/rust/src/bindings.rs
index be7b072..bdb0d5b 100644
--- a/sdk/rust/src/bindings.rs
+++ b/sdk/rust/src/bindings.rs
@@ -62,8 +62,12 @@ macro_rules! unwrap_or_return_one {
///
/// * The function returns an opaque pointer (handle) of the service. On error,
/// the function returns NULL.
+///
+/// # Safety
+///
+/// `address`, `enclave_info_path`, `as_root_ca_cert_path` should be C string (null terminated).
#[no_mangle]
-pub extern "C" fn teaclave_connect_authentication_service(
+pub unsafe extern "C" fn teaclave_connect_authentication_service(
address: *const c_char,
enclave_info_path: *const c_char,
as_root_ca_cert_path: *const c_char,
@@ -72,17 +76,13 @@ pub extern "C" fn teaclave_connect_authentication_service(
return ptr::null_mut();
}
- let address = unsafe { CStr::from_ptr(address).to_string_lossy().into_owned() };
- let enclave_info_path = unsafe {
- CStr::from_ptr(enclave_info_path)
- .to_string_lossy()
- .into_owned()
- };
- let as_root_ca_cert_path = unsafe {
- CStr::from_ptr(as_root_ca_cert_path)
- .to_string_lossy()
- .into_owned()
- };
+ let address = CStr::from_ptr(address).to_string_lossy().into_owned();
+ let enclave_info_path = CStr::from_ptr(enclave_info_path)
+ .to_string_lossy()
+ .into_owned();
+ let as_root_ca_cert_path = CStr::from_ptr(as_root_ca_cert_path)
+ .to_string_lossy()
+ .into_owned();
let enclave_info = unwrap_or_return_null!(EnclaveInfo::from_file(enclave_info_path));
let bytes = unwrap_or_return_null!(fs::read(as_root_ca_cert_path));
let as_root_ca_cert = unwrap_or_return_null!(pem::parse(bytes)).contents;
@@ -98,6 +98,12 @@ pub extern "C" fn teaclave_connect_authentication_service(
/// Close and free the authentication service handle, i.e., the
/// `AuthenticaionClient` type opaque pointer. The function returns 0 for
/// success. On error, the function returns 1.
+///
+/// # Safety
+///
+/// This function is unsafe because improper use may lead to
+/// memory problems. For example, a double-free may occur if the
+/// function is called twice on the same raw pointer.
#[no_mangle]
pub unsafe extern "C" fn teaclave_close_authentication_service(
client: *mut AuthenticationClient,
@@ -113,8 +119,12 @@ pub unsafe extern "C" fn teaclave_close_authentication_service(
/// Register a new user with `user_id` and `user_password`. The function returns
/// 0 for success. On error, the function returns 1.
+///
+/// # Safety
+///
+/// `user_id`, `user_password` should be C string (null terminated).
#[no_mangle]
-pub extern "C" fn teaclave_user_register(
+pub unsafe extern "C" fn teaclave_user_register(
client: &mut AuthenticationClient,
user_id: *const c_char,
user_password: *const c_char,
@@ -126,8 +136,8 @@ pub extern "C" fn teaclave_user_register(
return 1;
}
- let user_id = unsafe { CStr::from_ptr(user_id).to_string_lossy().into_owned() };
- let user_password = unsafe { CStr::from_ptr(user_password).to_string_lossy().into_owned() };
+ let user_id = CStr::from_ptr(user_id).to_string_lossy().into_owned();
+ let user_password = CStr::from_ptr(user_password).to_string_lossy().into_owned();
unwrap_or_return_one!(client.user_register(&user_id, &user_password));
0
@@ -137,8 +147,12 @@ pub extern "C" fn teaclave_user_register(
/// will be save in the `token` buffer, and length will be set in the
/// `token_len` argument. The function returns 0 for success. On error, the
/// function returns 1.
+///
+/// # Safety
+///
+/// `user_id`, `user_password` should be C string (null terminated), token and token_len should be consistent.
#[no_mangle]
-pub extern "C" fn teaclave_user_login(
+pub unsafe extern "C" fn teaclave_user_login(
client: &mut AuthenticationClient,
user_id: *const c_char,
user_password: *const c_char,
@@ -154,20 +168,18 @@ pub extern "C" fn teaclave_user_login(
return 1;
}
- let user_id = unsafe { CStr::from_ptr(user_id).to_string_lossy().into_owned() };
- let user_password = unsafe { CStr::from_ptr(user_password).to_string_lossy().into_owned() };
+ let user_id = CStr::from_ptr(user_id).to_string_lossy().into_owned();
+ let user_password = CStr::from_ptr(user_password).to_string_lossy().into_owned();
let token_string = unwrap_or_return_one!(client.user_login(&user_id, &user_password));
let token_c_string = unwrap_or_return_one!(CString::new(token_string));
let bytes = token_c_string.as_bytes_with_nul();
- unsafe {
- if *token_len < bytes.len() {
- return 1;
- } else {
- ptr::copy_nonoverlapping(bytes.as_ptr(), token as _, bytes.len());
- *token_len = bytes.len();
- }
+ if *token_len < bytes.len() {
+ return 1;
+ } else {
+ ptr::copy_nonoverlapping(bytes.as_ptr(), token as _, bytes.len());
+ *token_len = bytes.len();
}
0
@@ -190,8 +202,12 @@ pub extern "C" fn teaclave_user_login(
///
/// * The function returns an opaque pointer (handle) of the service. On error,
/// the function returns NULL.
+///
+/// # Safety
+///
+/// All arguments should be C string (null terminated).
#[no_mangle]
-pub extern "C" fn teaclave_connect_frontend_service(
+pub unsafe extern "C" fn teaclave_connect_frontend_service(
address: *const c_char,
enclave_info_path: *const c_char,
as_root_ca_cert_path: *const c_char,
@@ -200,17 +216,13 @@ pub extern "C" fn teaclave_connect_frontend_service(
return ptr::null_mut();
}
- let address = unsafe { CStr::from_ptr(address).to_string_lossy().into_owned() };
- let enclave_info_path = unsafe {
- CStr::from_ptr(enclave_info_path)
- .to_string_lossy()
- .into_owned()
- };
- let as_root_ca_cert_path = unsafe {
- CStr::from_ptr(as_root_ca_cert_path)
- .to_string_lossy()
- .into_owned()
- };
+ let address = CStr::from_ptr(address).to_string_lossy().into_owned();
+ let enclave_info_path = CStr::from_ptr(enclave_info_path)
+ .to_string_lossy()
+ .into_owned();
+ let as_root_ca_cert_path = CStr::from_ptr(as_root_ca_cert_path)
+ .to_string_lossy()
+ .into_owned();
let enclave_info = unwrap_or_return_null!(EnclaveInfo::from_file(enclave_info_path));
let bytes = unwrap_or_return_null!(fs::read(as_root_ca_cert_path));
let as_root_ca_cert = unwrap_or_return_null!(pem::parse(bytes)).contents;
@@ -226,6 +238,12 @@ pub extern "C" fn teaclave_connect_frontend_service(
/// Close and free the frontend service handle, i.e., the `FrontendClient` type
/// opaque pointer. The function returns 0 for success. On error, the function
/// returns 1.
+///
+/// # Safety
+///
+/// This function is unsafe because improper use may lead to
+/// memory problems. For example, a double-free may occur if the
+/// function is called twice on the same raw pointer.
#[no_mangle]
pub unsafe extern "C" fn teaclave_close_frontend_service(client: *mut FrontendClient) -> c_int {
if client.is_null() {
@@ -239,8 +257,12 @@ pub unsafe extern "C" fn teaclave_close_frontend_service(client: *mut FrontendCl
/// Set user's credential with `user_id` and `user_token`. The function returns
/// 0 for success. On error, the function returns 1.
+///
+/// # Safety
+///
+/// `user_id` and `user_token` should be C string (null terminated).
#[no_mangle]
-pub extern "C" fn teaclave_set_credential(
+pub unsafe extern "C" fn teaclave_set_credential(
client: &mut FrontendClient,
user_id: *const c_char,
user_token: *const c_char,
@@ -249,8 +271,8 @@ pub extern "C" fn teaclave_set_credential(
return 1;
}
- let user_id = unsafe { CStr::from_ptr(user_id).to_string_lossy().into_owned() };
- let user_token = unsafe { CStr::from_ptr(user_token).to_string_lossy().into_owned() };
+ let user_id = CStr::from_ptr(user_id).to_string_lossy().into_owned();
+ let user_token = CStr::from_ptr(user_token).to_string_lossy().into_owned();
client.set_credential(&user_id, &user_token);
0
@@ -258,8 +280,12 @@ pub extern "C" fn teaclave_set_credential(
/// Invoke task with `task_id`. The function returns 0 for success. On error,
/// the function returns 1.
+///
+/// # Safety
+///
+/// `task_id` should be C string (null terminated).
#[no_mangle]
-pub extern "C" fn teaclave_invoke_task(
+pub unsafe extern "C" fn teaclave_invoke_task(
client: &mut FrontendClient,
task_id: *const c_char,
) -> c_int {
@@ -267,7 +293,7 @@ pub extern "C" fn teaclave_invoke_task(
return 1;
}
- let task_id = unsafe { CStr::from_ptr(task_id).to_string_lossy().into_owned() };
+ let task_id = CStr::from_ptr(task_id).to_string_lossy().into_owned();
match client.invoke_task(&task_id) {
Ok(_) => 0,
Err(_) => 1,
@@ -278,8 +304,12 @@ pub extern "C" fn teaclave_invoke_task(
/// buffer, and set corresponding `task_result_len` argument. Note that this is
/// a blocking function and wait for the return of the task. The function
/// returns 0 for success. On error, the function returns 1.
+///
+/// # Safety
+///
+/// Inconsistent length of allocated buffer may caused overflow.
#[no_mangle]
-pub extern "C" fn teaclave_get_task_result(
+pub unsafe extern "C" fn teaclave_get_task_result(
client: &mut FrontendClient,
task_id: *const c_char,
task_result: *mut c_char,
@@ -289,16 +319,14 @@ pub extern "C" fn teaclave_get_task_result(
return 1;
}
- let task_id = unsafe { CStr::from_ptr(task_id).to_string_lossy().into_owned() };
+ let task_id = CStr::from_ptr(task_id).to_string_lossy().into_owned();
match client.get_task_result(&task_id) {
Ok(result) => {
- unsafe {
- if *task_result_len < result.len() {
- return 1;
- } else {
- ptr::copy_nonoverlapping(result.as_ptr(), task_result as _, result.len());
- *task_result_len = result.len();
- }
+ if *task_result_len < result.len() {
+ return 1;
+ } else {
+ ptr::copy_nonoverlapping(result.as_ptr(), task_result as _, result.len());
+ *task_result_len = result.len();
}
0
}
@@ -323,8 +351,12 @@ macro_rules! generate_function_serialized {
/// # Return
///
/// The function returns 0 for success. On error, the function returns 1.
+ ///
+ /// # Safety
+ ///
+ /// Inconsistent length of allocated buffer may caused overflow.
#[no_mangle]
- pub extern "C" fn $c_function_name(
+ pub unsafe extern "C" fn $c_function_name(
client: &mut $client_type,
serialized_request: *const c_char,
serialized_response: *mut c_char,
@@ -338,23 +370,19 @@ macro_rules! generate_function_serialized {
return 1;
}
- let serialized_request = unsafe {
- CStr::from_ptr(serialized_request)
- .to_string_lossy()
- .into_owned()
- };
+ let serialized_request = CStr::from_ptr(serialized_request)
+ .to_string_lossy()
+ .into_owned();
let function_id_string =
unwrap_or_return_one!(client.$rust_function_name(&serialized_request));
let function_id_c_string = unwrap_or_return_one!(CString::new(function_id_string));
let bytes = function_id_c_string.as_bytes_with_nul();
- unsafe {
- if *serialized_response_len < bytes.len() {
- return 1;
- } else {
- ptr::copy_nonoverlapping(bytes.as_ptr(), serialized_response as _, bytes.len());
- *serialized_response_len = bytes.len();
- }
+ if *serialized_response_len < bytes.len() {
+ return 1;
+ } else {
+ ptr::copy_nonoverlapping(bytes.as_ptr(), serialized_response as _, bytes.len());
+ *serialized_response_len = bytes.len();
}
0
diff --git a/sdk/rust/src/lib.rs b/sdk/rust/src/lib.rs
index 633b9ce..95c768c 100644
--- a/sdk/rust/src/lib.rs
+++ b/sdk/rust/src/lib.rs
@@ -190,6 +190,7 @@ impl FrontendClient {
Ok(response)
}
+ #[allow(clippy::too_many_arguments)]
pub fn register_function(
&mut self,
name: &str,
diff --git a/services/proto/proto_gen/main.rs b/services/proto/proto_gen/main.rs
index d686980..00eddf6 100644
--- a/services/proto/proto_gen/main.rs
+++ b/services/proto/proto_gen/main.rs
@@ -15,9 +15,7 @@
// specific language governing permissions and limitations
// under the License.
-use askama;
use askama::Template;
-use prost_build;
use std::path;
use structopt::StructOpt;
diff --git a/third_party/wamr.patch b/third_party/wamr.patch
new file mode 100644
index 0000000..793b07d
--- /dev/null
+++ b/third_party/wamr.patch
@@ -0,0 +1,651 @@
+diff --git a/core/shared/platform/teaclave-sgx/platform_internal.h b/core/shared/platform/teaclave-sgx/platform_internal.h
+new file mode 100644
+index 0000000..93417b4
+--- /dev/null
++++ b/core/shared/platform/teaclave-sgx/platform_internal.h
+@@ -0,0 +1,58 @@
++/*
++ * Copyright (C) 2019 Intel Corporation. All rights reserved.
++ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
++ */
++
++#ifndef _PLATFORM_INTERNAL_H
++#define _PLATFORM_INTERNAL_H
++
++#include <inttypes.h>
++#include <stdbool.h>
++#include <assert.h>
++#include <time.h>
++#include <string.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <math.h>
++#include <unistd.h>
++#include <stdarg.h>
++#include <ctype.h>
++#include <limits.h>
++#include <errno.h>
++#include <sgx_thread.h>
++#include <pthread.h>
++
++#include "sgx_error.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#ifndef BH_PLATFORM_LINUX_SGX
++#define BH_PLATFORM_LINUX_SGX
++#endif
++
++#define _STACK_SIZE_ADJUSTMENT (32 * 1024)
++
++/* Stack size of applet threads's native part. */
++#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT)
++
++/* Default thread priority */
++#define BH_THREAD_DEFAULT_PRIORITY 0
++
++typedef pthread_t korp_thread;
++typedef pthread_t korp_tid;
++typedef pthread_mutex_t korp_mutex;
++typedef pthread_cond_t korp_cond;
++
++typedef void (*os_print_function_t)(const char* message);
++void os_set_print_function(os_print_function_t pf);
++
++char *strcpy(char *dest, const char *src);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* end of _PLATFORM_INTERNAL_H */
++
+diff --git a/core/shared/platform/teaclave-sgx/sgx_platform.c b/core/shared/platform/teaclave-sgx/sgx_platform.c
+new file mode 100644
+index 0000000..e819f26
+--- /dev/null
++++ b/core/shared/platform/teaclave-sgx/sgx_platform.c
+@@ -0,0 +1,172 @@
++/*
++ * Copyright (C) 2019 Intel Corporation. All rights reserved.
++ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
++ */
++
++#include "platform_api_vmcore.h"
++#include "platform_api_extension.h"
++#include "sgx_rsrv_mem_mngr.h"
++
++#define FIXED_BUFFER_SIZE (1<<9)
++
++static os_print_function_t print_function = NULL;
++
++int bh_platform_init()
++{
++ return 0;
++}
++
++void
++bh_platform_destroy()
++{
++}
++
++void *
++os_malloc(unsigned size)
++{
++ return malloc(size);
++}
++
++void *
++os_realloc(void *ptr, unsigned size)
++{
++ return realloc(ptr, size);
++}
++
++void
++os_free(void *ptr)
++{
++ free(ptr);
++}
++
++int putchar(int c)
++{
++ return 0;
++}
++
++int puts(const char *s)
++{
++ return 0;
++}
++
++void os_set_print_function(os_print_function_t pf)
++{
++ print_function = pf;
++}
++
++int os_printf(const char *message, ...)
++{
++ if (print_function != NULL) {
++ char msg[FIXED_BUFFER_SIZE] = { '\0' };
++ va_list ap;
++ va_start(ap, message);
++ vsnprintf(msg, FIXED_BUFFER_SIZE, message, ap);
++ va_end(ap);
++ print_function(msg);
++ }
++
++ return 0;
++}
++
++int os_vprintf(const char * format, va_list arg)
++{
++ if (print_function != NULL) {
++ char msg[FIXED_BUFFER_SIZE] = { '\0' };
++ vsnprintf(msg, FIXED_BUFFER_SIZE, format, arg);
++ print_function(msg);
++ }
++
++ return 0;
++}
++
++char *strcpy(char *dest, const char *src)
++{
++ const unsigned char *s = src;
++ unsigned char *d = dest;
++
++ while ((*d++ = *s++));
++ return dest;
++}
++
++void* os_mmap(void *hint, size_t size, int prot, int flags)
++{
++ int mprot = 0;
++ uint64 aligned_size, page_size;
++ void* ret = NULL;
++ sgx_status_t st = 0;
++
++ page_size = getpagesize();
++ aligned_size = (size + page_size - 1) & ~(page_size - 1);
++
++ if (aligned_size >= UINT32_MAX)
++ return NULL;
++
++ ret = sgx_alloc_rsrv_mem(aligned_size);
++ if (ret == NULL) {
++ os_printf("os_mmap(size=%u, aligned size=%lu, prot=0x%x) failed.",
++ size, aligned_size, prot);
++ return NULL;
++ }
++
++ if (prot & MMAP_PROT_READ)
++ mprot |= SGX_PROT_READ;
++ if (prot & MMAP_PROT_WRITE)
++ mprot |= SGX_PROT_WRITE;
++ if (prot & MMAP_PROT_EXEC)
++ mprot |= SGX_PROT_EXEC;
++
++ st = sgx_tprotect_rsrv_mem(ret, aligned_size, mprot);
++ if (st != SGX_SUCCESS) {
++ os_printf("os_mmap(size=%u, prot=0x%x) failed to set protect.",
++ size, prot);
++ sgx_free_rsrv_mem(ret, aligned_size);
++ return NULL;
++ }
++
++ return ret;
++}
++
++void os_munmap(void *addr, size_t size)
++{
++ uint64 aligned_size, page_size;
++
++ page_size = getpagesize();
++ aligned_size = (size + page_size - 1) & ~(page_size - 1);
++ sgx_free_rsrv_mem(addr, aligned_size);
++}
++
++int os_mprotect(void *addr, size_t size, int prot)
++{
++ int mprot = 0;
++ sgx_status_t st = 0;
++ uint64 aligned_size, page_size;
++
++ page_size = getpagesize();
++ aligned_size = (size + page_size - 1) & ~(page_size - 1);
++
++ if (prot & MMAP_PROT_READ)
++ mprot |= SGX_PROT_READ;
++ if (prot & MMAP_PROT_WRITE)
++ mprot |= SGX_PROT_WRITE;
++ if (prot & MMAP_PROT_EXEC)
++ mprot |= SGX_PROT_EXEC;
++ st = sgx_tprotect_rsrv_mem(addr, aligned_size, mprot);
++ if (st != SGX_SUCCESS)
++ os_printf("os_mprotect(addr=0x%"PRIx64", size=%u, prot=0x%x) failed.",
++ (uintptr_t)addr, size, prot);
++
++ return (st == SGX_SUCCESS? 0:-1);
++}
++
++uint64
++os_time_get_boot_microsecond()
++{
++ /* TODO */
++ return 0;
++}
++
++void
++os_dcache_flush(void)
++{
++}
++
+diff --git a/core/shared/platform/teaclave-sgx/sgx_rsrv_mem_mngr.h b/core/shared/platform/teaclave-sgx/sgx_rsrv_mem_mngr.h
+new file mode 100644
+index 0000000..b32a68b
+--- /dev/null
++++ b/core/shared/platform/teaclave-sgx/sgx_rsrv_mem_mngr.h
+@@ -0,0 +1,90 @@
++/*
++ * Copyright (C) 2011-2019 Intel Corporation. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * * Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ * * Neither the name of Intel Corporation nor the names of its
++ * contributors may be used to endorse or promote products derived
++ * from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ */
++
++/*
++ * This file is copied from https://github.com/intel/linux-sgx/blob/4589daddd58bec7367a6a9de3fe301e6de17671a/common/inc/internal/sgx_rsrv_mem_mngr.h
++ * The reason we copied here is that the official SGX SDK release has
++ * not included this header file yet.
++ */
++
++#pragma once
++
++#ifndef _SGX_RSRV_MEM_MNGR_H_
++#define _SGX_RSRV_MEM_MNGR_H_
++
++#include "stdint.h"
++#include "sgx_error.h"
++
++#define SGX_PROT_READ 0x1 /* page can be read */
++#define SGX_PROT_WRITE 0x2 /* page can be written */
++#define SGX_PROT_EXEC 0x4 /* page can be executed */
++#define SGX_PROT_NONE 0x0 /* page can not be accessed */
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++ /* Allocate a range of EPC memory from the reserved memory area with RW permission
++ *
++ * Parameters:
++ * Inputs: length [in]: Size of region to be allocated in bytes. Page aligned
++ * Return: Starting address of the new allocated memory area on success; otherwise NULL
++ */
++ void * sgx_alloc_rsrv_mem(size_t length);
++
++
++ /* Free a range of EPC memory from the reserved memory area
++ *
++ * Parameters:
++ * Inputs: addr[in]: Starting address of region to be freed. Page aligned.
++ * length[in]: The length of the memory to be freed in bytes. Page aligned
++ * Return: 0 on success; otherwise -1
++ */
++ int sgx_free_rsrv_mem(void * addr, size_t length);
++
++
++ /* Modify the access permissions of the pages in the reserved memory area.
++ *
++ * Parameters:
++ * Inputs: addr[in]: Starting address of region which needs to change access permission. Page aligned.
++ * length[in]: The length of the memory to be manipulated in bytes. Page aligned.
++ * prot[in]: The target memory protection.
++ * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h
++ */
++ sgx_status_t sgx_tprotect_rsrv_mem(void *addr, size_t len, int prot);
++
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
++
+diff --git a/core/shared/platform/teaclave-sgx/sgx_thread.c b/core/shared/platform/teaclave-sgx/sgx_thread.c
+new file mode 100644
+index 0000000..d1503b4
+--- /dev/null
++++ b/core/shared/platform/teaclave-sgx/sgx_thread.c
+@@ -0,0 +1,180 @@
++/*
++ * Copyright (C) 2019 Intel Corporation. All rights reserved.
++ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
++ */
++
++#include "platform_api_vmcore.h"
++#include "platform_api_extension.h"
++
++#ifndef SGX_DISABLE_PTHREAD
++typedef struct {
++ thread_start_routine_t start;
++ void *arg;
++} thread_wrapper_arg;
++
++static void *os_thread_wrapper(void *arg)
++{
++ thread_wrapper_arg * targ = arg;
++ thread_start_routine_t start_func = targ->start;
++ void *thread_arg = targ->arg;
++ os_printf("THREAD CREATED %p\n", &targ);
++ BH_FREE(targ);
++ start_func(thread_arg);
++ return NULL;
++}
++
++int os_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start,
++ void *arg, unsigned int stack_size, int prio)
++{
++ thread_wrapper_arg *targ;
++
++ assert(tid);
++ assert(start);
++
++ targ = (thread_wrapper_arg *) BH_MALLOC(sizeof(*targ));
++ if (!targ) {
++ return BHT_ERROR;
++ }
++
++ targ->start = start;
++ targ->arg = arg;
++
++ if (pthread_create(tid, NULL, os_thread_wrapper, targ) != 0) {
++ BH_FREE(targ);
++ return BHT_ERROR;
++ }
++
++ return BHT_OK;
++}
++
++int os_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg,
++ unsigned int stack_size)
++{
++ return os_thread_create_with_prio(tid, start, arg, stack_size,
++ BH_THREAD_DEFAULT_PRIORITY);
++}
++#endif
++
++korp_tid os_self_thread()
++{
++#ifndef SGX_DISABLE_PTHREAD
++ return pthread_self();
++#else
++ return 0;
++#endif
++}
++
++int os_mutex_init(korp_mutex *mutex)
++{
++#ifndef SGX_DISABLE_PTHREAD
++ pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
++ *mutex = m;
++#endif
++ return BHT_OK;
++}
++
++int os_mutex_destroy(korp_mutex *mutex)
++{
++#ifndef SGX_DISABLE_PTHREAD
++ pthread_mutex_destroy(mutex);
++#endif
++ return BHT_OK;
++}
++
++int os_mutex_lock(korp_mutex *mutex)
++{
++#ifndef SGX_DISABLE_PTHREAD
++ return pthread_mutex_lock(mutex);
++#else
++ return 0;
++#endif
++}
++
++int os_mutex_unlock(korp_mutex *mutex)
++{
++#ifndef SGX_DISABLE_PTHREAD
++ return pthread_mutex_unlock(mutex);
++#else
++ return 0;
++#endif
++}
++
++int os_cond_init(korp_cond *cond)
++{
++#ifndef SGX_DISABLE_PTHREAD
++ pthread_cond_t c = PTHREAD_COND_INITIALIZER;
++ *cond = c;
++#endif
++ return BHT_OK;
++}
++
++int os_cond_destroy(korp_cond *cond)
++{
++#ifndef SGX_DISABLE_PTHREAD
++ pthread_cond_destroy(cond);
++#endif
++ return BHT_OK;
++}
++
++int os_cond_wait(korp_cond *cond, korp_mutex *mutex)
++{
++#ifndef SGX_DISABLE_PTHREAD
++ assert(cond);
++ assert(mutex);
++
++ if (pthread_cond_wait(cond, mutex) != BHT_OK)
++ return BHT_ERROR;
++
++#endif
++ return BHT_OK;
++}
++
++int os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds)
++{
++ os_printf("warning: SGX pthread_cond_timedwait isn't supported, "
++ "calling pthread_cond_wait instead!\n");
++ return BHT_ERROR;
++}
++
++int os_cond_signal(korp_cond *cond)
++{
++#ifndef SGX_DISABLE_PTHREAD
++ assert(cond);
++
++ if (pthread_cond_signal(cond) != BHT_OK)
++ return BHT_ERROR;
++
++#endif
++ return BHT_OK;
++}
++
++int os_thread_join(korp_tid thread, void **value_ptr)
++{
++#ifndef SGX_DISABLE_PTHREAD
++ return pthread_join(thread, value_ptr);
++#else
++ return 0;
++#endif
++}
++
++int os_thread_detach(korp_tid thread)
++{
++ /* SGX pthread_detach isn't provided, return directly. */
++ return 0;
++}
++
++void os_thread_exit(void *retval)
++{
++#ifndef SGX_DISABLE_PTHREAD
++ pthread_exit(retval);
++#else
++ return;
++#endif
++}
++
++uint8 *os_thread_get_stack_boundary()
++{
++ /* TODO: get sgx stack boundary */
++ return NULL;
++}
++
+diff --git a/core/shared/platform/teaclave-sgx/shared_platform.cmake b/core/shared/platform/teaclave-sgx/shared_platform.cmake
+new file mode 100644
+index 0000000..fa3a7aa
+--- /dev/null
++++ b/core/shared/platform/teaclave-sgx/shared_platform.cmake
+@@ -0,0 +1,33 @@
++# Copyright (C) 2019 Intel Corporation. All rights reserved.
++# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
++
++set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
++
++add_definitions(-DBH_PLATFORM_LINUX_SGX)
++
++include_directories(${PLATFORM_SHARED_DIR})
++include_directories(${PLATFORM_SHARED_DIR}/../include)
++
++if ("$ENV{SGX_SDK}" STREQUAL "")
++ set (SGX_SDK_DIR "/opt/intel/sgxsdk")
++else()
++ set (SGX_SDK_DIR $ENV{SGX_SDK})
++endif()
++
++include_directories (${SGX_SDK_DIR}/include)
++if (NOT BUILD_UNTRUST_PART EQUAL 1)
++ include_directories (${SGX_SDK_DIR}/include/tlibc
++ ${SGX_SDK_DIR}/include/libcxx)
++endif ()
++
++if (NOT WAMR_BUILD_LIBC_WASI EQUAL 1)
++ add_definitions(-DSGX_DISABLE_WASI)
++endif ()
++
++if (NOT WAMR_BUILD_THREAD_MGR EQUAL 1)
++ add_definitions(-DSGX_DISABLE_PTHREAD)
++endif ()
++
++file (GLOB source_all ${PLATFORM_SHARED_DIR}/*.c)
++
++set (PLATFORM_SHARED_SOURCE ${source_all})
+diff --git a/product-mini/platforms/teaclave-sgx/CMakeLists.txt b/product-mini/platforms/teaclave-sgx/CMakeLists.txt
+new file mode 100644
+index 0000000..d4c71d8
+--- /dev/null
++++ b/product-mini/platforms/teaclave-sgx/CMakeLists.txt
+@@ -0,0 +1,82 @@
++# Copyright (C) 2019 Intel Corporation. All rights reserved.
++# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
++
++cmake_minimum_required (VERSION 2.8)
++
++project (iwasm)
++
++set (WAMR_BUILD_PLATFORM "teaclave-sgx")
++
++# Reset default linker flags
++set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
++set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
++
++# Set WAMR_BUILD_TARGET
++if (NOT DEFINED WAMR_BUILD_TARGET)
++ if (CMAKE_SIZEOF_VOID_P EQUAL 8)
++ # Build as X86_64 by default in 64-bit platform
++ set (WAMR_BUILD_TARGET "X86_64")
++ else ()
++ # Build as X86_32 by default in 32-bit platform
++ set (WAMR_BUILD_TARGET "X86_32")
++ endif ()
++endif ()
++
++if (NOT CMAKE_BUILD_TYPE)
++ set(CMAKE_BUILD_TYPE Release)
++endif ()
++
++if (NOT DEFINED WAMR_BUILD_INTERP)
++ # Enable Interpreter by default
++ set (WAMR_BUILD_INTERP 1)
++endif ()
++
++if (NOT DEFINED WAMR_BUILD_AOT)
++ # Enable AOT by default
++ # Please install Intel SGX SDKv2.8 or later.
++ set (WAMR_BUILD_AOT 0)
++endif ()
++
++if (NOT DEFINED WAMR_BUILD_JIT)
++ # Disable JIT by default.
++ set (WAMR_BUILD_JIT 0)
++endif ()
++
++if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN)
++ # Enable libc builtin support by default
++ set (WAMR_BUILD_LIBC_BUILTIN 0)
++endif ()
++
++if (NOT DEFINED WAMR_BUILD_LIBC_WASI)
++ # Enable libc wasi support by default
++ set (WAMR_BUILD_LIBC_WASI 0)
++endif ()
++
++if (NOT DEFINED WAMR_BUILD_FAST_INTERP)
++ # Enable fast interpreter
++ set (WAMR_BUILD_FAST_INTERP 0)
++endif ()
++
++if (NOT DEFINED WAMR_BUILD_MULTI_MODULE)
++ # Enable multiple modules
++ set (WAMR_BUILD_MULTI_MODULE 0)
++endif ()
++
++if (NOT DEFINED WAMR_BUILD_LIB_PTHREAD)
++ # Enable pthread library by default
++ set (WAMR_BUILD_LIB_PTHREAD 0)
++endif ()
++
++if (COLLECT_CODE_COVERAGE EQUAL 1)
++ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
++endif ()
++
++set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
++set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -ffunction-sections -fdata-sections \
++ -Wall -Wno-unused-parameter -Wno-pedantic \
++ -nostdinc -fvisibility=hidden -fpie" )
++
++set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
++
++include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
++add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE})
diff --git a/third_party/wasm-micro-runtime b/third_party/wasm-micro-runtime
new file mode 160000
index 0000000..7706e4b
--- /dev/null
+++ b/third_party/wasm-micro-runtime
@@ -0,0 +1 @@
+Subproject commit 7706e4b1514e5fd95a1c5efe258ecd08467d030a
diff --git a/types/src/worker.rs b/types/src/worker.rs
index 37c5991..a3cc5be 100644
--- a/types/src/worker.rs
+++ b/types/src/worker.rs
@@ -41,6 +41,7 @@ pub trait TeaclaveExecutor {
pub enum ExecutorType {
Builtin,
Python,
+ WAMicroRuntime,
}
impl std::default::Default for ExecutorType {
@@ -56,6 +57,7 @@ impl std::convert::TryFrom<&str> for ExecutorType {
let executor_type = match selector {
"python" => ExecutorType::Python,
"builtin" => ExecutorType::Builtin,
+ "wamr" => ExecutorType::WAMicroRuntime,
_ => anyhow::bail!("Invalid executor type: {}", selector),
};
Ok(executor_type)
@@ -81,6 +83,7 @@ impl std::fmt::Display for ExecutorType {
match self {
ExecutorType::Builtin => write!(f, "builtin"),
ExecutorType::Python => write!(f, "python"),
+ ExecutorType::WAMicroRuntime => write!(f, "wamr"),
}
}
}
@@ -89,6 +92,7 @@ impl std::fmt::Display for ExecutorType {
pub enum Executor {
MesaPy,
Builtin,
+ WAMicroRuntime,
}
impl std::default::Default for Executor {
@@ -104,6 +108,7 @@ impl std::convert::TryFrom<&str> for Executor {
let executor = match selector {
"mesapy" => Executor::MesaPy,
"builtin" => Executor::Builtin,
+ "wamr" => Executor::WAMicroRuntime,
_ => anyhow::bail!("Unsupported executor: {}", selector),
};
Ok(executor)
@@ -123,6 +128,7 @@ impl std::fmt::Display for Executor {
match self {
Executor::MesaPy => write!(f, "mesapy"),
Executor::Builtin => write!(f, "builtin"),
+ Executor::WAMicroRuntime => write!(f, "wamr"),
}
}
}
diff --git a/worker/src/worker.rs b/worker/src/worker.rs
index 2109451..1f1ed1e 100644
--- a/worker/src/worker.rs
+++ b/worker/src/worker.rs
@@ -23,7 +23,7 @@ use std::format;
use teaclave_types::{Executor, ExecutorType, StagedFiles, StagedFunction};
-use teaclave_executor::{BuiltinFunctionExecutor, MesaPy};
+use teaclave_executor::{BuiltinFunctionExecutor, MesaPy, WAMicroRuntime};
use teaclave_runtime::DefaultRuntime;
use teaclave_types::{TeaclaveExecutor, TeaclaveRuntime};
@@ -58,6 +58,10 @@ impl Default for Worker {
worker.register_executor((ExecutorType::Builtin, Executor::Builtin), || {
Box::new(BuiltinFunctionExecutor::default())
});
+ worker.register_executor(
+ (ExecutorType::WAMicroRuntime, Executor::WAMicroRuntime),
+ || Box::new(WAMicroRuntime::default()),
+ );
worker
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org