Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add proper tracing options, remove getenv calls from enclave code. #806

Open
wants to merge 16 commits into
base: oe_port
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Move enclave config into mprotected memory pages
Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
  • Loading branch information
wintersteiger committed Sep 15, 2020
commit 95d1aac3a35be2cee9c57993878b4cfd8ff1fd83
24 changes: 19 additions & 5 deletions src/enclave/enclave_oe.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,11 +299,25 @@ static void _read_eeid_config()
const oe_eeid_t* eeid = (oe_eeid_t*)__oe_get_eeid();
const char* config_json = (const char*)eeid->data;

sgxlkl_enclave_config_t* cfg = oe_malloc(sizeof(sgxlkl_enclave_config_t));
if (!cfg)
sgxlkl_fail("out of memory, cannot allocate enclave config.\n");
sgxlkl_read_enclave_config(config_json, cfg, true);
sgxlkl_enclave_state.config = cfg;
size_t num_pages = 0;
const sgxlkl_enclave_config_page_t* cfg_pages =
sgxlkl_read_enclave_config(config_json, true, &num_pages);

/* Make the config pages read-only */
prp marked this conversation as resolved.
Show resolved Hide resolved
for (size_t i = 0; i < num_pages; i++)
{
int mprotect_ret;
sgxlkl_host_syscall_mprotect(
&mprotect_ret,
(void*)&cfg_pages[i],
sizeof(sgxlkl_enclave_config_t),
PROT_READ);

if (mprotect_ret != 0)
sgxlkl_warn("Could not protect memory pages for config\n");
}

sgxlkl_enclave_state.config = &cfg_pages->config;
}

static void _copy_shared_memory(const sgxlkl_shared_memory_t* host)
Expand Down
3 changes: 3 additions & 0 deletions src/include/shared/oe_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <openenclave/corelibc/oemalloc.h>
#include <openenclave/corelibc/oestdlib.h>
#include <openenclave/corelibc/oestring.h>
#include <openenclave/corelibc/stdlib.h>
#include <openenclave/internal/safecrt.h>

#define malloc oe_malloc
Expand All @@ -21,11 +22,13 @@
#define strtok_r oe_strtok_r
#define snprintf oe_snprintf
#define strtoul oe_strtoul
#define memalign oe_memalign

#else

#include <assert.h>
#include <inttypes.h>
#include <malloc.h>
wintersteiger marked this conversation as resolved.
Show resolved Hide resolved
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
Expand Down
17 changes: 13 additions & 4 deletions src/include/shared/sgxlkl_enclave_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,23 @@
/* Maximum path length of mount points for secondary disks */
#define SGXLKL_DISK_MNT_MAX_PATH_LEN 255

#include <openenclave/bits/defs.h>

#include <sgxlkl_enclave_config_gen.h>

void sgxlkl_read_enclave_config(
struct config_page
{
sgxlkl_enclave_config_t config;
} __attribute__((__aligned__(OE_PAGE_SIZE)));

typedef struct config_page sgxlkl_enclave_config_page_t;

const sgxlkl_enclave_config_page_t* sgxlkl_read_enclave_config(
const char* from,
sgxlkl_enclave_config_t* to,
bool enforce_format);
bool enforce_format,
size_t* num_pages);

void sgxlkl_free_enclave_config(sgxlkl_enclave_config_t* enclave_config);
void sgxlkl_free_enclave_config_page(sgxlkl_enclave_config_page_t* config_page);

/* Check if a disk is configured for encrypted operation */
bool is_encrypted(sgxlkl_enclave_mount_config_t* cfg);
Expand Down
4 changes: 3 additions & 1 deletion src/main-oe/sgxlkl_run_oe.c
Original file line number Diff line number Diff line change
Expand Up @@ -1488,7 +1488,9 @@ void enclave_config_from_file(const char* filename)
if (ret < 0)
sgxlkl_host_fail("Failed to read %s: %s.\n", filename, strerror(errno));

sgxlkl_read_enclave_config(buf, &sgxlkl_host_state.enclave_config, false);
const sgxlkl_enclave_config_page_t* config_page =
sgxlkl_read_enclave_config(buf, false, NULL);
sgxlkl_host_state.enclave_config = *(sgxlkl_enclave_config_t*)config_page;
}

