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 8003e93 Add support for Teaclave protected files in WAMR executor and
related (#512)
8003e93 is described below
commit 8003e93dc7d377287805ad2191e06fa84166d0a4
Author: Hongbo <[email protected]>
AuthorDate: Mon Jun 28 14:42:03 2021 -0400
Add support for Teaclave protected files in WAMR executor and related (#512)
---
.../python/wasm_teaclave_pf_payload/teaclave_pf.c | 125 +++++++++++++++++++
.../python/wasm_teaclave_pf_payload/teaclave_pf.h | 68 +++++++++++
.../wasm_teaclave_pf_payload/teaclave_pf.wasm | Bin 0 -> 2970 bytes
executor/src/context.rs | 104 +++++++++++++++-
executor/src/wamr.rs | 135 ++++++++++++++++++---
tests/fixtures/functions/wamr/expected_output.txt | 1 +
tests/fixtures/functions/wamr/input_a.txt | 1 +
tests/fixtures/functions/wamr/input_b.txt | 1 +
8 files changed, 412 insertions(+), 23 deletions(-)
diff --git a/examples/python/wasm_teaclave_pf_payload/teaclave_pf.c
b/examples/python/wasm_teaclave_pf_payload/teaclave_pf.c
new file mode 100644
index 0000000..1543273
--- /dev/null
+++ b/examples/python/wasm_teaclave_pf_payload/teaclave_pf.c
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ *
+ */
+
+/** Compilation flags:
+ * -nostdlib \
+ * -Wl,--export-all \
+ * -Wl,--no-entry \
+ * -Wl,--allow-undefined \
+ */
+
+#include "teaclave_pf.h"
+
+int strlen(const char *str)
+{
+ const char *s;
+
+ for (s = str; *s; ++s)
+ ;
+ return (s - str);
+}
+
+int atoi(const char *str)
+{
+ int result = 0;
+ int sign = 0;
+
+ while (*str == ' ' || *str == '\t' || *str == '\n')
+ ++str;
+
+ if (*str == '-')
+ {
+ sign = 1;
+ ++str;
+ }
+ else if (*str == '+')
+ {
+ ++str;
+ }
+
+ // proc numbers
+ while (*str >= '0' && *str <= '9')
+ {
+ result = result * 10 + *str - '0';
+ ++str;
+ }
+
+ if (sign == 1)
+ return -result;
+ else
+ return result;
+}
+
+int entrypoint(int argc, char *argv[])
+{
+ if (argc < 6)
+ {
+ return -1;
+ }
+
+ if ((argv[0] == 0) || argv[2] == 0 || argv[4] == 0)
+ {
+ return -1;
+ }
+
+ char *input_fid_a = argv[1];
+ char *input_fid_b = argv[3];
+ char *output_fid = argv[5];
+
+ int buf_len = 11, rv = -2;
+ char buf_a[buf_len];
+ char buf_b[buf_len];
+
+ int input_handle_a = teaclave_open_input(input_fid_a);
+ int input_handle_b = teaclave_open_input(input_fid_b);
+
+ int output_handle = teaclave_create_output(output_fid);
+
+ // check failure
+ if ((input_handle_a == -1) || (input_handle_b == -1) || (output_handle ==
-1))
+ {
+ return -1;
+ }
+
+ int read_bytes_a = teaclave_read_file(input_handle_a, buf_a, buf_len - 1);
+ int read_bytes_b = teaclave_read_file(input_handle_b, buf_b, buf_len - 1);
+
+ if ((read_bytes_a == -1) || (read_bytes_b == -1))
+ {
+ return -1;
+ }
+
+ int a = atoi(buf_a), b = atoi(buf_b);
+
+ if (a > b)
+ {
+ rv = teaclave_write_file(output_handle, input_fid_a,
strlen(input_fid_a));
+ }
+ else
+ {
+ rv = teaclave_write_file(output_handle, input_fid_b,
strlen(input_fid_b));
+ }
+
+ teaclave_close_file(input_handle_a);
+ teaclave_close_file(input_handle_b);
+ teaclave_close_file(output_handle);
+
+ return rv;
+}
diff --git a/examples/python/wasm_teaclave_pf_payload/teaclave_pf.h
b/examples/python/wasm_teaclave_pf_payload/teaclave_pf.h
new file mode 100644
index 0000000..85ec033
--- /dev/null
+++ b/examples/python/wasm_teaclave_pf_payload/teaclave_pf.h
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ *
+ */
+
+/**
+ * Open a protected file as input
+ *
+ * @param fid the uid of the file, c string pointer
+ *
+ * @return file handler, -1 if error occurs
+ */
+int teaclave_open_input(char *file_id);
+
+/**
+ * Create/Open? a protected file as output
+ *
+ * @param fid the uid of the file, c string pointer
+ *
+ * @return file handler, -1 if error occurs
+ */
+int teaclave_create_output(char *file_id);
+
+/**
+ * Read content from a file to a buffer
+ *
+ * @param fd file handler returned by `teaclave_open_input`
+ * @param out_buf the pointer to output buffer
+ * @param buf_size the total size in bytes of the output buffer
+ *
+ * @return bytes read from the file, -1 if error occurs
+ */
+int teaclave_read_file(int fd, void *out_buf, int buf_size);
+
+/**
+ * Write content from a buffer to a file
+ *
+ * @param fd file handler returned by `teaclave_create_output`
+ * @param buf the pointer to the buffer holding content to write
+ * @param buf_size the total size in bytes to read from the buffer and write
to the file
+ *
+ * @return bytes written to the file, -1 if error occurs
+ */
+int teaclave_write_file(int fd, void *buf, int buf_size);
+
+/**
+ * Close a file handler
+ *
+ * @param fd file handler to close
+ *
+ * @return 0 if succeed, -1 otherwise
+ */
+int teaclave_close_file(int fd);
diff --git a/examples/python/wasm_teaclave_pf_payload/teaclave_pf.wasm
b/examples/python/wasm_teaclave_pf_payload/teaclave_pf.wasm
new file mode 100755
index 0000000..1db2120
Binary files /dev/null and
b/examples/python/wasm_teaclave_pf_payload/teaclave_pf.wasm differ
diff --git a/executor/src/context.rs b/executor/src/context.rs
index 6e1303d..8470105 100644
--- a/executor/src/context.rs
+++ b/executor/src/context.rs
@@ -29,8 +29,11 @@ use std::format;
use teaclave_types::TeaclaveRuntime;
+use std::ffi::c_void;
+
const FFI_OK: c_uint = 0;
const FFI_FILE_ERROR: c_uint = 1;
+const FFI_FILE_ERROR_WASM: c_int = -1;
pub struct Context {
runtime: Box<dyn TeaclaveRuntime + Send + Sync>,
@@ -298,9 +301,7 @@ use std::ffi::CStr;
/*
* uint c_open_input(char* file_id, int* out_fd);
- *
*/
-
#[allow(unused)]
#[no_mangle]
extern "C" fn c_open_input(fid: *mut c_char, out_handle: *mut c_int) -> c_uint
{
@@ -321,8 +322,24 @@ extern "C" fn c_open_input(fid: *mut c_char, out_handle:
*mut c_int) -> c_uint {
}
/*
+ * int teaclave_open_input(char* file_id);
+ */
+#[allow(unused)]
+#[no_mangle]
+pub extern "C" fn wasm_open_input(_exec_env: *const c_void, fid: *mut c_char)
-> c_int {
+ debug!("wasm_open_input");
+ let fid = unsafe { CStr::from_ptr(fid).to_string_lossy().into_owned() };
+ match rtc_open_input(&fid) {
+ Ok(handle) => handle as i32,
+ Err(e) => {
+ error!("wasm_open_input: {:?}", e);
+ FFI_FILE_ERROR_WASM
+ }
+ }
+}
+
+/*
* uint c_create_output(char* file_id, int* out_fd);
- *
*/
#[allow(unused)]
#[no_mangle]
@@ -344,12 +361,29 @@ extern "C" fn c_create_output(fid: *mut c_char,
out_handle: *mut c_int) -> c_uin
}
/*
- * uint c_read_file(int fd, void* out_buf, size_t buf_size, size_t*
out_size_read);
+ * int teaclave_create_output(char* file_id);
*
*/
#[allow(unused)]
#[no_mangle]
+pub extern "C" fn wasm_create_output(_exec_env: *const c_void, fid: *mut
c_char) -> c_int {
+ debug!("wasm_create_output");
+ let fid = unsafe { CStr::from_ptr(fid).to_string_lossy().into_owned() };
+ match rtc_create_output(&fid) {
+ Ok(handle) => handle as i32,
+ Err(e) => {
+ error!("wasm_create_output: {:?}", e);
+ FFI_FILE_ERROR_WASM
+ }
+ }
+}
+
+/*
+ * uint c_read_file(int fd, void* out_buf, size_t buf_size, size_t*
out_size_read);
+ */
+#[allow(unused)]
+#[no_mangle]
extern "C" fn c_read_file(
handle: c_int,
out_buf: *mut c_uchar,
@@ -374,6 +408,29 @@ extern "C" fn c_read_file(
}
/*
+ * int teaclave_read_file(int fd, void* out_buf, int buf_size);
+ */
+#[allow(unused)]
+#[no_mangle]
+pub extern "C" fn wasm_read_file(
+ _exec_env: *const c_void,
+ handle: c_int,
+ out_buf: *mut c_uchar,
+ buf_size: c_int,
+) -> c_int {
+ debug!("wasm_read_file");
+ let out: &mut [u8] = unsafe { slice::from_raw_parts_mut(out_buf, buf_size
as usize) };
+
+ match rtc_read_handle(handle, out) {
+ Ok(size) => size as i32,
+ Err(e) => {
+ error!("wasm_read_file: {:?}", e);
+ FFI_FILE_ERROR_WASM
+ }
+ }
+}
+
+/*
* uint c_write_file(int fd, void* buf, size_t buf_size, size_t*
out_size_written);
*/
#[allow(unused)]
@@ -402,6 +459,29 @@ extern "C" fn c_write_file(
}
/*
+ * int teaclave_write_file(int fd, void* buf, size_t buf_size);
+ */
+#[allow(unused)]
+#[no_mangle]
+pub extern "C" fn wasm_write_file(
+ _exec_env: *const c_void,
+ handle: c_int,
+ in_buf: *mut c_uchar,
+ buf_size: c_int,
+) -> c_int {
+ debug!("wasm_write_file");
+ let in_buf: &[u8] = unsafe { slice::from_raw_parts_mut(in_buf, buf_size as
usize) };
+
+ match rtc_write_handle(handle, in_buf) {
+ Ok(size) => size as i32,
+ Err(e) => {
+ error!("wasm_write_file: {:?}", e);
+ FFI_FILE_ERROR_WASM
+ }
+ }
+}
+
+/*
* uint c_close_file(int fd);
*/
#[allow(unused)]
@@ -416,3 +496,19 @@ extern "C" fn c_close_file(handle: c_int) -> c_uint {
}
}
}
+
+/*
+ * int teaclave_close_file(int fd);
+ */
+#[allow(unused)]
+#[no_mangle]
+pub extern "C" fn wasm_close_file(_exec_env: *const c_void, handle: c_int) ->
c_int {
+ debug!("wasm_close_file");
+ match rtc_close_handle(handle) {
+ Ok(size) => FFI_OK as i32,
+ Err(e) => {
+ error!("wasm_close_file: {:?}", e);
+ FFI_FILE_ERROR_WASM
+ }
+ }
+}
diff --git a/executor/src/wamr.rs b/executor/src/wamr.rs
index b37bb3f..e1557d4 100644
--- a/executor/src/wamr.rs
+++ b/executor/src/wamr.rs
@@ -20,8 +20,12 @@ use std::prelude::v1::*;
use crate::context::reset_thread_context;
use crate::context::set_thread_context;
use crate::context::Context;
+use crate::context::{
+ wasm_close_file, wasm_create_output, wasm_open_input, wasm_read_file,
wasm_write_file,
+};
-use std::ffi::{c_void, CString};
+use std::ffi::{c_void, CStr, CString};
+use std::os::raw::{c_char, c_int};
use teaclave_types::{FunctionArguments, FunctionRuntime, TeaclaveExecutor};
@@ -29,6 +33,15 @@ const DEFAULT_HEAP_SIZE: u32 = 8092;
const DEFAULT_STACK_SIZE: u32 = 8092;
const DEFAULT_ERROR_BUF_SIZE: usize = 128;
+#[repr(C)]
+#[derive(Debug)]
+struct NativeSymbol {
+ symbol: *const c_char,
+ func_ptr: *const c_void,
+ signature: *const c_char,
+ attachment: *const c_void,
+}
+
extern "C" {
fn wasm_runtime_init() -> bool;
@@ -50,7 +63,7 @@ extern "C" {
fn wasm_runtime_lookup_function(
module_inst: *const c_void,
- name: *const i8,
+ name: *const c_char,
signature: *const u8,
) -> *const c_void;
@@ -66,6 +79,15 @@ extern "C" {
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);
+
+ fn wasm_runtime_register_natives(
+ module_name: *const c_char,
+ native_symbols: *const NativeSymbol,
+ n_native_symbols: u32,
+ ) -> bool;
+
+ fn wasm_runtime_get_exception(module_inst: *const c_void) -> *const c_char;
+
}
#[derive(Default)]
@@ -87,6 +109,51 @@ impl TeaclaveExecutor for WAMicroRuntime {
set_thread_context(Context::new(runtime))?;
unsafe { wasm_runtime_init() };
+
+ // export native function
+
+ let export_symbols: [NativeSymbol; 5] = [
+ NativeSymbol {
+ symbol: b"teaclave_open_input\0".as_ptr() as _,
+ func_ptr: wasm_open_input as *const c_void,
+ signature: b"($)i\0".as_ptr() as _,
+ attachment: std::ptr::null(),
+ },
+ NativeSymbol {
+ symbol: b"teaclave_create_output\0".as_ptr() as _,
+ func_ptr: wasm_create_output as *const c_void,
+ signature: b"($)i\0".as_ptr() as _,
+ attachment: std::ptr::null(),
+ },
+ NativeSymbol {
+ symbol: b"teaclave_read_file\0".as_ptr() as _,
+ func_ptr: wasm_read_file as *const c_void,
+ signature: b"(i*~)i\0".as_ptr() as _,
+ attachment: std::ptr::null(),
+ },
+ NativeSymbol {
+ symbol: b"teaclave_write_file\0".as_ptr() as _,
+ func_ptr: wasm_write_file as *const c_void,
+ signature: b"(i*~)i\0".as_ptr() as _,
+ attachment: std::ptr::null(),
+ },
+ NativeSymbol {
+ symbol: b"teaclave_close_file\0".as_ptr() as _,
+ func_ptr: wasm_close_file as *const c_void,
+ signature: b"(i)i\0".as_ptr() as _,
+ attachment: std::ptr::null(),
+ },
+ ];
+
+ let register_succeeded = unsafe {
+ wasm_runtime_register_natives(
+ b"env\0".as_ptr() as _,
+ export_symbols.as_ptr(),
+ export_symbols.len() as u32,
+ )
+ };
+ assert!(register_succeeded);
+
let module = unsafe {
wasm_runtime_load(
payload.as_ptr(),
@@ -111,7 +178,11 @@ impl TeaclaveExecutor for WAMicroRuntime {
assert!((module_instance as usize) != 0);
let entry_func = unsafe {
- wasm_runtime_lookup_function(module_instance, entry_name.as_ptr(),
std::ptr::null())
+ wasm_runtime_lookup_function(
+ module_instance,
+ entry_name.as_ptr() as _,
+ std::ptr::null(),
+ )
};
assert!((entry_func as usize) != 0);
@@ -144,20 +215,27 @@ impl TeaclaveExecutor for WAMicroRuntime {
};
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()?;
+ let result =
+ unsafe { wasm_runtime_call_wasm(exec_env, entry_func, wasm_argc,
wasm_argv.as_ptr()) };
+ reset_thread_context()?;
+
+ // 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) };
+
+ if result {
+ let rv = wasm_argv[0] as c_int;
log::debug!(
"IN WAMicroRuntime::execute after `wasm_runtime_call_wasm`,
{:?}",
- wasm_argv[0]
+ rv
);
- // 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())
+ Ok(rv.to_string())
} else {
- Ok("WAMR Error".to_string())
+ let error = unsafe {
CStr::from_ptr(wasm_runtime_get_exception(module_instance)) };
+ log::debug!("WAMR ERROR: {:?}", error);
+ Ok(error.to_str().unwrap().to_string())
}
}
}
@@ -166,6 +244,8 @@ impl TeaclaveExecutor for WAMicroRuntime {
pub mod tests {
use super::*;
use std::collections::HashMap;
+ use std::untrusted::fs;
+ use teaclave_crypto::*;
use teaclave_runtime::*;
use teaclave_test_utils::*;
use teaclave_types::*;
@@ -177,17 +257,30 @@ pub mod tests {
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());
+ args.insert("input_file_id1".to_string(), "pf_in_a".to_string());
+ args.insert("input_file_id2".to_string(), "pf_in_b".to_string());
+ args.insert("output_file_id".to_string(), "pf_out".to_string());
let args = FunctionArguments::from(args);
let wa_payload =
-
include_bytes!("../../examples/python/wasm_simple_add_payload/simple_add.wasm");
+
include_bytes!("../../examples/python/wasm_teaclave_pf_payload/teaclave_pf.wasm");
let wa_payload = wa_payload.to_vec();
-
- let input_files = StagedFiles::default();
- let output_files = StagedFiles::default();
+ let input_a = "fixtures/functions/wamr/input_a.txt";
+ let input_b = "fixtures/functions/wamr/input_b.txt";
+ let output = "fixtures/functions/wamr/output.txt";
+ let expected_output = "fixtures/functions/wamr/expected_output.txt";
+
+ let input_a_info =
+ StagedFileInfo::new(input_a, TeaclaveFile128Key::random(),
FileAuthTag::mock());
+ let input_b_info =
+ StagedFileInfo::new(input_b, TeaclaveFile128Key::random(),
FileAuthTag::mock());
+ let output_info =
+ StagedFileInfo::new(output, TeaclaveFile128Key::random(),
FileAuthTag::mock());
+
+ let input_files =
+ StagedFiles::new(hashmap!("pf_in_a" => input_a_info, "pf_in_b" =>
input_b_info));
+ let output_files = StagedFiles::new(hashmap!("pf_out" => output_info));
let runtime = Box::new(RawIoRuntime::new(input_files, output_files));
@@ -198,5 +291,9 @@ pub mod tests {
log::debug!("IN TEST test_wamr: AFTER execution, summary: {:?}",
summary);
assert_eq!(summary, "7");
+
+ let output = fs::read_to_string(&output).unwrap();
+ let expected = fs::read_to_string(&expected_output).unwrap();
+ assert_eq!(&output[..], &expected[..]);
}
}
diff --git a/tests/fixtures/functions/wamr/expected_output.txt
b/tests/fixtures/functions/wamr/expected_output.txt
new file mode 100644
index 0000000..127068f
--- /dev/null
+++ b/tests/fixtures/functions/wamr/expected_output.txt
@@ -0,0 +1 @@
+pf_in_a
\ No newline at end of file
diff --git a/tests/fixtures/functions/wamr/input_a.txt
b/tests/fixtures/functions/wamr/input_a.txt
new file mode 100644
index 0000000..858e289
--- /dev/null
+++ b/tests/fixtures/functions/wamr/input_a.txt
@@ -0,0 +1 @@
+4211037
\ No newline at end of file
diff --git a/tests/fixtures/functions/wamr/input_b.txt
b/tests/fixtures/functions/wamr/input_b.txt
new file mode 100644
index 0000000..5a2c471
--- /dev/null
+++ b/tests/fixtures/functions/wamr/input_b.txt
@@ -0,0 +1 @@
+1008611
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]