Permalink
Browse files

Check that ecall [user_check] pointers and ocall_malloc result pointe…

…r are outside enclave (#67)

This should reduce the enclave's attack surface by preventing an attacker from invoking ecalls on or triggering unexpected writes to arbitrary enclave memory, which could potentially leak information about that memory or lead to incorrect results.

Fixes #36. Fixes #66.
  • Loading branch information...
ankurdave committed Dec 1, 2018
1 parent a3502ab commit 5ddda15d89f5ac82f4416208c5319ace4aecdc36
@@ -357,7 +357,7 @@ void ocall_print_string(const char *str)
fflush(stdout);
}

void ocall_malloc(size_t size, uint8_t **ret) {
void unsafe_ocall_malloc(size_t size, uint8_t **ret) {
*ret = static_cast<uint8_t *>(malloc(size));
}

@@ -10,6 +10,7 @@
#include "Project.h"
#include "Sort.h"
#include "isv_enclave.h"
#include "sgx_lfence.h"
#include "util.h"

// This file contains definitions of the ecalls declared in Enclave.edl. Errors originating within
@@ -19,6 +20,11 @@

void ecall_encrypt(uint8_t *plaintext, uint32_t plaintext_length,
uint8_t *ciphertext, uint32_t cipher_length) {
// Guard against encrypting or overwriting enclave memory
assert(sgx_is_outside_enclave(plaintext, plaintext_length) == 1);
assert(sgx_is_outside_enclave(ciphertext, cipher_length) == 1);
sgx_lfence();

try {
// IV (12 bytes) + ciphertext + mac (16 bytes)
assert(cipher_length >= plaintext_length + SGX_AESGCM_IV_SIZE + SGX_AESGCM_MAC_SIZE);
@@ -33,6 +39,10 @@ void ecall_encrypt(uint8_t *plaintext, uint32_t plaintext_length,
void ecall_project(uint8_t *condition, size_t condition_length,
uint8_t *input_rows, size_t input_rows_length,
uint8_t **output_rows, size_t *output_rows_length) {
// Guard against operating on arbitrary enclave memory
assert(sgx_is_outside_enclave(input_rows, input_rows_length) == 1);
sgx_lfence();

try {
project(condition, condition_length,
input_rows, input_rows_length,
@@ -45,6 +55,10 @@ void ecall_project(uint8_t *condition, size_t condition_length,
void ecall_filter(uint8_t *condition, size_t condition_length,
uint8_t *input_rows, size_t input_rows_length,
uint8_t **output_rows, size_t *output_rows_length) {
// Guard against operating on arbitrary enclave memory
assert(sgx_is_outside_enclave(input_rows, input_rows_length) == 1);
sgx_lfence();

try {
filter(condition, condition_length,
input_rows, input_rows_length,
@@ -56,6 +70,10 @@ void ecall_filter(uint8_t *condition, size_t condition_length,

void ecall_sample(uint8_t *input_rows, size_t input_rows_length,
uint8_t **output_rows, size_t *output_rows_length) {
// Guard against operating on arbitrary enclave memory
assert(sgx_is_outside_enclave(input_rows, input_rows_length) == 1);
sgx_lfence();

try {
sample(input_rows, input_rows_length,
output_rows, output_rows_length);
@@ -68,6 +86,10 @@ void ecall_find_range_bounds(uint8_t *sort_order, size_t sort_order_length,
uint32_t num_partitions,
uint8_t *input_rows, size_t input_rows_length,
uint8_t **output_rows, size_t *output_rows_length) {
// Guard against operating on arbitrary enclave memory
assert(sgx_is_outside_enclave(input_rows, input_rows_length) == 1);
sgx_lfence();

try {
find_range_bounds(sort_order, sort_order_length,
num_partitions,
@@ -83,6 +105,11 @@ void ecall_partition_for_sort(uint8_t *sort_order, size_t sort_order_length,
uint8_t *input_rows, size_t input_rows_length,
uint8_t *boundary_rows, size_t boundary_rows_length,
uint8_t **output_partitions, size_t *output_partition_lengths) {
// Guard against operating on arbitrary enclave memory
assert(sgx_is_outside_enclave(input_rows, input_rows_length) == 1);
assert(sgx_is_outside_enclave(boundary_rows, boundary_rows_length) == 1);
sgx_lfence();

try {
partition_for_sort(sort_order, sort_order_length,
num_partitions,
@@ -97,6 +124,10 @@ void ecall_partition_for_sort(uint8_t *sort_order, size_t sort_order_length,
void ecall_external_sort(uint8_t *sort_order, size_t sort_order_length,
uint8_t *input_rows, size_t input_rows_length,
uint8_t **output_rows, size_t *output_rows_length) {
// Guard against operating on arbitrary enclave memory
assert(sgx_is_outside_enclave(input_rows, input_rows_length) == 1);
sgx_lfence();

try {
external_sort(sort_order, sort_order_length,
input_rows, input_rows_length,
@@ -109,6 +140,10 @@ void ecall_external_sort(uint8_t *sort_order, size_t sort_order_length,
void ecall_scan_collect_last_primary(uint8_t *join_expr, size_t join_expr_length,
uint8_t *input_rows, size_t input_rows_length,
uint8_t **output_rows, size_t *output_rows_length) {
// Guard against operating on arbitrary enclave memory
assert(sgx_is_outside_enclave(input_rows, input_rows_length) == 1);
sgx_lfence();

try {
scan_collect_last_primary(join_expr, join_expr_length,
input_rows, input_rows_length,
@@ -122,6 +157,11 @@ void ecall_non_oblivious_sort_merge_join(uint8_t *join_expr, size_t join_expr_le
uint8_t *input_rows, size_t input_rows_length,
uint8_t *join_row, size_t join_row_length,
uint8_t **output_rows, size_t *output_rows_length) {
// Guard against operating on arbitrary enclave memory
assert(sgx_is_outside_enclave(input_rows, input_rows_length) == 1);
assert(sgx_is_outside_enclave(join_row, join_row_length) == 1);
sgx_lfence();

try {
non_oblivious_sort_merge_join(join_expr, join_expr_length,
input_rows, input_rows_length,
@@ -138,6 +178,10 @@ void ecall_non_oblivious_aggregate_step1(
uint8_t **first_row, size_t *first_row_length,
uint8_t **last_group, size_t *last_group_length,
uint8_t **last_row, size_t *last_row_length) {
// Guard against operating on arbitrary enclave memory
assert(sgx_is_outside_enclave(input_rows, input_rows_length) == 1);
sgx_lfence();

try {
non_oblivious_aggregate_step1(
agg_op, agg_op_length,
@@ -157,6 +201,13 @@ void ecall_non_oblivious_aggregate_step2(
uint8_t *prev_partition_last_group, size_t prev_partition_last_group_length,
uint8_t *prev_partition_last_row, size_t prev_partition_last_row_length,
uint8_t **output_rows, size_t *output_rows_length) {
// Guard against operating on arbitrary enclave memory
assert(sgx_is_outside_enclave(input_rows, input_rows_length) == 1);
assert(sgx_is_outside_enclave(next_partition_first_row, next_partition_first_row_length) == 1);
assert(sgx_is_outside_enclave(prev_partition_last_group, prev_partition_last_group_length) == 1);
assert(sgx_is_outside_enclave(prev_partition_last_row, prev_partition_last_row_length) == 1);
sgx_lfence();

try {
non_oblivious_aggregate_step2(
agg_op, agg_op_length,
@@ -88,7 +88,18 @@ enclave {

untrusted {
void ocall_print_string([in, string] const char *str);
void ocall_malloc(size_t size, [out] uint8_t **ret);

/**
* Allocate memory outside of the enclave and return the pointer in `ret`.
*
* Before dereferencing the resulting pointer, the caller must check whether it is actually
* outside the enclave using `sgx_is_outside_enclave()`. Otherwise, an attacker could cause the
* enclave to perform unexpected operations on its own memory. The function `ocall_malloc()`
* wraps this function with such a bounds check and most callers should use that function
* instead.
*/
void unsafe_ocall_malloc(size_t size, [out] uint8_t **ret);

void ocall_free([user_check] uint8_t *buf);
void ocall_exit(int exit_code);
void ocall_throw([in, string] const char *message);
@@ -4,6 +4,7 @@
#include <cstdio>

#include "Enclave_t.h"
#include "sgx_lfence.h"

int printf(const char *fmt, ...) {
char buf[BUFSIZ] = {'\0'};
@@ -38,6 +39,14 @@ void exit(int exit_code) {
ocall_exit(exit_code);
}

void ocall_malloc(size_t size, uint8_t **ret) {
unsafe_ocall_malloc(size, ret);

// Guard against overwriting enclave memory
assert(sgx_is_outside_enclave(*ret, size) == 1);
sgx_lfence();
}

void print_bytes(uint8_t *ptr, uint32_t len) {
for (uint32_t i = 0; i < len; i++) {
printf("%u", *(ptr + i));
@@ -18,6 +18,14 @@ namespace std {
using ::exit;
}

/**
* Allocate memory outside of the enclave and return the pointer in `ret`.
*
* This is a checked wrapper around `unsafe_ocall_malloc`. The resulting pointer is safe to write
* to.
*/
void ocall_malloc(size_t size, uint8_t **ret);

std::string string_format(const std::string &fmt, ...);

void print_bytes(uint8_t *ptr, uint32_t len);

0 comments on commit 5ddda15

Please sign in to comment.