Skip to content

Commit

Permalink
Move enclave config into mprotected memory pages
Browse files Browse the repository at this point in the history
Signed-off-by: Christoph M. Wintersteiger <[email protected]>
  • Loading branch information
Christoph M. Wintersteiger committed Aug 25, 2020
1 parent 24332ff commit 0464173
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 100 deletions.
24 changes: 19 additions & 5 deletions src/enclave/enclave_oe.c
Original file line number Diff line number Diff line change
Expand Up @@ -302,11 +302,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 */
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>
#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 @@ -1467,7 +1467,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

0 comments on commit 0464173

Please sign in to comment.