Initial release of Intel SGX for Linux.

This release is used in conjunction with the linux-sgx-driver Intial release:
https://github.com/01org/linux-sgx-driver
commit-id: 0e865ce5e6b297a787bcdc12d98bada8174be6d7

Intel-id: 33399

Signed-off-by: Angie Chinchilla <angie.v.chinchilla@intel.com>
This commit is contained in:
Angie Chinchilla
2016-06-23 18:51:53 -04:00
parent ba82cfcbb0
commit 9441de4c38
2767 changed files with 820699 additions and 0 deletions

66
sdk/trts/Makefile Normal file
View File

@ -0,0 +1,66 @@
#
# Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#
include ../../buildenv.mk
CPPFLAGS += -I$(COMMON_DIR)/inc \
-I$(COMMON_DIR)/inc/internal \
-I$(COMMON_DIR)/inc/tlibc
CXXFLAGS += $(ENCLAVE_CXXFLAGS) \
-Werror \
-fno-exceptions \
-fno-rtti
OBJS := init_enclave.o \
trts.o \
trts_ecall.o \
trts_ocall.o \
trts_util.o \
trts_veh.o \
trts_xsave.o \
init_optimized_lib.o \
trts_version.o
all: $(OBJS) elf_parser
$(OBJS): %.o: %.cpp
$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) $< -o $@
.PHONY: elf_parser
elf_parser:
$(MAKE) -C linux
.PHONY: clean
clean:
@$(RM) $(OBJS) *.bak *~
$(MAKE) -C linux clean

137
sdk/trts/init_enclave.cpp Normal file
View File

@ -0,0 +1,137 @@
/*
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**
* File: init_enclave.cpp
* Description:
* Initialize enclave by rebasing the image to the enclave base
*/
#include <string.h>
#include "thread_data.h"
#include "global_data.h"
#include "util.h"
#include "xsave.h"
#include "sgx_trts.h"
#include "init_optimized_lib.h"
#include "trts_internal.h"
# include "linux/elf_parser.h"
#include "rts.h"
// The global cpu feature bits from uRTS
uint64_t g_cpu_feature_indicator = 0;
const volatile global_data_t g_global_data = {1, 2, 3, 4, 0,
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}};
uint32_t g_enclave_state = ENCLAVE_INIT_NOT_STARTED;
extern "C" {
uintptr_t __stack_chk_guard = 0;
#define __weak_alias(alias,sym) \
__asm__(".weak " __STRING(alias) " ; " \
__STRING(alias) " = " __STRING(sym))
__weak_alias(__intel_security_cookie, __stack_chk_guard);
}
// init_enclave()
// Initialize enclave.
// Parameters:
// [IN] enclave_base - the enclave base address
// [IN] ms - the marshalling structure passed by uRTS
// Return Value:
// 0 - success
// -1 - fail
//
extern "C" int init_enclave(void *enclave_base, void *ms)
{
if(enclave_base == NULL || ms == NULL)
{
return -1;
}
// relocation
if(0 != relocate_enclave(enclave_base))
{
return -1;
}
// Check if the ms is outside the enclave.
// sgx_is_outside_enclave() should be placed after relocate_enclave()
cpu_sdk_info_t *info = (cpu_sdk_info_t *)ms;
if(!sgx_is_outside_enclave(info, sizeof(cpu_sdk_info_t)))
{
return -1;
}
const sdk_version_t sdk_version = info->version;
const uint64_t cpu_features = info->cpu_features;
if (sdk_version != SDK_VERSION_1_5)
return -1;
// xsave
uint64_t xfrm = get_xfeature_state();
// optimized libs
if(0 != init_optimized_libs(cpu_features, xfrm))
{
CLEAN_XFEATURE_REGS
return -1;
}
if(SGX_SUCCESS != sgx_read_rand((unsigned char*)&__stack_chk_guard,
sizeof(__stack_chk_guard)))
{
CLEAN_XFEATURE_REGS
return -1;
}
// clean extended registers, no need to save
CLEAN_XFEATURE_REGS
return 0;
}
sgx_status_t do_init_enclave(void *ms)
{
void *enclave_base = get_enclave_base();
if(ENCLAVE_INIT_NOT_STARTED != lock_enclave())
{
return SGX_ERROR_UNEXPECTED;
}
if(0 != init_enclave(enclave_base, ms))
{
return SGX_ERROR_UNEXPECTED;
}
memset(GET_PTR(void, enclave_base, g_global_data.heap_offset), 0, g_global_data.heap_size);
g_enclave_state = ENCLAVE_INIT_DONE;
return SGX_SUCCESS;
}

View File