void override_enclave_config(
Expand Down
181 changes: 91 additions & 90 deletions src/shared/sgxlkl_enclave_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,34 @@
#define WARN sgxlkl_host_warn
#endif

#include <openenclave/bits/defs.h>

#include <json.h>
#include <shared/oe_compat.h>
#include <shared/sgxlkl_enclave_config.h>
#include <shared/string_list.h>
#include <shared/util.h>

#define CHECKMEM(C) \
if (!C) \
FAIL("out of memory\n");

// Duplicate a string (including NULL)
static int strdupz(char** to, const char* from)
static int strdupz(
char** to,
const char* from,
uint8_t** bytes,
size_t* bytes_remaining)
{
if (!to)
return 1;
else if (!from)
{
*to = NULL;
return 0;
}
else
{
size_t l = strlen(from);
*to = malloc(l + 1);
CHECKMEM(*to);
memcpy(*to, from, l + 1);
size_t sz = strlen(from) + 1;
if (*bytes_remaining < sz)
FAIL("out of memory\n");
memcpy(*bytes, from, sz);
*to = (char*)*bytes;
*bytes_remaining -= sz;
*bytes += sz;
}
return 0;
}
Expand All @@ -44,6 +46,9 @@ typedef struct json_callback_data
unsigned long index;
string_list_t* seen;
bool enforce_format;

uint8_t* bytes;
size_t bytes_remaining;
} json_callback_data_t;

static char* make_path(json_parser_t* parser)
Expand All @@ -67,8 +72,13 @@ static char* make_path(json_parser_t* parser)
}
}

char* r = NULL;
strdupz(&r, tmp);
size_t sz = strlen(tmp) + 1;
char* r = malloc(sz);
if (!r)
FAIL("out of memory\n");
char* t = r;
if (strdupz(&r, tmp, (uint8_t**)&t, &sz) != 0)
return NULL;
return r;
}

Expand Down Expand Up @@ -124,10 +134,16 @@ static char* make_path(json_parser_t* parser)
return JSON_OK; \
}

