occlum/test/env/main.c
Hui, Chunyang c14ee62678 Add untrusted environment variable override
Add "untrusted" sections for environment variables defined in Occlum.json. Environment
variable defined in "default" will be shown in libos directly. Environment variable
defined in "untrusted" can be passed from occlum run or PAL layer and can override
the value in "default" and thus is considered "untrusted".
2020-05-25 03:14:54 +00:00

218 lines
6.6 KiB
C

#include <string.h>
#include <stdio.h>
#include <elf.h>
#include <errno.h>
#include <spawn.h>
#include <sys/auxv.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
// ARG3
const char* expect_argv[EXPECT_ARGC] = {
"env",
EXPECT_ARG1,
EXPECT_ARG2,
EXPECT_ARG3,
};
// Expected child arguments
const int child_argc = 2;
const char* child_argv[3] = {
"env",
"child",
NULL
};
// Expected child environment variables
const char* child_envp[] = {
"ENV_CHILD=ok",
NULL
};
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",
arg_i, expect_arg, actual_arg);
return -1;
}
}
return 0;
}
static int test_env_val(const char* expect_env_key, const char* expect_env_val) {
const char* actual_env_val = getenv(expect_env_key);
if (actual_env_val == NULL) {
printf("ERROR: cannot find %s\n", expect_env_key);
return -1;
}
if (strcmp(actual_env_val, expect_env_val) != 0) {
printf("ERROR: environment variable %s=%s expected, but given %s\n",
expect_env_key, expect_env_val, actual_env_val);
return -1;
}
return 0;
}
// ============================================================================
// 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);
if (errno != 0 || page_size != 4096) {
THROW_ERROR("auxilary vector does not pass correct the value");
}
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
// TEST is set as untrusted in Occlum.json thus can be changed
if (test_env_val("TEST", "true") < 0) {
THROW_ERROR("get environment variable failed");
}
// STABLE is set to "yes" as default in Occlum.json and is given a value of
// "no" from outside. Because it is not set to untrusted thus can't be modified
// and should have the value defined in Occlum.json
if (test_env_val("STABLE", "yes") < 0) {
THROW_ERROR("get environment variable failed");
}
// OVERRIDE is set to "N" as default in Occlum.json and is given a value of
// "Y" from outside. As it is also set to untrusted thus it should be modified
// and have the value passed from outside
if (test_env_val("OVERRIDE", "Y") < 0) {
THROW_ERROR("untrusted env override 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));
}
}