@ -0,0 +1,126 @@
/*
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "init_optimized_lib.h"
#include <stdint.h>
#include "se_cpu_feature.h"
#include "sgx_trts.h"
#include "sgx_attributes.h"
#include "global_data.h"
extern "C" int sgx_init_string_lib(uint64_t cpu_feature_indicator);
extern "C" sgx_status_t sgx_init_crypto_lib(uint64_t cpu_feature_indicator);
static int set_global_feature_indicator(uint64_t feature_bit_array, uint64_t xfrm)
{
// Confirm the reserved bits and the unset bits by uRTS must be 0.
if(feature_bit_array & (RESERVED_CPU_FEATURE_BIT))
{
// clear the reserved bits
feature_bit_array = feature_bit_array & (~(RESERVED_CPU_FEATURE_BIT));
}
;
#ifdef SE_SIM
// Simulation mode - requires SSE for x86 and SSE2 for x64.
#ifdef SE_32
if(!(feature_bit_array & ~(CPU_FEATURE_SSE - 1)))
{
return -1;
}
#else
if(!(feature_bit_array & ~(CPU_FEATURE_SSE2 - 1)))
{
return -1;
}
#endif
#else
// HW mode - requires SSE4.2. Take SSE4.2 as the baseline.
if(!(feature_bit_array & ~(CPU_FEATURE_SSE4_2 - 1)))
{
return -1;
}
#endif
// Check for inconsistencies in the CPUID feature mask.
if ( (((feature_bit_array & CPU_FEATURE_SSE) == CPU_FEATURE_SSE) &&((feature_bit_array & (CPU_FEATURE_SSE - 1)) != (CPU_FEATURE_SSE - 1))) ||
(((feature_bit_array & CPU_FEATURE_SSE2) == CPU_FEATURE_SSE2) &&((feature_bit_array & (CPU_FEATURE_SSE2 - 1)) != (CPU_FEATURE_SSE2 - 1))) ||
(((feature_bit_array & CPU_FEATURE_SSE3) == CPU_FEATURE_SSE3) &&((feature_bit_array & (CPU_FEATURE_SSE3 - 1)) != (CPU_FEATURE_SSE3 - 1))) ||
(((feature_bit_array & CPU_FEATURE_SSSE3) == CPU_FEATURE_SSSE3) && ((feature_bit_array & (CPU_FEATURE_SSSE3 - 1)) != (CPU_FEATURE_SSSE3 - 1))) ||
(((feature_bit_array & CPU_FEATURE_SSE4_1) == CPU_FEATURE_SSE4_1) && ((feature_bit_array & (CPU_FEATURE_SSE4_1 - 1)) != (CPU_FEATURE_SSE4_1 - 1))) ||
(((feature_bit_array & CPU_FEATURE_SSE4_2) == CPU_FEATURE_SSE4_2) && ((feature_bit_array & (CPU_FEATURE_SSE4_2 - 1)) != (CPU_FEATURE_SSE4_2 - 1))) )
{
return -1;
}
// Determine whether the OS & ENCLAVE support SAVE/RESTORE of the AVX register set
// IF NOT, clear the advanced feature set bits corresponding to AVX and beyond
if(!XFEATURE_ENABLED_AVX(xfrm))
{
// AVX is disabled by OS, so clear the AVX related feature bits
feature_bit_array &= (~(CPU_FEATURE_AVX | CPU_FEATURE_F16C | CPU_FEATURE_AVX2 |
CPU_FEATURE_FMA | CPU_FEATURE_RTM | CPU_FEATURE_HLE | CPU_FEATURE_BMI |
CPU_FEATURE_PREFETCHW | CPU_FEATURE_RDSEED | CPU_FEATURE_ADCOX));
}
g_cpu_feature_indicator = feature_bit_array;
return 0;
}
extern "C" int init_optimized_libs(const uint64_t feature_bit_array, uint64_t xfrm)
{
if (g_enclave_state != ENCLAVE_INIT_IN_PROGRESS)
{
return -1;
}
// set the global feature indicator
if(set_global_feature_indicator(feature_bit_array, xfrm))
{
return -1;
}
// Init string library with the global feature indicator
if(sgx_init_string_lib(g_cpu_feature_indicator) != 0)
{
return -1;
}
// Init IPP crypto library with the global feature indicator
if(sgx_init_crypto_lib(g_cpu_feature_indicator) != 0)
{
return -1;
}
return 0;
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef INIT_OPTIMIZED_LIB_H
#define INIT_OPTIMIZED_LIB_H
#include "se_types.h"
#ifdef __cplusplus
extern "C" {
#endif
int init_optimized_libs(const uint64_t feature_bits_array, uint64_t xfrm);
#ifdef __cplusplus
}
#endif
#endif

91
sdk/trts/linux/Makefile Normal file
View File

@ -0,0 +1,91 @@
#
# Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#
include ../../../buildenv.mk
CFLAGS += -Werror $(ENCLAVE_CFLAGS) \
-I$(LINUX_SDK_DIR)/trts \
-I$(COMMON_DIR)/inc \
-I$(COMMON_DIR)/inc/internal \
-I$(COMMON_DIR)/inc/internal/linux \
-I$(LINUX_SDK_DIR)/simulation/assembly/
CXXFLAGS += -Werror $(ENCLAVE_CXXFLAGS) \
-I$(LINUX_SDK_DIR)/trts \
-I$(COMMON_DIR)/inc \
-I$(COMMON_DIR)/inc/internal/
TCFLAGS += -nostdinc \
-I$(COMMON_DIR)/inc/tlibc/
LDCFLAGS := -shared -nostdlib -nodefaultlibs -nostartfiles
CPP_SRCS := $(wildcard ../*.cpp)
C_SRCS := $(wildcard *.c)
ASM_SRCS := $(wildcard *.S)
OBJS := $(CPP_SRCS:.cpp=.o)
OBJS += $(C_SRCS:.c=.o)
OBJS += $(ASM_SRCS:.S=.o)
LIBTRTS = libsgx_trts.a
.PHONY: all
all: $(LIBTRTS) | $(BUILD_DIR)
$(CP) $(LIBTRTS) $|
$(LIBTRTS): $(OBJS) setcontext.o
$(AR) rsD $@ $(OBJS)
$(AR) rsD $@ $(ARCH)/setcontext.o
%.o: %.S
$(CC) $(CFLAGS) $(TCFLAGS) -c $< -o $@
%.o: %.c
$(CC) $(CFLAGS) $(TCFLAGS) -c $< -o $@
%.o: %.cpp
$(CXX) $(CXXFLAGS) $(TCFLAGS) -c $< -o $@
$(BUILD_DIR):
@$(MKDIR) $@
.PHONY: setcontext.o
setcontext.o:
$(MAKE) -C $(ARCH)
.PHONY: clean
clean:
@$(RM) $(OBJS) $(LIBTRTS) $(BUILD_DIR)/$(LIBTRTS)
$(MAKE) -C $(ARCH) clean
.PHONY: rebuild
rebuild: clean all

419
sdk/trts/linux/elf_parser.c Normal file
View File

@ -0,0 +1,419 @@
/*
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/*
* This file is part of trusted loader for tRTS.
*/
#include "elf_parser.h"
#include "rts.h"
#include "util.h"
#include "elf_util.h"
#include "global_data.h"
static int elf_tls_aligned_virtual_size(const void *enclave_base,
size_t *aligned_virtual_size);
static ElfW(Phdr)* get_phdr(const ElfW(Ehdr)* ehdr)
{
if (ehdr == NULL)
return NULL; /* Invalid image. */
/* Check the ElfW Magic number. */
if ((ehdr->e_ident[EI_MAG0] != ELFMAG0) ||
(ehdr->e_ident[EI_MAG1] != ELFMAG1) ||
(ehdr->e_ident[EI_MAG2] != ELFMAG2) ||
(ehdr->e_ident[EI_MAG3] != ELFMAG3))
return NULL;
/* Enclave image should be a shared object file. */
if (ehdr->e_type != ET_DYN)
return NULL;
return GET_PTR(ElfW(Phdr), ehdr, ehdr->e_phoff);
}
static ElfW(Sym)* get_sym(ElfW(Sym)* symtab, size_t idx)
{
if(STB_WEAK == ELFW(ST_BIND)(symtab[idx].st_info)
&& 0 == symtab[idx].st_value)
{
return NULL;
}
return &symtab[idx];
}
#ifdef __x86_64__
/* Relocation for x64 (with addend) */
static int do_relocs(const ElfW(Addr) enclave_base,
ElfW(Addr) rela_offset,
ElfW(Addr) sym_offset,
size_t nr_relocs)
{
ElfW(Rela)* rela = GET_PTR(ElfW(Rela), enclave_base, rela_offset);
ElfW(Sym)* symtab = GET_PTR(ElfW(Sym), enclave_base, sym_offset);
ElfW(Sym)* sym;
size_t i;
size_t aligned_virtual_size = 0;
for (i = 0; i < nr_relocs; ++i, ++rela)
{
ElfW(Addr)* reloc_addr = GET_PTR(ElfW(Addr), enclave_base, rela->r_offset);
switch (ELF64_R_TYPE(rela->r_info))
{
case R_X86_64_RELATIVE:
*reloc_addr = enclave_base + (uintptr_t)rela->r_addend;
break;
case R_X86_64_GLOB_DAT:
case R_X86_64_JUMP_SLOT:
case R_X86_64_64:
sym = get_sym(symtab, ELF64_R_SYM(rela->r_info));
if(!sym)
break;
*reloc_addr = enclave_base + sym->st_value + (uintptr_t)rela->r_addend;
break;
case R_X86_64_DTPMOD64:
*reloc_addr = 1;
break;
case R_X86_64_DTPOFF64:
sym = get_sym(symtab, ELF64_R_SYM(rela->r_info));
if(!sym)
break;
*reloc_addr = sym->st_value + (uintptr_t)rela->r_addend;
break;
case R_X86_64_TPOFF64:
sym = get_sym(symtab, ELF64_R_SYM(rela->r_info));
if(!sym)
break;
if ((0 == elf_tls_aligned_virtual_size((void *)enclave_base, &aligned_virtual_size)) && (aligned_virtual_size))
{
*reloc_addr = sym->st_value + (uintptr_t)rela->r_addend - aligned_virtual_size;
break;
}
else
return -1;
case R_X86_64_NONE:
break;
default: /* unsupported relocs */
return -1;
}
}
return 0;
}
#elif defined(__i386__)
/* Relocation for x86 (without addend) */
static int do_relocs(const ElfW(Addr) enclave_base,
ElfW(Addr) rel_offset,
ElfW(Addr) sym_offset,
size_t nr_relocs)
{
ElfW(Rel)* rel = GET_PTR(ElfW(Rel), enclave_base, rel_offset);
ElfW(Sym)* symtab = GET_PTR(ElfW(Sym), enclave_base, sym_offset);
ElfW(Sym)* sym = NULL;
size_t i;
size_t aligned_virtual_size = 0;
for (i = 0; i < nr_relocs; ++i, ++rel)
{
ElfW(Addr)* reloc_addr = GET_PTR(ElfW(Addr), enclave_base, rel->r_offset);
if(R_386_RELATIVE == ELF32_R_TYPE(rel->r_info))
{
*reloc_addr += enclave_base; /* B+A */
continue;
}
sym = get_sym(symtab, ELF32_R_SYM(rel->r_info));
if(!sym) /* when the weak symbol is not implemented, sym is NULL */
continue;
switch (ELF32_R_TYPE(rel->r_info))
{
case R_386_GLOB_DAT:
case R_386_JMP_SLOT: /* S */
*reloc_addr = enclave_base + sym->st_value;
break;
case R_386_32: /* S+A */
*reloc_addr += enclave_base + sym->st_value;
break;
case R_386_PC32: /* S+A-P */
*reloc_addr += (enclave_base + sym->st_value - (ElfW(Addr))reloc_addr);
break;
case R_386_NONE:
break;
case R_386_TLS_DTPMOD32:
*reloc_addr = 1;
break;
case R_386_TLS_DTPOFF32:
*reloc_addr = sym->st_value;
break;
case R_386_TLS_TPOFF:
if ((0 == elf_tls_aligned_virtual_size((void *)enclave_base, &aligned_virtual_size)) && (aligned_virtual_size))
{
*reloc_addr += sym->st_value - aligned_virtual_size;
break;
}
else
return -1;
case R_386_TLS_TPOFF32:
if ((0 == elf_tls_aligned_virtual_size((void *)enclave_base, &aligned_virtual_size)) && (aligned_virtual_size))
{
*reloc_addr += aligned_virtual_size - sym->st_value;
break;
}
else
return -1;
default: /* unsupported relocs */
return -1;
}
}
return 0;
}
#endif
#define DO_REL(base_addr, rel_offset, sym_offset, total_sz, rel_entry_sz) \
do { \
if (rel_offset) \
{ \
size_t n; \
if (rel_entry_sz == 0) \
return -1; \
n = total_sz/rel_entry_sz; \
if (do_relocs((ElfW(Addr))enclave_base, rel_offset, sym_offset, n)) \
return -1; \
} \
} while (0)
/* By default all symbol is linked as global symbol by link editor. When call global symbol,
* we first call .plt entry. It should have problems if the call goloal symbol when relocation
* is not done.
* Declare relocate_enclave as .hidden is to make it local symbol.
* Since this function is called before relocation is done, we must make
* it local symbol, so the code is like "fce3: e8 98 12 00 00 call 10f80 <relocate_enclave>"
* 0x9812=0x10f80-0xfce8
*/
__attribute__ ((visibility ("hidden")))
int relocate_enclave(void* enclave_base)
{
ElfW(Half) phnum = 0;
ElfW(Ehdr) *ehdr = (ElfW(Ehdr)*)enclave_base;
ElfW(Phdr) *phdr = get_phdr(ehdr);
if (phdr == NULL)
return -1; /* Invalid image. */
for (; phnum < ehdr->e_phnum; phnum++, phdr++)
{
/* Search for dynamic segment */
if (phdr->p_type == PT_DYNAMIC)
{
size_t count;
size_t n_dyn = phdr->p_filesz/sizeof(ElfW(Dyn));
ElfW(Dyn) *dyn = GET_PTR(ElfW(Dyn), ehdr, phdr->p_paddr);
ElfW(Addr) sym_offset = 0;
ElfW(Addr) rel_offset = 0;
ElfW(Addr) plt_offset = 0;
size_t rel_total_sz = 0;
size_t rel_entry_sz = 0;
size_t plt_total_sz = 0;
for (count = 0; count < n_dyn; count++, dyn++)
{
if (dyn->d_tag == DT_NULL) /* End */
break;
switch (dyn->d_tag)
{
case DT_SYMTAB: /* symbol table */
sym_offset = dyn->d_un.d_ptr;
break;
case RTS_DT_REL:/* Rel (x86) or Rela (x64) relocs */
rel_offset = dyn->d_un.d_ptr;
break;
case RTS_DT_RELSZ:
rel_total_sz = dyn->d_un.d_val;
break;
case RTS_DT_RELENT:
rel_entry_sz = dyn->d_un.d_val;
break;
case DT_JMPREL: /* PLT relocs */
plt_offset = dyn->d_un.d_ptr;
break;
case DT_PLTRELSZ:
plt_total_sz = dyn->d_un.d_val;
break;
}
}
DO_REL(enclave_base, rel_offset, sym_offset, rel_total_sz, rel_entry_sz);
DO_REL(enclave_base, plt_offset, sym_offset, plt_total_sz, rel_entry_sz);
}
}
return 0;
}
int elf_tls_info(const void* enclave_base,
uintptr_t *tls_addr, size_t *tdata_size)
{
ElfW(Half) phnum = 0;
const ElfW(Ehdr) *ehdr = (const ElfW(Ehdr)*)enclave_base;
ElfW(Phdr) *phdr = get_phdr(ehdr);
if (!tls_addr || !tdata_size)
return -1;
if (phdr == NULL)
return -1; /* Invalid image. */
/* Search for TLS segment */
*tls_addr = 0;
*tdata_size = 0;
for (; phnum < ehdr->e_phnum; phnum++, phdr++)
{
if (phdr->p_type == PT_TLS)
{
/* tls_addr here is got from the program header, the address
* need to be added by the enclave base.
*/
*tls_addr = (size_t)enclave_base + phdr->p_vaddr;
*tdata_size = phdr->p_filesz;
break;
}
}
return 0;
}
static int elf_tls_aligned_virtual_size(const void *enclave_base,
size_t *aligned_virtual_size)
{
ElfW(Half) phnum = 0;
const ElfW(Ehdr) *ehdr = (const ElfW(Ehdr)*)enclave_base;
ElfW(Phdr) *phdr = get_phdr(ehdr);
size_t virtual_size =0, align = 0;
if (phdr == NULL)
return -1;
if (!aligned_virtual_size)
return -1;
*aligned_virtual_size = 0;
for (; phnum < ehdr->e_phnum; phnum++, phdr++)
{
if (phdr->p_type == PT_TLS)
{
virtual_size = phdr->p_memsz;
align = phdr->p_align;
/* p_align == 0 or p_align == 1 means no alignment is required */
if (align == 0 || align == 1)
*aligned_virtual_size = virtual_size;
else
*aligned_virtual_size = (virtual_size + align - 1) & (~(align - 1));
break;
}
}
return 0;
}
int elf_get_init_array(const void* enclave_base,
uintptr_t *init_array_addr, size_t *init_array_size)
{
ElfW(Half) phnum = 0;
const ElfW(Ehdr) *ehdr = (const ElfW(Ehdr)*)enclave_base;
ElfW(Phdr) *phdr = get_phdr(ehdr);
if (!init_array_addr || !init_array_size)
return -1;
if (phdr == NULL)
return -1; /* Invalid image. */
*init_array_addr = 0;
*init_array_size = 0;
/* Search for Dynamic segment */
for (; phnum < ehdr->e_phnum; phnum++, phdr++)
{
if (phdr->p_type == PT_DYNAMIC)
{
size_t count;
size_t n_dyn = phdr->p_filesz/sizeof(ElfW(Dyn));
ElfW(Dyn) *dyn = GET_PTR(ElfW(Dyn), ehdr, phdr->p_paddr);
for (count = 0; count < n_dyn; count++, dyn++)
{
switch (dyn->d_tag)
{
case DT_INIT_ARRAY:
*init_array_addr = dyn->d_un.d_ptr;
break;
case DT_INIT_ARRAYSZ:
*init_array_size = dyn->d_un.d_val;
break;
}
}
}
}
return 0;
}
/* vim: set ts=4 sw=4 et cin: */

