Support environmental variables in Occlum.json
1. Now we support set App's env in Occlum.json, for example: "env": [ "OCCLUM=yes", "TEST=true" ] 2. Rewrite env test cases 3. Update Dockerfile to install "jq" tool
This commit is contained in:
parent
f37eb34038
commit
8ef52c7c2d
@ -1,5 +1,6 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::ffi::CString;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sgxfs::SgxFile;
|
use std::sgxfs::SgxFile;
|
||||||
|
|
||||||
@ -96,6 +97,7 @@ fn parse_mac(mac_str: &str) -> Result<sgx_aes_gcm_128bit_tag_t, Error> {
|
|||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub vm: ConfigVM,
|
pub vm: ConfigVM,
|
||||||
pub process: ConfigProcess,
|
pub process: ConfigProcess,
|
||||||
|
pub env: Vec<CString>,
|
||||||
pub mount: Vec<ConfigMount>,
|
pub mount: Vec<ConfigMount>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,6 +139,13 @@ impl Config {
|
|||||||
fn from_input(input: &InputConfig) -> Result<Config, Error> {
|
fn from_input(input: &InputConfig) -> Result<Config, Error> {
|
||||||
let vm = ConfigVM::from_input(&input.vm)?;
|
let vm = ConfigVM::from_input(&input.vm)?;
|
||||||
let process = ConfigProcess::from_input(&input.process)?;
|
let process = ConfigProcess::from_input(&input.process)?;
|
||||||
|
let env = {
|
||||||
|
let mut env = Vec::new();
|
||||||
|
for input_env in &input.env {
|
||||||
|
env.push(CString::new(input_env.clone())?);
|
||||||
|
}
|
||||||
|
env
|
||||||
|
};
|
||||||
let mount = {
|
let mount = {
|
||||||
let mut mount = Vec::new();
|
let mut mount = Vec::new();
|
||||||
for input_mount in &input.mount {
|
for input_mount in &input.mount {
|
||||||
@ -144,7 +153,12 @@ impl Config {
|
|||||||
}
|
}
|
||||||
mount
|
mount
|
||||||
};
|
};
|
||||||
Ok(Config { vm, process, mount })
|
Ok(Config {
|
||||||
|
vm,
|
||||||
|
process,
|
||||||
|
env,
|
||||||
|
mount,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,6 +262,8 @@ struct InputConfig {
|
|||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub process: InputConfigProcess,
|
pub process: InputConfigProcess,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
pub env: Vec<String>,
|
||||||
|
#[serde(default)]
|
||||||
pub mount: Vec<InputConfigMount>,
|
pub mount: Vec<InputConfigMount>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,11 +76,10 @@ fn do_boot(path_str: &str, argv: &Vec<CString>) -> Result<(), Error> {
|
|||||||
// info!("boot: path: {:?}, argv: {:?}", path_str, argv);
|
// info!("boot: path: {:?}, argv: {:?}", path_str, argv);
|
||||||
util::mpx_util::mpx_enable()?;
|
util::mpx_util::mpx_enable()?;
|
||||||
|
|
||||||
// The default environment variables
|
let envp = &config::LIBOS_CONFIG.env;
|
||||||
let envp = vec![CString::new("OCCLUM=yes").unwrap()];
|
|
||||||
let file_actions = Vec::new();
|
let file_actions = Vec::new();
|
||||||
let parent = &process::IDLE_PROCESS;
|
let parent = &process::IDLE_PROCESS;
|
||||||
process::do_spawn(&path_str, argv, &envp, &file_actions, parent)?;
|
process::do_spawn(&path_str, argv, envp, &file_actions, parent)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use prelude::*;
|
use prelude::*;
|
||||||
use std::{convert, error, fmt};
|
use std::{convert, error, ffi, fmt};
|
||||||
|
|
||||||
// TODO: remove errno.h
|
// TODO: remove errno.h
|
||||||
|
|
||||||
@ -31,6 +31,12 @@ impl convert::From<std::io::Error> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl convert::From<std::ffi::NulError> for Error {
|
||||||
|
fn from(info: std::ffi::NulError) -> Error {
|
||||||
|
Error::new(Errno::EINVAL, "std::ffi::NulError")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl error::Error for Error {
|
impl error::Error for Error {
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
self.desc
|
self.desc
|
||||||
|
@ -36,7 +36,7 @@ all: build
|
|||||||
build: prebuild $(BUILD_TARGETS) postbuild
|
build: prebuild $(BUILD_TARGETS) postbuild
|
||||||
|
|
||||||
prebuild:
|
prebuild:
|
||||||
@$(RM) -rf $(BUILD_DIR)/test/*
|
@$(RM) -rf $(BUILD_DIR)/test
|
||||||
@mkdir -p $(BUILD_DIR)/test
|
@mkdir -p $(BUILD_DIR)/test
|
||||||
@cd $(BUILD_DIR)/test && \
|
@cd $(BUILD_DIR)/test && \
|
||||||
$(PROJECT_DIR)/build/bin/occlum init
|
$(PROJECT_DIR)/build/bin/occlum init
|
||||||
@ -86,4 +86,4 @@ $(BENCH_TARGETS): bench-%: %
|
|||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@$(RM) -rf $(BUILD_DIR)/test/*
|
@$(RM) -rf $(BUILD_DIR)/test
|
||||||
|
@ -7,6 +7,10 @@
|
|||||||
"default_heap_size": "16MB",
|
"default_heap_size": "16MB",
|
||||||
"default_mmap_size": "32MB"
|
"default_mmap_size": "32MB"
|
||||||
},
|
},
|
||||||
|
"env": [
|
||||||
|
"OCCLUM=yes",
|
||||||
|
"TEST=true"
|
||||||
|
],
|
||||||
"mount": [
|
"mount": [
|
||||||
{
|
{
|
||||||
"target": "/",
|
"target": "/",
|
||||||
|
8
test/env/Makefile
vendored
8
test/env/Makefile
vendored
@ -6,9 +6,9 @@ ARG2 := arg2
|
|||||||
ARG3 := this is a string with spaces
|
ARG3 := this is a string with spaces
|
||||||
|
|
||||||
EXTRA_C_FLAGS := \
|
EXTRA_C_FLAGS := \
|
||||||
-DEXPECTED_ARGC=$(ARGC) \
|
-DEXPECT_ARGC=$(ARGC) \
|
||||||
-DEXPECTED_ARG1="\"$(ARG1)\"" \
|
-DEXPECT_ARG1="\"$(ARG1)\"" \
|
||||||
-DEXPECTED_ARG2="\"$(ARG2)\"" \
|
-DEXPECT_ARG2="\"$(ARG2)\"" \
|
||||||
-DEXPECTED_ARG3="\"$(ARG3)\""
|
-DEXPECT_ARG3="\"$(ARG3)\""
|
||||||
EXTRA_LINK_FLAGS :=
|
EXTRA_LINK_FLAGS :=
|
||||||
BIN_ARGS := "$(ARG1)" "$(ARG2)" "$(ARG3)"
|
BIN_ARGS := "$(ARG1)" "$(ARG2)" "$(ARG3)"
|
||||||
|
200
test/env/main.c
vendored
200
test/env/main.c
vendored
@ -2,56 +2,200 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <spawn.h>
|
||||||
#include <sys/auxv.h>
|
#include <sys/auxv.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Helper structs & variables & functions
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
const char** g_argv;
|
||||||
|
int g_argc;
|
||||||
|
|
||||||
// Expected arguments are given by Makefile throught macro ARGC, ARG1, ARG2 and
|
// Expected arguments are given by Makefile throught macro ARGC, ARG1, ARG2 and
|
||||||
// ARG3
|
// ARG3
|
||||||
const char* expected_argv[EXPECTED_ARGC] = {
|
const char* expect_argv[EXPECT_ARGC] = {
|
||||||
"env",
|
"env",
|
||||||
EXPECTED_ARG1,
|
EXPECT_ARG1,
|
||||||
EXPECTED_ARG2,
|
EXPECT_ARG2,
|
||||||
EXPECTED_ARG3,
|
EXPECT_ARG3,
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
// Expected child arguments
|
||||||
// Test argc
|
const int child_argc = 2;
|
||||||
if (argc != EXPECTED_ARGC) {
|
const char* child_argv[child_argc + 1] = {
|
||||||
printf("ERROR: expect %d arguments, but %d are given\n", EXPECTED_ARGC, argc);
|
"env",
|
||||||
return -1;
|
"child",
|
||||||
}
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
// Test argv
|
// Expected child environment variables
|
||||||
for (int arg_i = 0; arg_i < argc; arg_i++) {
|
const char* child_envp[] = {
|
||||||
printf("arg[%d] = %s\n", arg_i, argv[arg_i]);
|
"ENV_CHILD=ok",
|
||||||
const char* actual_arg = argv[arg_i];
|
NULL
|
||||||
const char* expected_arg = expected_argv[arg_i];
|
};
|
||||||
if (strcmp(actual_arg, expected_arg) != 0) {
|
|
||||||
|
static int test_argv_val(const char** expect_argv) {
|
||||||
|
for (int arg_i = 0; arg_i < g_argc; arg_i++) {
|
||||||
|
const char* actual_arg = *(g_argv + arg_i);
|
||||||
|
const char* expect_arg = *(expect_argv + arg_i);
|
||||||
|
if (strcmp(actual_arg, expect_arg) != 0) {
|
||||||
printf("ERROR: expect argument %d is %s, but given %s\n",
|
printf("ERROR: expect argument %d is %s, but given %s\n",
|
||||||
arg_i, expected_arg, actual_arg);
|
arg_i, expect_arg, actual_arg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Test envp
|
static int test_env_val(const char* expect_env_key, const char* expect_env_val) {
|
||||||
// Occlum LibOS by default passes an environment OCCLUM=yes
|
const char* actual_env_val = getenv(expect_env_key);
|
||||||
const char* env_val = getenv("OCCLUM");
|
if (actual_env_val == NULL) {
|
||||||
if (env_val == 0) {
|
printf("ERROR: cannot find %s\n", expect_env_key);
|
||||||
printf("ERROR: cannot find environment variable OCCLUM\n");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else if (strcmp(env_val, "yes") != 0) {
|
if (strcmp(actual_env_val, expect_env_val) != 0) {
|
||||||
printf("ERROR: environment variable OCCLUM=yes expected, but given %s\n",
|
printf("ERROR: environment variable %s=%s expected, but given %s\n",
|
||||||
env_val);
|
expect_env_key, expect_env_val, actual_env_val);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Test aux
|
// ============================================================================
|
||||||
|
// Test cases for argv
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static int test_env_getargv() {
|
||||||
|
// Test argc
|
||||||
|
if (g_argc != EXPECT_ARGC) {
|
||||||
|
printf("ERROR: expect %d arguments, but %d are given\n", EXPECT_ARGC, g_argc);
|
||||||
|
throw_error("arguments count is not expected");
|
||||||
|
}
|
||||||
|
// Test argv
|
||||||
|
if (test_argv_val(expect_argv) < 0) {
|
||||||
|
throw_error("argument variables are not expected");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Test cases for aux
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static int test_env_getauxval() {
|
||||||
unsigned long page_size = getauxval(AT_PAGESZ);
|
unsigned long page_size = getauxval(AT_PAGESZ);
|
||||||
if (errno != 0 || page_size != 4096) {
|
if (errno != 0 || page_size != 4096) {
|
||||||
printf("ERROR: auxilary vector does not pass correct the value\n");
|
throw_error("auxilary vector does not pass correct the value");
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Test cases for env
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
// The environment variables are specified in Occlum.json
|
||||||
|
static int test_env_getenv() {
|
||||||
|
if (test_env_val("OCCLUM", "yes") < 0) {
|
||||||
|
throw_error("get environment variable failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Here we call getenv() again to make sure that
|
||||||
|
// LibOS can handle several environment variables in Occlum.json correctly
|
||||||
|
if (test_env_val("TEST", "true") < 0) {
|
||||||
|
throw_error("get environment variable failed");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_env_set_child_env_and_argv() {
|
||||||
|
int status, child_pid;
|
||||||
|
int ret = posix_spawn(&child_pid,
|
||||||
|
"/bin/env", NULL, NULL,
|
||||||
|
(char *const *)child_argv,
|
||||||
|
(char *const *)child_envp);
|
||||||
|
if (ret < 0) {
|
||||||
|
throw_error("spawn process error");
|
||||||
|
}
|
||||||
|
printf("Spawn a child process with pid=%d\n", child_pid);
|
||||||
|
ret = wait4(-1, &status, 0, NULL);
|
||||||
|
if (ret < 0) {
|
||||||
|
throw_error("failed to wait4 the child process");
|
||||||
|
}
|
||||||
|
if (!WIFEXITED(status)) {
|
||||||
|
throw_error("test cases in child faild");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Child Test cases for argv
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static int test_env_child_getargv() {
|
||||||
|
// Test argc
|
||||||
|
if (g_argc != child_argc) {
|
||||||
|
printf("ERROR: expect %d arguments, but %d are given\n", child_argc, g_argc);
|
||||||
|
throw_error("arguments count is not expected");
|
||||||
|
}
|
||||||
|
// Test argv
|
||||||
|
if (test_argv_val(child_argv) < 0) {
|
||||||
|
throw_error("argument variables are not expected");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Child Test cases for env
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
#define ENV_SIZE (256)
|
||||||
|
static int test_env_child_getenv() {
|
||||||
|
char env_key[ENV_SIZE];
|
||||||
|
char env_val[ENV_SIZE];
|
||||||
|
for (int i = 0; child_envp[i] != NULL; ++i) {
|
||||||
|
int num = sscanf(child_envp[i], "%[^=]=%s", env_key, env_val);
|
||||||
|
if (num != 2) {
|
||||||
|
throw_error("parse environment variable failed");
|
||||||
|
}
|
||||||
|
if (test_env_val(env_key, env_val) < 0) {
|
||||||
|
throw_error("get environment variable failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Test suite main
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static test_case_t test_cases[] = {
|
||||||
|
TEST_CASE(test_env_getargv),
|
||||||
|
TEST_CASE(test_env_getauxval),
|
||||||
|
TEST_CASE(test_env_getenv),
|
||||||
|
TEST_CASE(test_env_set_child_env_and_argv),
|
||||||
|
};
|
||||||
|
|
||||||
|
static test_case_t child_test_cases[] = {
|
||||||
|
TEST_CASE(test_env_getauxval),
|
||||||
|
TEST_CASE(test_env_child_getargv),
|
||||||
|
TEST_CASE(test_env_child_getenv),
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, const char* argv[]) {
|
||||||
|
// Save argument for test cases
|
||||||
|
g_argc = argc;
|
||||||
|
g_argv = argv;
|
||||||
|
// Test argc
|
||||||
|
if (getpid() > 1) {
|
||||||
|
return test_suite_run(child_test_cases, ARRAY_SIZE(child_test_cases));
|
||||||
|
} else {
|
||||||
|
return test_suite_run(test_cases, ARRAY_SIZE(test_cases));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -37,7 +37,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int client_pid;
|
int client_pid;
|
||||||
char* client_argv[] = {"client", "127.0.0.1"};
|
char* client_argv[] = {"client", "127.0.0.1", NULL};
|
||||||
ret = posix_spawn(&client_pid, "/bin/client", NULL, NULL, client_argv, NULL);
|
ret = posix_spawn(&client_pid, "/bin/client", NULL, NULL, client_argv, NULL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
printf("spawn client process error: %s(errno: %d)\n", strerror(errno), errno);
|
printf("spawn client process error: %s(errno: %d)\n", strerror(errno), errno);
|
||||||
|
@ -65,7 +65,7 @@ main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
// spawn clients
|
// spawn clients
|
||||||
int client_pid;
|
int client_pid;
|
||||||
char* client_argv[] = {"client", "127.0.0.1"};
|
char* client_argv[] = {"client", "127.0.0.1", NULL};
|
||||||
for(int i=0; i<3; ++i) {
|
for(int i=0; i<3; ++i) {
|
||||||
int ret = posix_spawn(&client_pid, "/bin/client", NULL, NULL, client_argv, NULL);
|
int ret = posix_spawn(&client_pid, "/bin/client", NULL, NULL, client_argv, NULL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
@ -14,6 +14,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||||||
expect \
|
expect \
|
||||||
gdb \
|
gdb \
|
||||||
git-core \
|
git-core \
|
||||||
|
jq \
|
||||||
kmod \
|
kmod \
|
||||||
libboost-system-dev \
|
libboost-system-dev \
|
||||||
libboost-thread-dev \
|
libboost-thread-dev \
|
||||||
|
@ -103,7 +103,10 @@ cmd_build() {
|
|||||||
export OCCLUM_CONF_DEFAULT_MMAP_SIZE=`get_conf_default_mmap_size`
|
export OCCLUM_CONF_DEFAULT_MMAP_SIZE=`get_conf_default_mmap_size`
|
||||||
cd "$context_dir/build"
|
cd "$context_dir/build"
|
||||||
"$occlum_dir/build/bin/occlum-gen-default-occlum-json"\
|
"$occlum_dir/build/bin/occlum-gen-default-occlum-json"\
|
||||||
|
> "Occlum_new.json"
|
||||||
|
jq -s '.[0] + .[1]' "../../Occlum.json" "Occlum_new.json"\
|
||||||
> "Occlum.json"
|
> "Occlum.json"
|
||||||
|
rm -f "Occlum_new.json"
|
||||||
"$occlum_dir/build/bin/occlum-protect-integrity" protect Occlum.json
|
"$occlum_dir/build/bin/occlum-protect-integrity" protect Occlum.json
|
||||||
|
|
||||||
export OCCLUM_BUILTIN_CONF_FILE_MAC=`get_occlum_conf_file_mac`
|
export OCCLUM_BUILTIN_CONF_FILE_MAC=`get_occlum_conf_file_mac`
|
||||||
|
Loading…
Reference in New Issue
Block a user