github.com/epfl-dcsl/gotee@v0.0.0-20200909122901-014b35f5e5e9/src/gosec/sim.go (about)

     1  package gosec
     2  
     3  /* This file implements a simulated environnement to load and execute enclave
     4   * binaries without sgx.
     5   */
     6  
     7  import (
     8  	"debug/elf"
     9  	"fmt"
    10  	"log"
    11  	"runtime"
    12  	"sort"
    13  	"syscall"
    14  	"unsafe"
    15  )
    16  
    17  func simLoadProgram(path string) {
    18  	fmt.Println("[DEBUG] loading the program in simulation.")
    19  	file, err := elf.Open(path)
    20  	check(err)
    21  	_, enclWrap = sgxCreateSecs(file)
    22  	enclWrap.isSim = true
    23  	srcWrap = transposeOutWrapper(enclWrap)
    24  	defer func() { check(file.Close()) }()
    25  
    26  	// Check that the sections are sorted now.
    27  	sort.Sort(SortedElfSections(file.Sections))
    28  
    29  	var aggreg []*elf.Section
    30  	for _, sec := range file.Sections {
    31  		if sec.Flags&elf.SHF_ALLOC != elf.SHF_ALLOC {
    32  			continue
    33  		}
    34  		if len(aggreg) == 0 || aggreg[len(aggreg)-1].Flags == sec.Flags {
    35  			aggreg = append(aggreg, sec)
    36  			continue
    37  		}
    38  		mapSections(aggreg)
    39  		aggreg = nil
    40  		aggreg = append(aggreg, sec)
    41  	}
    42  	mapSections(aggreg)
    43  
    44  	//For debugging.
    45  	enclWrap.DumpDebugInfo()
    46  	// Map the enclave preallocated heap.
    47  	simPreallocate(enclWrap)
    48  
    49  	for _, tcs := range enclWrap.tcss {
    50  		prot := _PROT_READ | _PROT_WRITE
    51  		manon := _MAP_PRIVATE | _MAP_ANON | _MAP_FIXED
    52  		// mmap the stack
    53  		_, err = syscall.RMmap(tcs.Stack, int(tcs.Ssiz), prot, manon, -1, 0)
    54  		check(err)
    55  	}
    56  
    57  	// register the heap, setup the enclave stack
    58  	etcs := enclWrap.defaultTcs()
    59  	etcs.Used = true
    60  	srcWrap.defaultTcs().Used = true
    61  	runtime.Cooprt.Tcss = enclWrap.tcss
    62  	_ = runtime.SetupEnclSysStack(etcs.Stack+etcs.Ssiz, enclWrap.mhstart)
    63  
    64  	// Create the thread for enclave, setups the stacks.
    65  	fn := unsafe.Pointer(uintptr(file.Entry))
    66  	enclWrap.entry = uintptr(fn)
    67  	dtcs, stcs := enclWrap.defaultTcs(), srcWrap.defaultTcs()
    68  	dtcs.Used, stcs.Used = true, true
    69  	sgxEEnter(uint64(0), dtcs, stcs, nil)
    70  }
    71  
    72  func simPreallocate(wrap *sgx_wrapper) {
    73  	prot := _PROT_READ | _PROT_WRITE
    74  	flags := _MAP_ANON | _MAP_FIXED | _MAP_PRIVATE
    75  
    76  	// The span
    77  	_, err := syscall.RMmap(wrap.mhstart, int(wrap.mhsize), prot,
    78  		flags, -1, 0)
    79  	check(err)
    80  
    81  	// The memory buffer for mmap calls.
    82  	_, err = syscall.RMmap(wrap.membuf, int(MEMBUF_SIZE), prot,
    83  		flags, -1, 0)
    84  	check(err)
    85  }
    86  
    87  // mapSections mmaps the elf sections.
    88  // If wrap nil, simple mmap. Otherwise, mmap to another address space specified
    89  // by wrap.mmask for SGX.
    90  func mapSections(secs []*elf.Section) {
    91  	if len(secs) == 0 {
    92  		return
    93  	}
    94  
    95  	start := uintptr(secs[0].Addr)
    96  	end := uintptr(secs[len(secs)-1].Addr + secs[len(secs)-1].Size)
    97  	size := int(end - start)
    98  	if start >= end {
    99  		log.Fatalf("Error, sections are not ordered: %#x - %#x", start, end)
   100  	}
   101  
   102  	prot := _PROT_READ | _PROT_WRITE
   103  	b, err := syscall.RMmap(start, size, prot, _MAP_PRIVATE|_MAP_ANON, -1, 0)
   104  	check(err)
   105  
   106  	for _, sec := range secs {
   107  		if sec.Type == elf.SHT_NOBITS {
   108  			continue
   109  		}
   110  		data, err := sec.Data()
   111  		check(err)
   112  		offset := int(sec.Addr - uint64(start))
   113  		for i := range data {
   114  			b[offset+i] = data[i]
   115  		}
   116  	}
   117  	prot = _PROT_READ
   118  	if (secs[0].Flags & elf.SHF_WRITE) == elf.SHF_WRITE {
   119  		prot |= _PROT_WRITE
   120  	}
   121  
   122  	if (secs[0].Flags & elf.SHF_EXECINSTR) == elf.SHF_EXECINSTR {
   123  		prot |= _PROT_EXEC
   124  	}
   125  
   126  	err = syscall.Mprotect(b, prot)
   127  	check(err)
   128  }