View File

@ -0,0 +1,59 @@
/*
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**
* File: elf_parser.h
* Description:
* Header file for tRTS ELF parser.
*/
#ifndef _PE_PARSER_H_
#define _PE_PARSER_H_
#include "se_types.h"
#ifdef __cplusplus
extern "C" {
#endif
int relocate_enclave(void* enclave_base);
int elf_tls_info(const void* enclave_base,
uintptr_t *tls_addr, size_t *tdata_size);
int elf_get_init_array(const void* enclave_base,
uintptr_t *init_array_addr, size_t *init_array_size);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,95 @@
/*
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "internal/global_init.h"
#include "linux/elf_parser.h"
#include "global_data.h"
#include "internal/util.h"
#include "thread_data.h"
#include "sgx_trts.h"
#include <assert.h>
#include <stdlib.h>
typedef void (*fp_t)(void);
/* required by global constructor when -fuse-cxa-atexit is enabled */
void *__dso_handle __attribute__((weak)) = &(__dso_handle);
int __cxa_atexit(void (*fun)(void *), void *para, void *dso)
{
(void)(fun);
(void)(para);
(void)(dso);
return 0;
}
/* auxiliary routines */
static void do_ctors_aux(void)
{
/* SGX RTS does not support .ctors currently */
fp_t *p = NULL;
uintptr_t init_array_addr;
size_t init_array_size;
const void *enclave_start = (const void*)&__ImageBase;
elf_get_init_array(enclave_start, &init_array_addr, &init_array_size);
if (init_array_addr == 0 || init_array_size == 0)
return;
fp_t *fp_start = (fp_t*)(init_array_addr + (uintptr_t)(enclave_start));
fp_t *fp_end = fp_start + (init_array_size / sizeof(fp_t));
/* traverse .init_array in forward order */
for (p = fp_start; p < fp_end; p++)
{
(*p)();
}
}
void init_global_object(void)
{
do_ctors_aux();
}
void init_stack_guard(void)
{
thread_data_t *thread_data = get_thread_data();
assert(thread_data != NULL);
if (SGX_SUCCESS != sgx_read_rand(
(unsigned char*)&thread_data->stack_guard,
sizeof(thread_data->stack_guard)))
abort();
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
.file "metadata_sec.S"
#define METADATA_SIZE 4096
.section ".note.sgxmeta", "", @note
.p2align 0 /* section no alignment */
.long 1f - 0f /* name size (not including padding) */
.long 2f - 1f /* desc size (not including padding) */
.long 0x01 /* type */
0: .asciz "sgx_metadata" /* name */
1: .fill METADATA_SIZE, 1, 0 /* desc - stand for metadata which is initialized with 0 */
2: .p2align 0

View File

@ -0,0 +1,55 @@
/*
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**
* File: tls_support.c
* Description:
* TLS support in the enclave.
*/
#include "thread_data.h"
typedef struct
{
unsigned long int ti_module;
unsigned long int ti_offset;
} tls_index;
#if defined SE_GNU32
void * __attribute__((__regparm__(1))) ___tls_get_addr(tls_index *ti)
#elif defined SE_GNU64
void *__tls_get_addr(tls_index *ti)
#endif
{
thread_data_t *thread_data = get_thread_data();
return (unsigned char *)thread_data->tls_addr + ti->ti_offset;
}

494
sdk/trts/linux/trts_pic.S Normal file
View File

@ -0,0 +1,494 @@
/*
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/*
* Description:
* The file provides `enclave_entry' function to switch code between
* trusted and untrusted envronment.
*/
.file "trts_pic.S"
#include "trts_pic.h"
.text
DECLARE_LOCAL_FUNC get_enclave_base
lea_pic __ImageBase, %xax
ret
DECLARE_LOCAL_FUNC get_enclave_state
lea_pic g_enclave_state, %xcx
xor %xax, %xax
movl (%xcx), %eax
ret
DECLARE_LOCAL_FUNC set_enclave_state
lea_pic g_enclave_state, %xax
#ifdef LINUX32
mov SE_WORDSIZE(%esp), %edi
#endif
movl %edi, (%xax)
ret
DECLARE_LOCAL_FUNC lock_enclave
lea_pic g_enclave_state, %xdx
xor %xax, %xax
mov $ENCLAVE_INIT_NOT_STARTED, %eax
xor %xcx, %xcx
mov $ENCLAVE_INIT_IN_PROGRESS, %ecx /* if (g_global_data.enclave_state == ENCLAVE_INIT_NOT_STARTED) */
lock cmpxchgl %ecx, (%xdx) /* g_global_data.enclave_state == ENCLAVE_INIT_IN_PROGRESS */
ret /* xax: the initial value of enclave state */
/*
* ---------------------------------------------------------------------
* Function: thread_data_t* get_thread_data(void);
*
* Get the address of thread_data
* ---------------------------------------------------------------------
*/
DECLARE_LOCAL_FUNC get_thread_data
READ_TD_DATA self_addr
ret
/*
* ---------------------------------------------------------------------
* Function: enclave_entry
* The entry point of the enclave.
*
* Registers:
* XAX - TCS.CSSA
* XBX - the address of a TCS
* XCX - the address of the instruction following the EENTER
* XDI - the reason of entering the enclave
* XSI - the pointer to the marshalling structure
*/
DECLARE_GLOBAL_FUNC enclave_entry
/*
* ----------------------------------------------------------------------
* Dispatch code according to CSSA and the reason of EENTER
* eax > 0 - exception handler
* edi >= 0 - ecall
* edi == -1 - do_init_enclave
* edi == -2 - oret
* Registers
* No need to use any register during the dipatch
* ----------------------------------------------------------------------
*/
.cfi_startproc
cmp $0, %xax
jne .Ldo_handler /* handle exception state */
xor %xdx, %xdx
READ_TD_DATA last_sp
cmp $0, %xax
jne .Lswitch_stack
GET_STACK_BASE %xbx /* if last_sp == 0, set sp to stack base */
sub $STATIC_STACK_SIZE, %xax /* give space for static stack */
.Lswitch_stack:
xchg %xsp, %xax
push %xcx
push %xbp
.cfi_def_cfa_offset 2 * SE_WORDSIZE
.cfi_offset xbp, -2 * SE_WORDSIZE
mov %xsp, %xbp
.cfi_def_cfa_register xbp
/* Save the registers */
sub $(6*SE_WORDSIZE), %xsp
mov %xax, -1*SE_WORDSIZE(%xbp) /* xsp_u */
mov %xdx, -3*SE_WORDSIZE(%xbp) /* cssa */
mov %xbx, -4*SE_WORDSIZE(%xbp) /* TCS */
mov %xsi, -5*SE_WORDSIZE(%xbp) /* XSI */
mov %xdi, -6*SE_WORDSIZE(%xbp) /* XDI */
#ifdef LINUX64
mov %rdx, %rcx
mov %rbx, %rdx
#endif
call enter_enclave
.Lexit_enclave:
mov -1*SE_WORDSIZE(%xbp), %xdx /* xdx: xsp_u */
mov %xbp, %xsp
pop %xbp /* xbp_u */
pop %xbx /* ret_u */
mov %xdx, %xsp /* xsp_u */
mov $OCMD_ERET, %xdi
mov %xax, %xsi
.Lclear_and_exit_enclave:
/* Clear all GPRs, except xax, xbx, xdi and xsi */
xor %xcx, %xcx
xor %xdx, %xdx
#if defined(LINUX64)
xor %r8, %r8
xor %r9, %r9
xor %r10, %r10
xor %r11, %r11
xor %r12, %r12
xor %r13, %r13
xor %r14, %r14
xor %r15, %r15
#endif
/* Set status flags to pre-defined values */
add %xdx, %xdx /* OF = SF = AF = CF = 0; ZF = PF = 1 */
/* EEXIT */
mov $SE_EEXIT, %xax /* EEXIT leaf */
ENCLU
/* Should not come here */
ud2
.Ldo_handler:
mov %xax, %xdx /* XDX: cssa */
GET_STACK_BASE %xbx /* XAX: static stack, set sp to stack base */
jmp .Lswitch_stack
/* Should not come here */
ud2
.cfi_endproc
/*
* -------------------------------------------------------------------------
* sgx_status_t do_ocall(unsigned int index, void *ms);
*
* Function: do_ocall
* The entry point of the enclave
* Parameters:
* func_addr - target function address
* ms - marshalling structure
*
* Stack: (same as do_oret)
* bottom of stack ->
* -----------------
* | ECALL/OCALL |
* previous TD.last_sp -> | frames |
* -----------------
* | ECALL frame |
* | do_ocall param 2| 21
* | do_ocall param 1| 20
* |do_ocall ret_addr| 19
* | ocall_depth | 18
* | reserved | 17
* | reserved | 16
* | reserved | 15
* | rbx | 14
* | rsi | 13
* | rdi | 12
* | rbp | 11
* | r12 | 10
* | r13 | 9
* | r14 | 8
* | r15 | 7
* | prev TD.last_sp | 6
* | ocall_index | 5
* | OCALL FLAG | 4
* | shadow | 3
* | shadow | 2
* | shadow | 1
* TD.last_sp -> | shadow | 0
* -----------------
* -------------------------------------------------------------------------
*/
DECLARE_LOCAL_FUNC do_ocall
/*
* 8 for GPR, 1 for TD.last_sp, 1 for ocall_index
* 1 for OCALL_FLAG, 4 for shadow space.
* Stack Pointer is 16-byte aligned under x86_64.
*/
sub $(19*SE_WORDSIZE), %xsp
/* save non-volatile registers, except xsp */
mov %xbx, SE_WORDSIZE*14(%xsp)
mov %xsi, SE_WORDSIZE*13(%xsp)
mov %xdi, SE_WORDSIZE*12(%xsp)
mov %xbp, SE_WORDSIZE*11(%xsp)
#ifdef LINUX64
mov %r12, SE_WORDSIZE*10(%rsp)
mov %r13, SE_WORDSIZE* 9(%rsp)
mov %r14, SE_WORDSIZE* 8(%rsp)
mov %r15, SE_WORDSIZE* 7(%rsp)
#endif
/* set xdi and xsi using the input parameters */
#ifdef LINUX64
mov %edi, %edi /* it should clear the high 32bit word of RDI */
/*
* rdi - param 1 (index), rsi - param 2 (ms)
* only use lower 32bit of rdi, rsi remains unchanged.
*/
#endif
#ifdef LINUX32
mov SE_WORDSIZE*20(%esp), %edi
mov SE_WORDSIZE*21(%esp), %esi
#endif
/* save ocall index to the stack */
mov $OCALL_FLAG, %xax
mov %xax, SE_WORDSIZE*4(%xsp) /* save OCALL_FLAG */
mov %xdi, SE_WORDSIZE*5(%xsp) /* save ocall_index */
/*
* save the inside stack context
* push TD.last_sp
* set TD.last_sp = xsp
*/
READ_TD_DATA self_addr
mov %xax, %xbx
/* call update_ocall_lastsp */
#ifdef LINUX32
mov %xsp, (%xsp)
#else
mov %xsp, %xdi
#endif
call update_ocall_lastsp /* xax: td.last_sp */
#ifdef LINUX64
mov SE_WORDSIZE*12(%xsp), %xdi /* restore xdi */
mov SE_WORDSIZE*13(%xsp), %xsi /* restore xdi */
#endif
/* restore outside stack context */
mov first_ssa_gpr(%xbx), %xdx
mov ssa_bp_u(%xdx), %xbp
mov ssa_sp_u(%xdx), %xsp
/*
* set EEXIT registers
* return address can be read from the ECALL frame:
* TD.last_sp ->
* -------------
* | ret_addr |
* | xbp_u |
* | xsp_u |
* | ... |
*/
mov -1*SE_WORDSIZE(%xax), %xbx /* return address */
mov $SE_EEXIT, %xax /* EEXIT leaf */
/* Clear all GPRs, except xax, xbx, xdi, and xsi*/
xor %xcx, %xcx
xor %xdx, %xdx
#ifdef LINUX64
xor %r8, %r8
xor %r9, %r9
xor %r10, %r10
xor %r11, %r11
xor %r12, %r12
xor %r13, %r13
xor %r14, %r14
xor %r15, %r15
#endif
/* Set status flags to pre-defined values */
add %xdx, %xdx /* OF = SF = AF = CF = 0; ZF = PF = 1 */
ENCLU
/*
* ------------------------------------------------------------------
* this function is the wrapper of do_ocall, which is used to
* stick ocall bridge and proxy frame together
* ------------------------------------------------------------------
*/
DECLARE_LOCAL_FUNC __morestack
.cfi_startproc
push %xbp
.cfi_def_cfa_offset 2*SE_WORDSIZE
.cfi_offset xbp,-2*SE_WORDSIZE
mov %xsp, %xbp
.cfi_def_cfa_register xbp
sub $(4*SE_WORDSIZE), %xsp
#ifdef LINUX32
/* save the 2 parameters */
mov (2*SE_WORDSIZE)(%xbp), %xax
mov %xax, (0*SE_WORDSIZE)(%xsp)
mov (3*SE_WORDSIZE)(%xbp), %xax
mov %xax, (1*SE_WORDSIZE)(%xsp)
#endif
call do_ocall
leave
ret
.cfi_endproc
DECLARE_GLOBAL_FUNC asm_oret
#ifdef LINUX32
mov SE_WORDSIZE(%xsp), %xdi
mov 2*SE_WORDSIZE(%xsp), %xsi
#endif
mov %xdi, %xsp /* restore thread_data.last_sp */
mov %xsi, %xax /* ocall return value */
#ifdef LINUX64
mov 7*SE_WORDSIZE(%xsp), %r15
mov 8*SE_WORDSIZE(%xsp), %r14
mov 9*SE_WORDSIZE(%xsp), %r13
mov 10*SE_WORDSIZE(%xsp), %r12
#endif
mov 11*SE_WORDSIZE(%xsp), %xbp
mov 12*SE_WORDSIZE(%xsp), %xdi
mov 13*SE_WORDSIZE(%xsp), %xsi
mov 14*SE_WORDSIZE(%xsp), %xbx
add $(19*SE_WORDSIZE), %xsp
ret
/* should not come here */
ud2
/*
* ------------------------------------------------------------------------
* extern "C" int do_egetkey(key_request_t *key_request, key_128bit_t *key)
* return value:
* 0 - success
* none-zeor - EGETKEY error code
* EGETKEY: rbx - the address of KEYREQUEST structure
* rcx - the address where the key is outputted
* ------------------------------------------------------------------------
*/
DECLARE_LOCAL_FUNC do_egetkey
SE_PROLOG
mov $SE_EGETKEY, %xax /* EGETKEY leaf */
ENCLU
#ifdef SE_SIM
cmp $SGX_SUCCESS, %xax /* In simulation mode, ZF flag will not be set */
jnz .Legetkey_done /* because the stack clean operation will always clean ZF flag */
#else
jz .Legetkey_done /* if EGETKEY error, ZF flag is set and error code is set to xax */
#endif
xor %xax, %xax
.Legetkey_done:
SE_EPILOG
ret
/*
* -------------------------------------------------------------------------
* extern "C" void do_ereport(sgx_target_info_t *target_info, sgx_report_data_t *report_data, sgx_report_t *report);
* EREPORT: rbx - the address of TARGETINFO;
* rcx - the address of REPORTDATA;
* rdx - the address where REPORT is outputted
* -------------------------------------------------------------------------
*/
DECLARE_LOCAL_FUNC do_ereport
SE_PROLOG
mov $SE_EREPORT, %xax /* EREPORT leaf */
ENCLU
SE_EPILOG
ret
#define _RDRAND_RETRY_TIMES 10
/*
* -------------------------------------
* extern "C" uint32_t do_rdrand(uint32_t *rand);
* return value:
* non-zero: rdrand succeeded
* zero: rdrand failed
* -------------------------------------
*/
DECLARE_LOCAL_FUNC do_rdrand
mov $_RDRAND_RETRY_TIMES, %ecx
.Lrdrand_retry:
.byte 0x0F, 0xC7, 0xF0 /* rdrand %eax */
jc .Lrdrand_return
dec %ecx
jnz .Lrdrand_retry
xor %xax, %xax
ret
.Lrdrand_return:
#ifdef LINUX32
mov SE_WORDSIZE(%esp), %ecx
#else
mov %rdi, %rcx
#endif
movl %eax, (%xcx)
mov $1, %xax
ret
/*
* -------------------------------------------------------------------------
* extern "C" void abort(void) __attribute__(__noreturn__);
* -------------------------------------------------------------------------
*/
DECLARE_LOCAL_FUNC abort
lea_pic g_enclave_state, %xax
movl $ENCLAVE_CRASHED, (%xax)
ud2
/*
* -------------------------------------------------------------------------
* extern "C" __attribute__((regparm(1))) void continue_execution(sgx_exception_info_t *info);
* -------------------------------------------------------------------------
*/
DECLARE_LOCAL_FUNC continue_execution
#ifdef LINUX32
mov %xax, %xcx
#else
mov %xdi, %xcx
#endif
mov SE_WORDSIZE*4(%xcx), %xdx
mov %xdx, %xsp
sub $(SE_WORDSIZE), %xsp
#ifdef LINUX64
mov SE_WORDSIZE*17(%xcx), %xax
#else
mov SE_WORDSIZE*9(%xcx), %xax
#endif
mov %xax, (%xsp)
mov SE_WORDSIZE*0(%xcx), %xax
mov SE_WORDSIZE*2(%xcx), %xdx
mov SE_WORDSIZE*3(%xcx), %xbx
mov SE_WORDSIZE*5(%xcx), %xbp
mov SE_WORDSIZE*6(%xcx), %xsi
mov SE_WORDSIZE*7(%xcx), %xdi
#ifdef LINUX64
mov SE_WORDSIZE*8(%xcx), %xsi
mov SE_WORDSIZE*9(%xcx), %xsi
mov SE_WORDSIZE*10(%xcx), %xsi
mov SE_WORDSIZE*11(%xcx), %xsi
mov SE_WORDSIZE*12(%xcx), %xsi
mov SE_WORDSIZE*13(%xcx), %xsi
mov SE_WORDSIZE*14(%xcx), %xsi
mov SE_WORDSIZE*15(%xcx), %xsi
push SE_WORDSIZE*16(%xcx)
popf
#else
push SE_WORDSIZE*8(%xcx)
popf
#endif
mov SE_WORDSIZE*1(%xcx), %xcx
ret

113
sdk/trts/linux/trts_pic.h Normal file
View File

@ -0,0 +1,113 @@
/*
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/*
* This header contains constant definitions for tRTS.
*/
#ifndef TRTS_PIC_H__
#define TRTS_PIC_H__
#include "linux/linux-regs.h"
#include "rts_cmd.h"
#define SE_GUARD_PAGE_SIZE 0x1000
#define ENCLAVE_INIT_NOT_STARTED 0
#define ENCLAVE_INIT_IN_PROGRESS 1
#define ENCLAVE_INIT_DONE 2
#define ENCLAVE_CRASHED 3
/* Status */
#define SGX_SUCCESS 0
#define SGX_ERROR_UNEXPECTED 0x000000001 // Unexpected error
#define SGX_ERROR_INVALID_FUNCTION 0x000001001 // Invalid ecall/ocall function
#define SGX_ERROR_INVALID_ENCLAVE 0x000002001 // The enclave image is incorrect
#define SGX_ERROR_ENCLAVE_CRASHED 0x000001006 // enclave is crashed
#define SGX_ERROR_STACK_OVERRUN 0x000001009 // enclave is running out of stack
#define STATIC_STACK_SIZE (SE_WORDSIZE * 100)
/* Thread Data
* c.f. data structure defintion for thread_data_t in `rts.h'.
*/
#define last_sp (SE_WORDSIZE * 1)
#define stack_base_addr (SE_WORDSIZE * 2)
#define stack_limit_addr (SE_WORDSIZE * 3)
#define first_ssa_gpr (SE_WORDSIZE * 4)
#define self_addr 0
/* SSA GPR */
#define ssa_sp_t 32
#define ssa_sp_u 144
#define ssa_bp_u 152
#define ssa_exit_info 160
#endif
#define EXIT_INFO_VALID 0x80000000
/* OCALL command */
#define OCALL_FLAG 0x04F434944
#define dtv SE_WORDSIZE
#define tls 0
.macro READ_TD_DATA offset
#ifdef SE_SIM
/* TLS support in simulation mode
* see "sdk/simulation/uinst/linux/set_tls.c"
* and "sdk/simulation/assembly/linux/gnu_tls.h"
* TD address (tcs->ofs_base) is set to tcb_head->dtv->value.
* The offset of tcb_head->dtv->value is SE_WORDSIZE.
*/
#if defined(LINUX32)
mov %gs:dtv, %xax
#elif defined(LINUX64)
mov %fs:dtv, %xax
#endif
mov tls(%xax), %xax
mov \offset(%xax), %xax
#else /* SE_SIM */
#if defined(LINUX32)
mov %fs:\offset, %xax
#elif defined(LINUX64)
mov %gs:\offset, %xax
#endif
#endif /* !SE_SIM */
.endm
.macro GET_STACK_BASE tcs
mov \tcs, %xax
sub $SE_GUARD_PAGE_SIZE, %xax
.endm

View File

@ -0,0 +1,45 @@
#
# Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#
include ../../../../buildenv.mk
CPPFLAGS += -I$(LINUX_SDK_DIR)/cpprt/linux/libunwind/src/x86
OBJS := setcontext.o
.PHONY: all
all: $(OBJS)
$(OBJS): %.o: %.S
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
.PHONY: clean
clean:
@$(RM) *.o

View File

@ -0,0 +1,66 @@
/*
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "offsets.h"
.global setcontext
.type setcontext, @function
setcontext:
movl 4(%esp),%eax /* ucontext_t* */
/* restore FP state */
movl LINUX_UC_FPREGS_PTR_OFF(%eax), %ecx
fldenv (%ecx)
#ifdef SE_SIM
/* restore FS */
movl (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FS_OFF)(%eax), %ecx
movl %ecx, %fs
#endif
/* new stack */
movl (LINUX_UC_MCONTEXT_OFF+LINUX_SC_ESP_OFF)(%eax), %esp
/* push the return address on the stack */
movl (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EIP_OFF)(%eax), %ecx
pushl %ecx
/* restore GPRs */
movl (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EDI_OFF)(%eax), %edi
movl (LINUX_UC_MCONTEXT_OFF+LINUX_SC_ESI_OFF)(%eax), %esi
movl (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EBP_OFF)(%eax), %ebp
movl (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EBX_OFF)(%eax), %ebx
movl (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EDX_OFF)(%eax), %edx
movl (LINUX_UC_MCONTEXT_OFF+LINUX_SC_ECX_OFF)(%eax), %ecx
movl (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EAX_OFF)(%eax), %eax
ret

View File

@ -0,0 +1,46 @@
#
# Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#
include ../../../../buildenv.mk
CPPFLAGS += -I$(LINUX_SDK_DIR)/cpprt/linux/libunwind/src/x86_64
CFLAGS += -DISE=1
OBJS := setcontext.o
$(OBJS): %.o: %.S
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
.PHONY: all
all: $(OBJS)
.PHONY: clean
clean:
@$(RM) *.o

View File

@ -0,0 +1,117 @@
/* libunwind - a platform-independent unwind library
Copyright (C) 2007 Google, Inc
Contributed by Arun Sharma <arun.sharma@google.com>
Copyright (C) 2010 Konstantin Belousov <kib@freebsd.org>
This file is part of libunwind.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "ucontext_i.h"
#if (!ISE)
#if defined __linux__
#include <asm/unistd.h>
#define SIG_SETMASK 2
#define SIGSET_BYTE_SIZE (64/8)
#elif defined __FreeBSD__
#include <sys/syscall.h>
#endif
#endif
/* int _Ux86_64_setcontext (const ucontext_t *ucp)
Restores the machine context provided.
Unlike the libc implementation, doesn't clobber %rax
*/
.global _Ux86_64_setcontext
.type _Ux86_64_setcontext, @function
_Ux86_64_setcontext:
#if defined __linux__
#if (!ISE)
/* restore signal mask
sigprocmask(SIG_SETMASK, ucp->uc_sigmask, NULL, sizeof(sigset_t)) */
push %rdi
mov $__NR_rt_sigprocmask, %rax
lea UC_SIGMASK(%rdi), %rsi
mov $SIG_SETMASK, %rdi
xor %rdx, %rdx
mov $SIGSET_BYTE_SIZE, %r10
syscall
pop %rdi
#endif
/* restore fp state */
mov UC_MCONTEXT_FPREGS_PTR(%rdi),%r8
fldenv (%r8)
ldmxcsr FPREGS_OFFSET_MXCSR(%r8)
#elif defined __FreeBSD__
#if (!ISE)
/* restore signal mask */
pushq %rdi
xorl %edx,%edx
leaq UC_SIGMASK(%rdi),%rsi
movl $3,%edi/* SIG_SETMASK */
movl $SYS_sigprocmask,%eax
movq %rcx,%r10
syscall
popq %rdi
#endif
/* restore fp state */
cmpq $UC_MCONTEXT_FPOWNED_FPU,UC_MCONTEXT_OWNEDFP(%rdi)
jne 1f
cmpq $UC_MCONTEXT_FPFMT_XMM,UC_MCONTEXT_FPFORMAT(%rdi)
jne 1f
fxrstor UC_MCONTEXT_FPSTATE(%rdi)
1:
#else
#error Port me
#endif
/* restore the rest of the state */
mov UC_MCONTEXT_GREGS_R8(%rdi),%r8
mov UC_MCONTEXT_GREGS_R9(%rdi),%r9
mov UC_MCONTEXT_GREGS_RBX(%rdi),%rbx
mov UC_MCONTEXT_GREGS_RBP(%rdi),%rbp
mov UC_MCONTEXT_GREGS_R12(%rdi),%r12
mov UC_MCONTEXT_GREGS_R13(%rdi),%r13
mov UC_MCONTEXT_GREGS_R14(%rdi),%r14
mov UC_MCONTEXT_GREGS_R15(%rdi),%r15
mov UC_MCONTEXT_GREGS_RSI(%rdi),%rsi
mov UC_MCONTEXT_GREGS_RDX(%rdi),%rdx
mov UC_MCONTEXT_GREGS_RAX(%rdi),%rax
mov UC_MCONTEXT_GREGS_RCX(%rdi),%rcx
mov UC_MCONTEXT_GREGS_RSP(%rdi),%rsp
/* push the return address on the stack */
mov UC_MCONTEXT_GREGS_RIP(%rdi),%rcx
push %rcx
mov UC_MCONTEXT_GREGS_RCX(%rdi),%rcx
mov UC_MCONTEXT_GREGS_RDI(%rdi),%rdi
retq
.size _Ux86_64_setcontext, . - _Ux86_64_setcontext
/* We do not need executable stack. */
.section .note.GNU-stack,"",@progbits

323
sdk/trts/trts.cpp Normal file
View File

@ -0,0 +1,323 @@
/*
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "sgx_trts.h"
#include "sgx_edger8r.h"
#include "trts_inst.h"
#include <stdlib.h>
#include <string.h>
#include "util.h"
#include "thread_data.h"
#include "global_data.h"
#include "internal/rts.h"
#ifdef SE_SIM
#include "t_instructions.h" /* for `g_global_data_sim' */
#include "sgx_spinlock.h"
#endif
#ifndef SE_SIM
#include "se_cdefs.h"
// add a version to trts
SGX_ACCESS_VERSION(trts, 1);
#endif
// sgx_is_within_enclave()
// Parameters:
// addr - the start address of the buffer
// size - the size of the buffer
// Return Value:
// 1 - the buffer is strictly within the enclave
// 0 - the whole buffer or part of the buffer is not within the enclave,
// or the buffer is wrap around
//
int sgx_is_within_enclave(const void *addr, size_t size)
{
size_t start = reinterpret_cast<size_t>(addr);
size_t end = 0;
size_t enclave_start = (size_t)&__ImageBase;
size_t enclave_end = enclave_start + g_global_data.enclave_size - 1;
// g_global_data.enclave_end = enclave_base + enclave_size - 1;
// so the enclave range is [enclave_start, enclave_end] inclusively
if(size > 0)
{
end = start + size - 1;
}
else
{
end = start;
}
if( (start <= end) && (start >= enclave_start) && (end <= enclave_end) )
{
return 1;
}
return 0;
}
// sgx_is_outside_enclave()
// Parameters:
// addr - the start address of the buffer
// size - the size of the buffer
// Return Value:
// 1 - the buffer is strictly outside the enclave
// 0 - the whole buffer or part of the buffer is not outside the enclave,
// or the buffer is wrap around
//
int sgx_is_outside_enclave(const void *addr, size_t size)
{
size_t start = reinterpret_cast<size_t>(addr);
size_t end = 0;
size_t enclave_start = (size_t)&__ImageBase;
size_t enclave_end = enclave_start + g_global_data.enclave_size - 1;
// g_global_data.enclave_end = enclave_base + enclave_size - 1;
// so the enclave range is [enclave_start, enclave_end] inclusively
if(size > 0)
{
end = start + size - 1;
}
else
{
end = start;
}
if( (start <= end) && ((end < enclave_start) || (start > enclave_end)) )
{
return 1;
}
return 0;
}
// sgx_ocalloc()
// Parameters:
// size - bytes to allocate on the outside stack
// Return Value:
// the pointer to the allocated space on the outside stack
// NULL - fail to allocate
//
// sgx_ocalloc allocates memory on the outside stack. It is only used for OCALL, and will be auto freed when ECALL returns.
// To achieve this, the outside stack pointer in SSA is updated when the stack memory is allocated,
// but the outside stack pointer saved in the ECALL stack frame is not changed accordingly.
// When doing an OCALL, the stack pointer is set as the value in SSA and EEXIT.
// When ECALL or exception handling returns, the stack pointer is set as the value in the ECALL stack frame and then EEXIT,
// so the outside stack is automatically unwind.
// In addition, sgx_ocalloc needs perform outside stack probe to make sure it is not allocating beyond the end of the stack.
#define OC_ROUND 16
void * sgx_ocalloc(size_t size)
{
// read the outside stack address from current SSA
thread_data_t *thread_data = get_thread_data();
ssa_gpr_t *ssa_gpr = reinterpret_cast<ssa_gpr_t *>(thread_data->first_ssa_gpr);
size_t addr = ssa_gpr->REG(sp_u);
// check u_rsp points to the untrusted address.
// if the check fails, it should be hacked. call abort directly
if(!sgx_is_outside_enclave(reinterpret_cast<void *>(addr), sizeof(size_t)))
{
abort();
}
// size is too large to allocate. call abort() directly.
if(addr < size)
{
abort();
}
// calculate the start address for the allocated memory
addr -= size;
addr &= ~(static_cast<size_t>(OC_ROUND - 1)); // for stack alignment
// the allocated memory has overlap with enclave, abort the enclave
if(!sgx_is_outside_enclave(reinterpret_cast<void *>(addr), size))
{
abort();
}
// probe the outside stack to ensure that we do not skip over the stack3 guard page
// we need to probe all the pages including the first page and the last page
// the first page need to be probed in case uRTS didnot touch that page before EENTER enclave
// the last page need to be probed in case the enclave didnot touch that page before another OCALLOC
size_t first_page = TRIM_TO_PAGE(ssa_gpr->REG(sp_u) - 1);
size_t last_page = TRIM_TO_PAGE(addr);
// To avoid the dead-loop in the following for(...) loop.
// Attacker might fake a stack address that is within address 0x4095.
if (last_page == 0)
{
abort();
}
// the compiler may optimize the following code to probe the pages in any order
// while we only expect the probe order should be from higher addr to lower addr
// so use volatile to avoid optimization by the compiler
for(volatile size_t page = first_page; page >= last_page; page -= SE_PAGE_SIZE)
{
*reinterpret_cast<uint8_t *>(page) = 0;
}
// update the outside stack address in the SSA
ssa_gpr->REG(sp_u) = addr;
return reinterpret_cast<void *>(addr);
}
// sgx_ocfree()
// Parameters:
// N/A
// Return Value:
// N/A
// sgx_ocfree restores the original outside stack pointer in the SSA.
// Do not call this function if you still need the buffer allocated by sgx_ocalloc within the ECALL.
void sgx_ocfree()
{
// ECALL stack frame
// last_sp -> | |
// -------------
// | ret_addr |
// | xbp_u |
// | xsp_u |
thread_data_t *thread_data = get_thread_data();
ssa_gpr_t *ssa_gpr = reinterpret_cast<ssa_gpr_t *>(thread_data->first_ssa_gpr);
uintptr_t *addr = reinterpret_cast<uintptr_t *>(thread_data->last_sp);
uintptr_t usp = *(addr - 3);
if(!sgx_is_outside_enclave(reinterpret_cast<void *>(usp), sizeof(uintptr_t)))
{
abort();
}
ssa_gpr->REG(sp_u) = usp;
}
#ifdef SE_SIM
static sgx_spinlock_t g_seed_lock = SGX_SPINLOCK_INITIALIZER;
static uint32_t get_rand_lcg()
{
sgx_spin_lock(&g_seed_lock);
uint32_t& seed = g_global_data_sim.seed;
seed = seed * 1103515245 + 12345;
uint32_t n = (seed % ((uint32_t)RAND_MAX + 1));
sgx_spin_unlock(&g_seed_lock);
return n;
}
#endif
static sgx_status_t __do_get_rand32(uint32_t* rand_num)
{
#ifndef SE_SIM
/* We expect the CPU has RDRAND support for HW mode. Otherwise, an exception will be thrown
* do_rdrand() will try to call RDRAND for 10 times
*/
if(0 == do_rdrand(rand_num))
return SGX_ERROR_UNEXPECTED;
#else
/* use LCG in simulation mode */
*rand_num = get_rand_lcg();
#endif
return SGX_SUCCESS;
}
sgx_status_t sgx_read_rand(unsigned char *rand, size_t length_in_bytes)
{
// check parameters
//
// rand can be within or outside the enclave
if(!rand || !length_in_bytes)
{
return SGX_ERROR_INVALID_PARAMETER;
}
if(!sgx_is_within_enclave(rand, length_in_bytes) && !sgx_is_outside_enclave(rand, length_in_bytes))
{
return SGX_ERROR_INVALID_PARAMETER;
}
// loop to rdrand
uint32_t rand_num = 0;
while(length_in_bytes > 0)
{
sgx_status_t status = __do_get_rand32(&rand_num);
if(status != SGX_SUCCESS)
{
return status;
}
size_t size = (length_in_bytes < sizeof(rand_num)) ? length_in_bytes : sizeof(rand_num);
memcpy(rand, &rand_num, size);
rand += size;
length_in_bytes -= size;
}
memset_s(&rand_num, sizeof(rand_num), 0, sizeof(rand_num));
return SGX_SUCCESS;
}
#include "trts_internal.h"
extern "C" int enter_enclave(int index, void *ms, void *tcs, int cssa)
{
if(get_enclave_state() == ENCLAVE_CRASHED)
{
return SGX_ERROR_ENCLAVE_CRASHED;
}
sgx_status_t error = SGX_ERROR_UNEXPECTED;
if(cssa == 0)
{
if(index >= 0)
{
error = do_ecall(index, ms, tcs);
}
else if(index == ECMD_INIT_ENCLAVE)
{
error = do_init_enclave(ms);
}
else if(index == ECMD_ORET)
{
error = do_oret(ms);
}
}
else if((cssa == 1) && (index == ECMD_EXCEPT))
{
error = trts_handle_exception(tcs);
}
if(error == SGX_ERROR_UNEXPECTED)
{
set_enclave_state(ENCLAVE_CRASHED);
}
return error;
}

189
sdk/trts/trts_ecall.cpp Normal file
View File

@ -0,0 +1,189 @@
/*
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "se_memcpy.h"
#include "thread_data.h"
#include "global_data.h"
#include "rts.h"
#include "util.h"
#include "xsave.h"
#include "sgx_trts.h"
#include "sgx_spinlock.h"
#include "global_init.h"
#include "trts_internal.h"
# include "linux/elf_parser.h"
# define GET_TLS_INFO elf_tls_info
// is_ecall_allowed()
// check the index in the dynamic entry table
static sgx_status_t is_ecall_allowed(uint32_t ordinal)
{
if(ordinal >= g_ecall_table.nr_ecall)
{
return SGX_ERROR_INVALID_FUNCTION;
}
thread_data_t *thread_data = get_thread_data();
if(thread_data->last_sp == thread_data->stack_base_addr)
{
// root ECALL, check the priv bits.
if (g_ecall_table.ecall_table[ordinal].is_priv)
return SGX_ERROR_ECALL_NOT_ALLOWED;
return SGX_SUCCESS;
}
ocall_context_t *context = reinterpret_cast<ocall_context_t*>(thread_data->last_sp);
if(context->ocall_flag != OCALL_FLAG)
{
// abort the enclave if ocall frame is invalid
abort();
}
uintptr_t ocall_index = context->ocall_index;
if(ocall_index >= g_dyn_entry_table.nr_ocall)
{
return SGX_ERROR_INVALID_FUNCTION;
}
return (g_dyn_entry_table.entry_table[ocall_index * g_ecall_table.nr_ecall + ordinal] ? SGX_SUCCESS : SGX_ERROR_ECALL_NOT_ALLOWED);
}
// get_func_addr()
// Get the address of ecall function from the ecall table
// Parameters:
// [IN] ordinal - the index of the ecall function in the ecall table
// Return Value:
// non-zero - success
// zero - fail
//
static sgx_status_t get_func_addr(uint32_t ordinal, void **addr)
{
sgx_status_t status = is_ecall_allowed(ordinal);
if(SGX_SUCCESS != status)
{
return status;
}
*addr = const_cast<void *>(g_ecall_table.ecall_table[ordinal].ecall_addr);
if(!sgx_is_within_enclave(*addr, 0))
{
return SGX_ERROR_UNEXPECTED;
}
return SGX_SUCCESS;
}
static volatile bool g_is_first_ecall = true;
static volatile sgx_spinlock_t g_ife_lock = SGX_SPINLOCK_INITIALIZER;
typedef sgx_status_t (*ecall_func_t)(void *ms);
static sgx_status_t trts_ecall(uint32_t ordinal, void *ms)
{
if (unlikely(g_is_first_ecall))
{
// The thread performing the global initialization cannot do a nested ECall
thread_data_t *thread_data = get_thread_data();
if (thread_data->last_sp != thread_data->stack_base_addr)
{ // nested ecall
return SGX_ERROR_ECALL_NOT_ALLOWED;
}
sgx_spin_lock(&g_ife_lock);
if (g_is_first_ecall)
{
//invoke global object's construction
init_global_object();
g_is_first_ecall = false;
}
sgx_spin_unlock(&g_ife_lock);
}
void *addr = NULL;
sgx_status_t status = get_func_addr(ordinal, &addr);
if(status == SGX_SUCCESS)
{
ecall_func_t func = (ecall_func_t)addr;
status = func(ms);
}
// clean extended registers, no need to save
CLEAN_XFEATURE_REGS
return status;
}
extern "C" void init_stack_guard();
static sgx_status_t do_init_thread(void *tcs)
{
thread_data_t *thread_data = GET_PTR(thread_data_t, tcs, g_global_data.td_template.self_addr);
memcpy_s(thread_data, SE_PAGE_SIZE, const_cast<thread_data_t *>(&g_global_data.td_template), sizeof(thread_data_t));
thread_data->last_sp += (size_t)tcs;
thread_data->self_addr += (size_t)tcs;
thread_data->stack_base_addr += (size_t)tcs;
thread_data->stack_limit_addr += (size_t)tcs;
thread_data->first_ssa_gpr += (size_t)tcs;
thread_data->tls_array += (size_t)tcs;
thread_data->tls_addr += (size_t)tcs;
thread_data->last_sp -= (size_t)STATIC_STACK_SIZE;
thread_data->stack_base_addr -= (size_t)STATIC_STACK_SIZE;
uintptr_t tls_addr = 0;
size_t tdata_size = 0;
if(0 != GET_TLS_INFO(&__ImageBase, &tls_addr, &tdata_size))
{
return SGX_ERROR_UNEXPECTED;
}
if(tls_addr)
{
memset((void *)TRIM_TO_PAGE(thread_data->tls_addr), 0, ROUND_TO_PAGE(thread_data->self_addr - thread_data->tls_addr));
memcpy_s((void *)(thread_data->tls_addr), thread_data->self_addr - thread_data->tls_addr, (void *)tls_addr, tdata_size);
}
init_stack_guard();
return SGX_SUCCESS;
}
sgx_status_t do_ecall(int index, void *ms, void *tcs)
{
sgx_status_t status = SGX_ERROR_UNEXPECTED;
if(ENCLAVE_INIT_DONE != get_enclave_state())
{
return status;
}
thread_data_t *thread_data = get_thread_data();
if( (NULL == thread_data) || ((thread_data->stack_base_addr == thread_data->last_sp) && (0 != g_global_data.thread_policy)))
{
status = do_init_thread(tcs);
if(0 != status)
{
return status;
}
}
status = trts_ecall(index, ms);
return status;
}

79
sdk/trts/trts_internal.h Normal file
View File

@ -0,0 +1,79 @@
/*
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TRTS_INTERNAL_H
#define TRTS_INTERNAL_H
#include "util.h"
#ifdef SE_64
#define STATIC_STACK_SIZE 8*100
#else
#define STATIC_STACK_SIZE 4*100
#endif
#define TD2TCS(td) ((const void *)(((thread_data_t*)(td))->stack_base_addr + (size_t)STATIC_STACK_SIZE + (size_t)SE_GUARD_PAGE_SIZE))
typedef struct {
const void *ecall_addr;
uint8_t is_priv;
} ecall_addr_t;
typedef struct {
size_t nr_ecall;
ecall_addr_t ecall_table[1];
} ecall_table_t;
typedef struct {
size_t nr_ocall;
uint8_t entry_table[1];
} entry_table_t;
#ifdef __cplusplus
extern "C" {
#endif
extern ecall_table_t g_ecall_table;
extern entry_table_t g_dyn_entry_table;
int lock_enclave();
void *get_enclave_base();
int get_enclave_state();
void set_enclave_state(int state);
sgx_status_t do_init_enclave(void *ms);
sgx_status_t do_ecall(int index, void *ms, void *tcs);
sgx_status_t do_oret(void *ms);
sgx_status_t trts_handle_exception(void *tcs);
#ifdef __cplusplus
}
#endif
#endif

143
sdk/trts/trts_ocall.cpp Normal file
View File

@ -0,0 +1,143 @@
/*
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <string.h>
#include "thread_data.h"
#include "global_data.h"
#include "sgx_edger8r.h"
#include "rts.h"
#include "util.h"
#include "xsave.h"
#include "trts_internal.h"
extern "C" sgx_status_t asm_oret(uintptr_t sp, void *ms);
extern "C" sgx_status_t __morestack(const unsigned int index, void *ms);
#define do_ocall __morestack
//
// sgx_ocall
// Parameters:
// index - the index in the ocall table
// ms - the mashalling structure
// Return Value:
// OCALL status
//
sgx_status_t sgx_ocall(const unsigned int index, void *ms)
{
// sgx_ocall is not allowed during exception handling
thread_data_t *thread_data = get_thread_data();
// we have exceptions being handled
if(thread_data->exception_flag != 0) {
return SGX_ERROR_OCALL_NOT_ALLOWED;
}
// the OCALL index should be within the ocall table range
if(static_cast<size_t>(index) >= g_dyn_entry_table.nr_ocall)
{
return SGX_ERROR_INVALID_FUNCTION;
}
// save and clean extended feature registers
uint8_t buffer[FXSAVE_SIZE] = {0};
save_and_clean_xfeature_regs(buffer);
// do sgx_ocall
sgx_status_t status = do_ocall(index, ms);
// restore extended feature registers
restore_xfeature_regs(buffer);
// clear buffer to avoid secret leaking
memset_s(buffer, FXSAVE_SIZE, 0, FXSAVE_SIZE);
return status;
}
extern "C"
uintptr_t update_ocall_lastsp(ocall_context_t* context)
{
thread_data_t* thread_data = get_thread_data();
uintptr_t last_sp = 0;
last_sp = thread_data->last_sp;
context->pre_last_sp = last_sp;
if (context->pre_last_sp == thread_data->stack_base_addr)
{
context->ocall_depth = 1;
} else {
// thread_data->last_sp is only set when ocall or exception handling occurs
// ocall is block during exception handling, so last_sp is always ocall frame here
ocall_context_t* context_pre = reinterpret_cast<ocall_context_t*>(context->pre_last_sp);
context->ocall_depth = context_pre->ocall_depth + 1;
}
thread_data->last_sp = reinterpret_cast<uintptr_t>(context);
return last_sp;
}
sgx_status_t do_oret(void *ms)
{
thread_data_t *thread_data = get_thread_data();
uintptr_t last_sp = thread_data->last_sp;
ocall_context_t *context = reinterpret_cast<ocall_context_t*>(thread_data->last_sp);
if(0 == last_sp)
{
return SGX_ERROR_UNEXPECTED;
}
// At least 1 ecall frame and 1 ocall frame are expected on stack.
// 30 is an estimated value: 8 for enclave_entry and 22 for do_ocall.
if(last_sp > thread_data->stack_base_addr - 30 * sizeof(size_t))
{
goto invalid_ocall_frame;
}
if(context->ocall_flag != OCALL_FLAG)
{
goto invalid_ocall_frame;
}
if(context->pre_last_sp > thread_data->stack_base_addr)
{
goto invalid_ocall_frame;
}
if(context->pre_last_sp <= (uintptr_t)&context)
{
goto invalid_ocall_frame;
}
thread_data->last_sp = context->pre_last_sp;
asm_oret(last_sp, ms);
invalid_ocall_frame:
return SGX_ERROR_UNEXPECTED;
}

55
sdk/trts/trts_util.cpp Normal file
View File

@ -0,0 +1,55 @@
/*
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "trts_util.h"
#include "global_data.h"
#include "util.h"
#include "thread_data.h"
// No need to check the state of enclave or thread.
// The functions should be called within an ECALL, so the enclave and thread must be initialized at that time.
void * get_heap_base(void)
{
return GET_PTR(void, &__ImageBase, g_global_data.heap_offset);
}
size_t get_heap_size(void)
{
return g_global_data.heap_size;
}
int * get_errno_addr(void)
{
thread_data_t *thread_data = get_thread_data();
return reinterpret_cast<int *>(&thread_data->last_error);
}

52
sdk/trts/trts_util.h Normal file
View File

@ -0,0 +1,52 @@
/*
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef _TRTS_UTIL_H_
#define _TRTS_UTIL_H_
#include <stddef.h> /* for size_t */
#include "se_types.h"
#ifdef __cplusplus
extern "C" {
#endif
void * get_heap_base(void);
size_t get_heap_size(void);
int * get_errno_addr(void);
#ifdef __cplusplus
}
#endif
#endif

395
sdk/trts/trts_veh.cpp Normal file
View File

@ -0,0 +1,395 @@
/*
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**
* File: trts_veh.cpp
* Description:
* This file implements the support of custom exception handling.
*/
#include "sgx_trts_exception.h"
#include <stdlib.h>
#include "sgx_trts.h"
#include "xsave.h"
#include "arch.h"
#include "sgx_spinlock.h"
#include "thread_data.h"
#include "global_data.h"
#include "trts_internal.h"
typedef struct _handler_node_t
{
uintptr_t callback;
struct _handler_node_t *next;
} handler_node_t;
static handler_node_t *g_first_node = NULL;
static sgx_spinlock_t g_handler_lock = SGX_SPINLOCK_INITIALIZER;
static uintptr_t g_veh_cookie = 0;
#define ENC_VEH_POINTER(x) (uintptr_t)(x) ^ g_veh_cookie
#define DEC_VEH_POINTER(x) (sgx_exception_handler_t)((x) ^ g_veh_cookie)
static bool is_stack_addr(void *address, size_t size)
{
thread_data_t *thread_data = get_thread_data();
size_t stack_base = thread_data->stack_base_addr;
size_t stack_top = thread_data->stack_limit_addr;
size_t addr = (size_t) address;
return (addr <= (addr + size)) && (stack_base >= (addr + size)) && (stack_top <= addr);
}
static bool is_valid_sp(uintptr_t sp)
{
return ( !(sp & (sizeof(uintptr_t) - 1)) // sp is expected to be 4/8 bytes aligned
&& is_stack_addr((void*)sp, 0) ); // sp points to the top/bottom of stack are accepted
}
// sgx_register_exception_handler()
// register a custom exception handler
// Parameter
// is_first_handler - the order in which the handler should be called.
// if the parameter is nonzero, the handler is the first handler to be called.
// if the parameter is zero, the handler is the last handler to be called.
// exception_handler - a pointer to the handler to be called.
// Return Value
// handler - success
// NULL - fail
void *sgx_register_exception_handler(int is_first_handler, sgx_exception_handler_t exception_handler)
{
// initialize g_veh_cookie for the first time sgx_register_exception_handler is called.
if(unlikely(g_veh_cookie == 0))
{
uintptr_t rand = 0;
do
{
if(SGX_SUCCESS != sgx_read_rand((unsigned char *)&rand, sizeof(rand)))
{
return NULL;
}
} while(rand == 0);
sgx_spin_lock(&g_handler_lock);
if(g_veh_cookie == 0)
{
g_veh_cookie = rand;
}
sgx_spin_unlock(&g_handler_lock);
}
if(!sgx_is_within_enclave((const void*)exception_handler, 0))
{
return NULL;
}
handler_node_t *node = (handler_node_t *)malloc(sizeof(handler_node_t));
if(!node)
{
return NULL;
}
node->callback = ENC_VEH_POINTER(exception_handler);
// write lock
sgx_spin_lock(&g_handler_lock);
if((g_first_node == NULL) || is_first_handler)
{
node->next = g_first_node;
g_first_node = node;
}
else
{
handler_node_t *tmp = g_first_node;
while(tmp->next != NULL)
{
tmp = tmp->next;
}
node->next = NULL;
tmp->next = node;
}
// write unlock
sgx_spin_unlock(&g_handler_lock);
return node;
}
// sgx_unregister_exception_handler()
// unregister a custom exception handler.
// Parameter
// handler - a handler to the custom exception handler previously
// registered using the sgx_register_exception_handler function.
// Return Value
// none zero - success
// 0 - fail
int sgx_unregister_exception_handler(void *handler)
{
if(!handler)
{
return 0;
}
int status = 0;
// write lock
sgx_spin_lock(&g_handler_lock);
if(g_first_node)
{
handler_node_t *node = g_first_node;
if(node == handler)
{
g_first_node = node->next;
status = 1;
}
else
{
while(node->next != NULL)
{
if(node->next == handler)
{
node->next = node->next->next;
status = 1;
break;
}
node = node->next;
}
}
}
// write unlock
sgx_spin_unlock(&g_handler_lock);
if(status) free(handler);
return status;
}
// continue_execution(sgx_exception_info_t *info):
// try to restore the thread context saved in info to current execution context.
extern "C" __attribute__((regparm(1))) void continue_execution(sgx_exception_info_t *info);
// internal_handle_exception(sgx_exception_info_t *info):
// the 2nd phrase exception handing, which traverse registered exception handlers.
// if the exception can be handled, then continue execution
// otherwise, throw abortion, go back to 1st phrase, and call the default handler.
extern "C" __attribute__((regparm(1))) void internal_handle_exception(sgx_exception_info_t *info)
{
int status = EXCEPTION_CONTINUE_SEARCH;
handler_node_t *node = NULL;
thread_data_t *thread_data = get_thread_data();
size_t size = 0;
uintptr_t *nhead = NULL;
uintptr_t *ntmp = NULL;
uintptr_t xsp = 0;
if (thread_data->exception_flag < 0)
goto failed_end;
thread_data->exception_flag++;
// read lock
sgx_spin_lock(&g_handler_lock);
node = g_first_node;
while(node != NULL)
{
size += sizeof(uintptr_t);
node = node->next;
}
if (size == 0 || (nhead = (uintptr_t *)malloc(size)) == NULL)
{
sgx_spin_unlock(&g_handler_lock);
goto failed_end;
}
ntmp = nhead;
node = g_first_node;
while(node != NULL)
{
*ntmp = node->callback;
ntmp++;
node = node->next;
}
// read unlock
sgx_spin_unlock(&g_handler_lock);
// call exception handler until EXCEPTION_CONTINUE_EXECUTION is returned
ntmp = nhead;
while(size > 0)
{
sgx_exception_handler_t handler = DEC_VEH_POINTER(*ntmp);
status = handler(info);
if(EXCEPTION_CONTINUE_EXECUTION == status)
{
break;
}
ntmp++;
size -= sizeof(sgx_exception_handler_t);
}
free(nhead);
// call default handler
// ignore invalid return value, treat to EXCEPTION_CONTINUE_SEARCH
// check SP to be written on SSA is pointing to the trusted stack
xsp = info->cpu_context.REG(sp);
if (!is_valid_sp(xsp))
{
goto failed_end;
}
if(EXCEPTION_CONTINUE_EXECUTION == status)
{
//exception is handled, decrease the nested exception count
thread_data->exception_flag--;
}
else
{
//exception cannot be handled
thread_data->exception_flag = -1;
}
//instruction triggering the exception will be executed again.
continue_execution(info);
failed_end:
thread_data->exception_flag = -1; // mark the current exception cannot be handled
abort(); // throw abortion
}
// trts_handle_exception(void *tcs)
// the entry point for the exceptoin handling
// Parameter
// the pointer of TCS
// Return Value
// none zero - success
// 0 - fail
#include "trts_internal.h"
extern "C" sgx_status_t trts_handle_exception(void *tcs)
{
thread_data_t *thread_data = get_thread_data();
ssa_gpr_t *ssa_gpr = NULL;
sgx_exception_info_t *info = NULL;
uintptr_t sp, *new_sp = NULL;
size_t size = 0;
if (tcs == NULL) goto default_handler;
if(get_enclave_state() != ENCLAVE_INIT_DONE)
{
goto default_handler;
}
// check if the exception is raised from 2nd phrase
if(thread_data->exception_flag == -1) {
goto default_handler;
}
if ((TD2TCS(thread_data) != tcs)
|| (((thread_data->first_ssa_gpr)&(~0xfff)) - SE_PAGE_SIZE) != (uintptr_t)tcs) {
goto default_handler;
}
// no need to check the result of ssa_gpr because thread_data is always trusted
ssa_gpr = reinterpret_cast<ssa_gpr_t *>(thread_data->first_ssa_gpr);
sp = ssa_gpr->REG(sp);
if(!is_stack_addr((void*)sp, 0)) // check stack overrun only, alignment will be checked after exception handled
{
g_enclave_state = ENCLAVE_CRASHED;
return SGX_ERROR_STACK_OVERRUN;
}
size = 0;
#ifdef SE_GNU64
size += 128; // preserve stack for red zone (128 bytes)
#endif
// decrease the stack to give space for info
size += sizeof(sgx_exception_info_t);
sp -= size;
sp = sp & ~0xF;
// check the decreased sp to make sure it is in the trusted stack range
if(!is_stack_addr((void *)sp, size))
{
g_enclave_state = ENCLAVE_CRASHED;
return SGX_ERROR_STACK_OVERRUN;
}
if(ssa_gpr->exit_info.valid != 1)
{ // exception handlers are not allowed to call in a non-exception state
goto default_handler;
}
info = (sgx_exception_info_t *)sp;
// No need to check the stack as it have already been checked by assembly code
// initialize the info with SSA[0]
info->exception_vector = (sgx_exception_vector_t)ssa_gpr->exit_info.vector;
info->exception_type = (sgx_exception_type_t)ssa_gpr->exit_info.exit_type;
info->cpu_context.REG(ax) = ssa_gpr->REG(ax);
info->cpu_context.REG(cx) = ssa_gpr->REG(cx);
info->cpu_context.REG(dx) = ssa_gpr->REG(dx);
info->cpu_context.REG(bx) = ssa_gpr->REG(bx);
info->cpu_context.REG(sp) = ssa_gpr->REG(sp);
info->cpu_context.REG(bp) = ssa_gpr->REG(bp);
info->cpu_context.REG(si) = ssa_gpr->REG(si);
info->cpu_context.REG(di) = ssa_gpr->REG(di);
info->cpu_context.REG(flags) = ssa_gpr->REG(flags);
info->cpu_context.REG(ip) = ssa_gpr->REG(ip);
#ifdef SE_64
info->cpu_context.r8 = ssa_gpr->r8;
info->cpu_context.r9 = ssa_gpr->r9;
info->cpu_context.r10 = ssa_gpr->r10;
info->cpu_context.r11 = ssa_gpr->r11;
info->cpu_context.r12 = ssa_gpr->r12;
info->cpu_context.r13 = ssa_gpr->r13;
info->cpu_context.r14 = ssa_gpr->r14;
info->cpu_context.r15 = ssa_gpr->r15;
#endif
// decrease the stack to save the SSA[0]->ip
size = sizeof(uintptr_t);
new_sp = (uintptr_t *)(sp - size);
if(!is_stack_addr(new_sp, size))
{
g_enclave_state = ENCLAVE_CRASHED;
return SGX_ERROR_STACK_OVERRUN;
}
ssa_gpr->REG(ip) = (size_t)internal_handle_exception; // prepare the ip for 2nd phrase handling
ssa_gpr->REG(sp) = (size_t)new_sp; // new stack for internal_handle_exception
ssa_gpr->REG(ax) = (size_t)info; // 1st parameter (info) for LINUX32
ssa_gpr->REG(di) = (size_t)info; // 1st parameter (info) for LINUX64, LINUX32 also uses it while restoring the context
*new_sp = info->cpu_context.REG(ip); // for debugger to get call trace
return SGX_SUCCESS;
default_handler:
g_enclave_state = ENCLAVE_CRASHED;
return SGX_ERROR_ENCLAVE_CRASHED;
}

48
sdk/trts/trts_version.cpp Normal file
View File

@ -0,0 +1,48 @@
/*
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "se_version.h"
#define __CONCAT(x, y) x/**/y
#define SGX_TRTS_VERSION_STR __CONCAT("SGX_TRTS_VERSION_", STRFILEVER)
#ifdef __cplusplus
extern "C" {
#endif
__attribute__((visibility("default")))
const char * sgx_trts_version = SGX_TRTS_VERSION_STR;
#ifdef __cplusplus
}
#endif

112
sdk/trts/trts_xsave.cpp Normal file
View File

@ -0,0 +1,112 @@
/*
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "arch.h"
#include "xsave.h"
#include "trts_inst.h"
#include "util.h"
// 'SYNTHETIC_STATE' buffer size is (512 + 64 + 256) bytes
// 512 for fxsave buffer,
// 64 for xsave header,
// 256 for YMM State (16 * 16 bytes of each YMMH-register)
// and the buffer should be 64 byte aligned.
#define SYNTHETIC_STATE_SIZE (512 + 64 + 256)
se_static_assert(SYNTHETIC_STATE_SIZE <= SE_PAGE_SIZE);
static SE_DECLSPEC_ALIGN(4096) const uint16_t
SYNTHETIC_STATE[SYNTHETIC_STATE_SIZE/sizeof(uint16_t)] = {
0x037F, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1F80, 0, 0xFFFF, 0
};
static int g_xsave_enabled; // flag to indicate whether xsave is enabled or not
// EENTER will set xcr0 with secs.attr.xfrm,
// So use the xfeature mask from report instead of calling xgetbv
uint64_t get_xfeature_state()
{
// target_info and report_data are useless
// we only need to make sure their alignment and within enclave
// so set the pointers to SYNTHETIC_STATE
sgx_target_info_t *target_info = (sgx_target_info_t *)SYNTHETIC_STATE;
sgx_report_data_t *report_data = (sgx_report_data_t *)SYNTHETIC_STATE;
uint8_t buffer[sizeof(sgx_report_t) + REPORT_ALIGN_SIZE -1] = {0};
sgx_report_t *report = (sgx_report_t *)ROUND_TO((size_t)buffer, REPORT_ALIGN_SIZE);
do_ereport(target_info, report_data, report);
g_xsave_enabled = (report->body.attributes.xfrm == SGX_XFRM_LEGACY) ? 0 : 1;
uint64_t xfrm = report->body.attributes.xfrm;
// no secrets in target_info, report_data, and report. no need to clear them before return
// tlibc functions cannot be used before calling init_optimized_libs().
return xfrm;
}
// save_and_clean_xfeature_regs()
// do fwait, fxsave, and then clean the extended feature registers
// Parameters:
// buffer - If the pointer is not NULL, save the CPU state to the memory
// Return Value:
// none
void save_and_clean_xfeature_regs(uint8_t *buffer)
{
do_fwait();
if(buffer != 0)
{
uint8_t *buf = (uint8_t*)ROUND_TO((size_t)buffer, FXSAVE_ALIGN_SIZE);
do_fxsave(buf);
}
if(g_xsave_enabled)
{
do_xrstor(SYNTHETIC_STATE);
}
else
{
do_fxrstor(SYNTHETIC_STATE);
}
}
// restore_xfeature_regs()
// restore the extended feature registers
//
void restore_xfeature_regs(const uint8_t *buffer)
{
if(buffer != 0)
{
uint8_t *buf = (uint8_t*)ROUND_TO((size_t)buffer, FXSAVE_ALIGN_SIZE);
do_fxrstor(buf);
}
}