From 73b4f8b08c45acf0e7956f40b93b6be30bc6928c Mon Sep 17 00:00:00 2001 From: "Hui, Chunyang" Date: Wed, 27 May 2020 05:44:10 +0000 Subject: [PATCH] Add support for PAL API v2 --- demos/embedded_mode/bench_driver/main.c | 38 ++++++-- .../embedded_mode/trusted_memcpy_bench/main.c | 16 ++-- src/exec/src/server.rs | 78 ++++++++++------ src/pal/include/occlum_pal_api.h | 92 +++++++++++++++---- src/pal/pal.lds | 1 + src/pal/src/pal_api.c | 41 ++++++--- src/run/main.c | 19 +++- 7 files changed, 211 insertions(+), 74 deletions(-) diff --git a/demos/embedded_mode/bench_driver/main.c b/demos/embedded_mode/bench_driver/main.c index e9d73d78..626b5722 100644 --- a/demos/embedded_mode/bench_driver/main.c +++ b/demos/embedded_mode/bench_driver/main.c @@ -1,6 +1,7 @@ #include #include #include +#include #include //============================================================================ @@ -23,7 +24,7 @@ "The embedded mode makes it possible to build Occlum-based SGX apps " \ "that comprise of trusted and untrused halves.\n" -static void print_help_msg(const char* prog_name) { +static void print_help_msg(const char *prog_name) { fprintf(stderr, HELP_MSG, prog_name, prog_name); } @@ -31,15 +32,15 @@ static void print_help_msg(const char* prog_name) { // Main //============================================================================ -int main(int argc, char* argv[]) { +int main(int argc, char *argv[]) { // Parse arguments - const char* prog_name = (const char*)argv[0]; + const char *prog_name = (const char *)argv[0]; if (argc < 2) { fprintf(stderr, "error: require one argument\n\n"); print_help_msg(prog_name); return EXIT_FAILURE; } - const char* total_bytes_str = argv[1]; + const char *total_bytes_str = argv[1]; // Init Occlum PAL occlum_pal_attr_t pal_attr = OCCLUM_PAL_ATTR_INITVAL; @@ -52,21 +53,44 @@ int main(int argc, char* argv[]) { char shared_buf[1024 * 1024] = {0}; // Prepare cmd path and arguments - const char* cmd_path = "/bin/trusted_memcpy_bench"; + const char *cmd_path = "/bin/trusted_memcpy_bench"; char buf_ptr_str[32] = {0}; char buf_size_str[32] = {0}; snprintf(buf_ptr_str, sizeof buf_ptr_str, "%lu", (unsigned long) shared_buf); snprintf(buf_size_str, sizeof buf_size_str, "%lu", sizeof shared_buf); - const char* cmd_args[] = { + const char *cmd_args[] = { buf_ptr_str, // buf_ptr buf_size_str, // buf_size total_bytes_str, // total_bytes NULL }; + struct occlum_stdio_fds io_fds = { + .stdin_fd = STDIN_FILENO, + .stdout_fd = STDOUT_FILENO, + .stderr_fd = STDERR_FILENO, + }; + + // Use Occlum PAL to create new process + int libos_tid = 0; + struct occlum_pal_create_process_args create_process_args = { + .path = cmd_path, + .argv = cmd_args, + .env = NULL, + .stdio = (const struct occlum_stdio_fds *) &io_fds, + .pid = &libos_tid, + }; + if (occlum_pal_create_process(&create_process_args) < 0) { + return EXIT_FAILURE; + } + // Use Occlum PAL to execute the cmd int exit_status = 0; - if (occlum_pal_exec(cmd_path, cmd_args, NULL, &exit_status) < 0) { + struct occlum_pal_exec_args exec_args = { + .pid = libos_tid, + .exit_value = &exit_status, + }; + if (occlum_pal_exec(&exec_args) < 0) { return EXIT_FAILURE; } diff --git a/demos/embedded_mode/trusted_memcpy_bench/main.c b/demos/embedded_mode/trusted_memcpy_bench/main.c index 578cdc66..47bfc5a8 100644 --- a/demos/embedded_mode/trusted_memcpy_bench/main.c +++ b/demos/embedded_mode/trusted_memcpy_bench/main.c @@ -15,7 +15,7 @@ " The size of the untrusted buffer\n" \ " The total number of bytes to copy from the buffer into the enclave\n" -static void print_help_msg(const char* prog_name) { +static void print_help_msg(const char *prog_name) { fprintf(stderr, HELP_MSG, prog_name); } @@ -25,8 +25,8 @@ static void print_help_msg(const char* prog_name) { #define MIN(x, y) ((x) <= (y) ? (x) : (y)) -static int copy_into_enclave(const char* src_buf, size_t buf_size, size_t total_bytes) { - char* dst_buf = malloc(buf_size); +static int copy_into_enclave(const char *src_buf, size_t buf_size, size_t total_bytes) { + char *dst_buf = malloc(buf_size); if (dst_buf == NULL) { fprintf(stderr, "ERROR: out of memory"); return -1; @@ -46,14 +46,14 @@ static int copy_into_enclave(const char* src_buf, size_t buf_size, size_t total_ // Main //============================================================================ -int main(int argc, char* argv[]) { +int main(int argc, char *argv[]) { // Parse arguments - const char* prog_name = argv[0]; + const char *prog_name = argv[0]; if (argc < 4) { print_help_msg(prog_name); return EXIT_FAILURE; } - const char* buf_ptr = (const char*) strtoul(argv[1], NULL, 10); + const char *buf_ptr = (const char *) strtoul(argv[1], NULL, 10); size_t buf_size = (size_t) strtoul(argv[2], NULL, 10); size_t total_bytes = (size_t) strtoul(argv[3], NULL, 10); if (buf_ptr == NULL || buf_size == 0 || total_bytes == 0) { @@ -63,7 +63,7 @@ int main(int argc, char* argv[]) { // Benchmark memcpy from outside the enclave to inside the enclave printf("Start copying data from the given buffer (ptr = %p, len = %lu) for a total of %lu bytes...\n", - buf_ptr, buf_size, total_bytes); + buf_ptr, buf_size, total_bytes); // Time begin struct timeval time_begin, time_end; @@ -79,7 +79,7 @@ int main(int argc, char* argv[]) { // Calculate the throughput unsigned long elapsed_us = (time_end.tv_sec - time_begin.tv_sec) * 1000000 - + (time_end.tv_usec - time_begin.tv_usec); + + (time_end.tv_usec - time_begin.tv_usec); if (elapsed_us == 0) { fprintf(stderr, "ERROR: elapsed time (in us) cannot be zero"); print_help_msg(prog_name); diff --git a/src/exec/src/server.rs b/src/exec/src/server.rs index 7040656d..03bccff9 100644 --- a/src/exec/src/server.rs +++ b/src/exec/src/server.rs @@ -318,29 +318,45 @@ pub struct occlum_stdio_fds { pub stderr_fd: i32, } +/* + * The struct which consists of arguments needed by occlum_pal_create_process + */ +#[repr(C)] +pub struct occlum_pal_create_process_args { + pub path: *const libc::c_char, + pub argv: *const *const libc::c_char, + pub env: *const *const libc::c_char, + pub stdio: *const occlum_stdio_fds, + pub pid: *mut i32, +} + +/* + * The struct which consists of arguments needed by occlum_pal_exec + */ +#[repr(C)] +pub struct occlum_pal_exec_args { + pub pid: i32, + pub exit_value: *mut i32, +} + extern "C" { /* - * @brief Execute a command inside the Occlum enclave + * @brief Create a new process inside the Occlum enclave * - * @param cmd_path The path of the command to be executed - * @param cmd_args The arguments to the command. The array must be NULL - * terminated. - * @param io_fds The file descriptors of the redirected standard I/O - * (i.e., stdin, stdout, stderr), If set to NULL, will - * use the original standard I/O file descriptors. - * @param exit_status Output. The exit status of the command. Note that the - * exit status is returned if and only if the function - * succeeds. + * @param args Mandatory input. Arguments for occlum_pal_create_process. * * @retval If 0, then success; otherwise, check errno for the exact error type. */ - fn occlum_pal_exec( - cmd_path: *const libc::c_char, - cmd_args: *const *const libc::c_char, - cmd_env: *const *const libc::c_char, - io_fds: *const occlum_stdio_fds, - exit_status: *mut i32, - ) -> i32; + fn occlum_pal_create_process(args: *mut occlum_pal_create_process_args) -> i32; + + /* + * @brief Execute the process inside the Occlum enclave + * + * @param args Mandatory input. Arguments for occlum_pal_exec. + * + * @retval If 0, then success; otherwise, check errno for the exact error type. + */ + fn occlum_pal_exec(args: *mut occlum_pal_exec_args) -> i32; /* * @brief Send a signal to one or multiple LibOS processes @@ -381,16 +397,26 @@ fn rust_occlum_pal_exec( let (cmd_envs_array, _cmd_envs) = vec_strings_to_cchars(envs)?; let stdio_raw = Box::new(stdio); + let mut libos_tid = 0; + let create_process_args = Box::new(occlum_pal_create_process_args { + path: cmd_path.as_ptr() as *const libc::c_char, + argv: Box::into_raw(cmd_args_array.into_boxed_slice()) as *const *const libc::c_char, + env: Box::into_raw(cmd_envs_array.into_boxed_slice()) as *const *const libc::c_char, + stdio: *stdio_raw, + pid: &mut libos_tid as *mut i32, + }); - let ret = unsafe { - occlum_pal_exec( - cmd_path.as_ptr() as *const libc::c_char, - Box::into_raw(cmd_args_array.into_boxed_slice()) as *const *const libc::c_char, - Box::into_raw(cmd_envs_array.into_boxed_slice()) as *const *const libc::c_char, - *stdio_raw, - exit_status as *mut i32, - ) - }; + let ret = unsafe{occlum_pal_create_process(Box::into_raw(create_process_args))}; + if ret != 0 { + return Err(ret); + } + + let exec_args = Box::new(occlum_pal_exec_args { + pid: libos_tid, + exit_value: exit_status as *mut i32, + }); + + let ret = unsafe {occlum_pal_exec(Box::into_raw(exec_args))}; match ret { 0 => Ok(()), diff --git a/src/pal/include/occlum_pal_api.h b/src/pal/include/occlum_pal_api.h index 6395b687..46c9e5a2 100644 --- a/src/pal/include/occlum_pal_api.h +++ b/src/pal/include/occlum_pal_api.h @@ -54,6 +54,67 @@ typedef struct occlum_stdio_fds { int stderr_fd; } occlum_stdio_fds_t; +/* + * The struct which consists of arguments needed by occlum_pal_create_process + */ +struct occlum_pal_create_process_args { + + // Path to new process. + // + // The path of the command which will be created as a new process. + // + // Mandatory field. Must not be NULL. + const char *path; + + // Argments array pass to new process. + // + // The arguments to the command. The array must be NULL terminated. + // + // Mandatory field. Must not be NULL. + const char **argv; + + // Untrusted environment variable array pass to new process. + // + // The untrusted env vars to the command. The array must be NULL terminated. + // + // Optional field. + const char **env; + + // File descriptors of the redirected standard I/O (i.e., stdin, stdout, stderr) + // + // If set to NULL, will use the original standard I/O file descriptors. + // + // Optional field. + const struct occlum_stdio_fds *stdio; + + // Output. Pid of new process in libos. + // + // If occlum_pal_create_process returns success, pid of the new process will + // be updated. + // + // Mandatory field. Must not be NULL. + int *pid; +}; + +/* + * The struct which consists of arguments needed by occlum_pal_exec + */ +struct occlum_pal_exec_args { + // Pid of new process created with occlum_pal_create_process. + // + // Mandatory field. + int pid; + + // Output. The exit status of the command. The semantic of + // this value follows the one described in wait(2) man + // page. For example, if the program terminated normally, + // then WEXITSTATUS(exit_status) gives the value returned + // from a main function. + // + // Mandatory field. Must not be NULL. + int *exit_value; +}; + /* * @brief Initialize an Occlum enclave * @@ -64,29 +125,22 @@ typedef struct occlum_stdio_fds { int occlum_pal_init(const struct occlum_pal_attr *attr); /* - * @brief Execute a command inside the Occlum enclave + * @brief Create a new process inside the Occlum enclave * - * @param cmd_path The path of the command to be executed - * @param cmd_args The arguments to the command. The array must be NULL - * terminated. - * @param cmd_env The untrusted env vars to the command. The array must - * be NULL terminated. - * @param io_fds The file descriptors of the redirected standard I/O - * (i.e., stdin, stdout, stderr), If set to NULL, will - * use the original standard I/O file descriptors. - * @param exit_status Output. The exit status of the command. The semantic of - * this value follows the one described in wait(2) man - * page. For example, if the program terminated normally, - * then WEXITSTATUS(exit_status) gives the value returned - * from a main function. + * @param args Mandatory input. Arguments for occlum_pal_create_process. * * @retval If 0, then success; otherwise, check errno for the exact error type. */ -int occlum_pal_exec(const char *cmd_path, - const char **cmd_args, - const char **cmd_env, - const struct occlum_stdio_fds *io_fds, - int *exit_status); +int occlum_pal_create_process(struct occlum_pal_create_process_args *args); + +/* + * @brief Execute the process inside the Occlum enclave + * + * @param args Mandatory input. Arguments for occlum_pal_exec. + * + * @retval If 0, then success; otherwise, check errno for the exact error type. + */ +int occlum_pal_exec(struct occlum_pal_exec_args *args); /* * @brief Send a signal to one or multiple LibOS processes diff --git a/src/pal/pal.lds b/src/pal/pal.lds index f54cfdd5..7ee33d5e 100644 --- a/src/pal/pal.lds +++ b/src/pal/pal.lds @@ -2,6 +2,7 @@ global: occlum_pal_get_version; occlum_pal_init; + occlum_pal_create_process; occlum_pal_exec; occlum_pal_kill; occlum_pal_destroy; diff --git a/src/pal/src/pal_api.c b/src/pal/src/pal_api.c index 39a27ced..4fc05a39 100644 --- a/src/pal/src/pal_api.c +++ b/src/pal/src/pal_api.c @@ -50,14 +50,11 @@ int occlum_pal_init(const struct occlum_pal_attr *attr) { return 0; } -int occlum_pal_exec(const char *cmd_path, - const char **cmd_args, - const char **cmd_env, - const struct occlum_stdio_fds *io_fds, - int *exit_status) { - errno = 0; +int occlum_pal_create_process(struct occlum_pal_create_process_args *args) { + int ecall_ret = 0; // libos_tid - if (cmd_path == NULL || cmd_args == NULL || exit_status == NULL) { + errno = 0; + if (args->path == NULL || args->argv == NULL || args->pid == NULL) { errno = EINVAL; return -1; } @@ -69,9 +66,8 @@ int occlum_pal_exec(const char *cmd_path, return -1; } - int ecall_ret = 0; // libos_tid - sgx_status_t ecall_status = occlum_ecall_new_process(eid, &ecall_ret, cmd_path, cmd_args, - cmd_env, io_fds); + sgx_status_t ecall_status = occlum_ecall_new_process(eid, &ecall_ret, args->path, + args->argv, args->env, args->stdio); if (ecall_status != SGX_SUCCESS) { const char *sgx_err = pal_get_sgx_error_msg(ecall_status); PAL_ERROR("Failed to do ECall: %s", sgx_err); @@ -83,9 +79,28 @@ int occlum_pal_exec(const char *cmd_path, return -1; } - int libos_tid = ecall_ret; + *args->pid = ecall_ret; + return 0; +} + +int occlum_pal_exec(struct occlum_pal_exec_args *args) { int host_tid = gettid(); - ecall_status = occlum_ecall_exec_thread(eid, &ecall_ret, libos_tid, host_tid); + int ecall_ret = 0; + + if (args->exit_value == NULL) { + errno = EINVAL; + return -1; + } + + sgx_enclave_id_t eid = pal_get_enclave_id(); + if (eid == SGX_INVALID_ENCLAVE_ID) { + PAL_ERROR("Enclave is not initialized yet."); + errno = ENOENT; + return -1; + } + + sgx_status_t ecall_status = occlum_ecall_exec_thread(eid, &ecall_ret, args->pid, + host_tid); if (ecall_status != SGX_SUCCESS) { const char *sgx_err = pal_get_sgx_error_msg(ecall_status); PAL_ERROR("Failed to do ECall: %s", sgx_err); @@ -97,7 +112,7 @@ int occlum_pal_exec(const char *cmd_path, return -1; } - *exit_status = ecall_ret; + *args->exit_value = ecall_ret; return 0; } diff --git a/src/run/main.c b/src/run/main.c index 937ce0cd..f9794eb0 100644 --- a/src/run/main.c +++ b/src/run/main.c @@ -47,7 +47,24 @@ int main(int argc, char *argv[]) { .stderr_fd = STDERR_FILENO, }; int exit_status = 0; - if (occlum_pal_exec(cmd_path, cmd_args, environ, &io_fds, &exit_status) < 0) { + int libos_tid = 0; + struct occlum_pal_create_process_args create_process_args = { + .path = cmd_path, + .argv = cmd_args, + .env = environ, + .stdio = (const struct occlum_stdio_fds *) &io_fds, + .pid = &libos_tid, + }; + if (occlum_pal_create_process(&create_process_args) < 0) { + // Command not found or other internal errors + return 127; + } + + struct occlum_pal_exec_args exec_args = { + .pid = libos_tid, + .exit_value = &exit_status, + }; + if (occlum_pal_exec(&exec_args) < 0) { // Command not found or other internal errors return 127; }