#define JSTRING(PATH, DEST) \
JPATH2T(PATH, JSON_TYPE_STRING, JSON_TYPE_NULL, { \
if (strdupz(&(DEST), un ? un->string : NULL)) \
return JSON_FAILED; \
#define JSTRING(PATH, DEST) \
JPATH2T(PATH, JSON_TYPE_STRING, JSON_TYPE_NULL, { \
json_callback_data_t* cbd = \
(json_callback_data_t*)parser->callback_data; \
if (strdupz( \
&(DEST), \
un ? un->string : NULL, \
&cbd->bytes, \
&cbd->bytes_remaining)) \
return JSON_FAILED; \
});

static json_result_t decode_safe_uint64_t(
Expand Down Expand Up @@ -229,10 +245,13 @@ static json_result_t decode_uint32_t(
else \
{ \
DEST##_len = l / 2; \
DEST = calloc(1, DEST##_len); \
CHECKMEM(DEST); \
if (data->bytes_remaining < DEST##_len) \
return JSON_OUT_OF_MEMORY; \
DEST = data->bytes; \
for (size_t i = 0; i < DEST##_len; i++) \
DEST[i] = hex_to_int(un->string + 2 * i, 2); \
data->bytes_remaining -= DEST##_len; \
data->bytes += DEST##_len; \
} \
} \
});
Expand All @@ -243,12 +262,16 @@ static json_result_t decode_uint32_t(
#define JU64(P, D) JPATH(P, return decode_uint64_t(parser, type, un, &D));
#define JU32(P, D) JPATH(P, return decode_uint32_t(parser, type, un, &D));

#define ALLOC_ARRAY(N, A, T) \
do \
{ \
data->config->N = un->integer; \
data->config->A = calloc(un->integer, sizeof(T)); \
CHECKMEM(data->config->A); \
#define ALLOC_ARRAY(N, A, T) \
do \
{ \
data->config->N = un->integer; \
size_t sz = un->integer * sizeof(T); \
if (data->bytes_remaining < sz) \
return JSON_OUT_OF_MEMORY; \
data->config->A = (T*)data->bytes; \
data->bytes_remaining -= sz; \
data->bytes += sz; \
} while (0)

static sgxlkl_enclave_mount_config_t* _mount(
Expand Down Expand Up @@ -382,13 +405,25 @@ static json_result_t json_read_callback(

JSTRING("cwd", cfg->cwd);
JPATHT("args", JSON_TYPE_STRING, {
strdupz(&cfg->args[i], un->string);
strdupz(
&cfg->args[i],
un->string,
&data->bytes,
&data->bytes_remaining);
});
JPATHT("env", JSON_TYPE_STRING, {
strdupz(&cfg->env[i], un->string);
strdupz(
&cfg->env[i],
un->string,
&data->bytes,
&data->bytes_remaining);
});
JPATHT("host_import_env", JSON_TYPE_STRING, {
strdupz(&cfg->host_import_env[i], un->string);
strdupz(
&cfg->host_import_env[i],
un->string,
&data->bytes,
&data->bytes_remaining);
});

JPATHT("exit_status", JSON_TYPE_STRING, {
Expand Down Expand Up @@ -488,10 +523,10 @@ void check_required_elements(string_list_t* seen)
}
}

void sgxlkl_read_enclave_config(
const sgxlkl_enclave_config_page_t* sgxlkl_read_enclave_config(
const char* from,
sgxlkl_enclave_config_t* to,
bool enforce_format)
bool enforce_format,
size_t* num_pages_out)
{
// Catch modifications to sgxlkl_enclave_config_t early. If this fails,
// the code above/below needs adjusting for the added/removed settings.
Expand All @@ -502,23 +537,35 @@ void sgxlkl_read_enclave_config(
if (!from)
FAIL("No config to read\n");

if (!to)
FAIL("No config to write to\n");
size_t num_pages = (strlen(from) / OE_PAGE_SIZE) + 1;
sgxlkl_enclave_config_page_t* config_page =
memalign(OE_PAGE_SIZE, num_pages * OE_PAGE_SIZE);
memset(config_page, 0, OE_PAGE_SIZE);
if (!config_page)
FAIL("out of memory\n");
config_page->config = sgxlkl_enclave_config_default;

*to = sgxlkl_enclave_config_default;
if (num_pages_out)
*num_pages_out = num_pages;

json_parser_t parser;
json_parser_options_t options;
options.allow_whitespace = !enforce_format;
json_result_t r = JSON_UNEXPECTED;
json_callback_data_t callback_data = {.config = to,
.index = 0,
.seen = NULL,
.enforce_format = enforce_format};
size_t config_size = sizeof(sgxlkl_enclave_config_t);
json_callback_data_t callback_data = {
.config = &config_page->config,
.index = 0,
.seen = NULL,
.enforce_format = enforce_format,
.bytes = (uint8_t*)(&config_page->config) + config_size,
.bytes_remaining = OE_PAGE_SIZE - config_size};

// parser destroys `from`, so we copy it first.
size_t json_len = strlen(from);
char* json_copy = malloc(sizeof(char) * (json_len + 1));
if (!json_copy)
FAIL("out of memory\n");
memcpy(json_copy, from, json_len);

json_allocator_t allocator = {.ja_malloc = malloc, .ja_free = free};
Expand All @@ -544,61 +591,15 @@ void sgxlkl_read_enclave_config(

if (enforce_format)
check_required_elements(callback_data.seen);
check_config(to);
check_config(&config_page->config);
string_list_free(callback_data.seen, true);
return config_page;
}

#define NONDEFAULT_FREE(X) \
if (config->X != default_config->X) \
free(config->X);

void sgxlkl_free_enclave_config(sgxlkl_enclave_config_t* config)
void sgxlkl_free_enclave_config_page(sgxlkl_enclave_config_page_t* config_page)
{
const sgxlkl_enclave_config_t* default_config =
&sgxlkl_enclave_config_default;

NONDEFAULT_FREE(net_ip4);
NONDEFAULT_FREE(net_gw4);
NONDEFAULT_FREE(net_mask4);
NONDEFAULT_FREE(hostname);

NONDEFAULT_FREE(wg.ip);
for (size_t i = 0; i < config->wg.num_peers; i++)
{
free(config->wg.peers[i].key);
free(config->wg.peers[i].allowed_ips);
free(config->wg.peers[i].endpoint);
}
NONDEFAULT_FREE(wg.peers);

NONDEFAULT_FREE(kernel_cmd);
NONDEFAULT_FREE(sysctl);
NONDEFAULT_FREE(cwd);

for (size_t i = 0; i < config->num_args; i++)
free(config->args[i]);
NONDEFAULT_FREE(args);

for (size_t i = 0; i < config->num_env; i++)
free(config->env[i]);
NONDEFAULT_FREE(env);

for (size_t i = 0; i < config->num_host_import_env; i++)
free(config->host_import_env[i]);
NONDEFAULT_FREE(host_import_env);

NONDEFAULT_FREE(root.key);
NONDEFAULT_FREE(root.key_id);
NONDEFAULT_FREE(root.roothash);

for (size_t i = 0; i < config->num_mounts; i++)
{
free(config->mounts[i].key);
free(config->mounts[i].key_id);
free(config->mounts[i].roothash);
}
NONDEFAULT_FREE(mounts);
free(config);
/* frees the entire config, including all strings */
free(config_page);
}

bool is_encrypted(sgxlkl_enclave_mount_config_t* cfg)
Expand Down