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]

Reply via email to