Browse Source

[Pal/Linux-SGX] Add memory gap around 'exec' area

For this also add the user_address_hole memory range to pal_control.
This is needed to communicate (in a not SGX specific way) the reserved
memory range for the memory gaps around the exec area which can be
inside of the user_address range.
Simon Gaiser 4 years ago
parent
commit
7ce7278121

+ 10 - 1
LibOS/shim/src/bookkeep/shim_vma.c

@@ -54,7 +54,7 @@ struct shim_vma {
 
 #define VMA_MGR_ALLOC   DEFAULT_VMA_COUNT
 #define PAGE_SIZE       allocsize
-#define RESERVED_VMAS   4
+#define RESERVED_VMAS   6
 
 static struct shim_vma * reserved_vmas[RESERVED_VMAS];
 static struct shim_vma early_vmas[RESERVED_VMAS];
@@ -292,6 +292,15 @@ int init_vma (void)
 
     /* Bookkeeping for preloaded areas */
 
+    if (PAL_CB(user_address_hole.end) - PAL_CB(user_address_hole.start) > 0) {
+        ret = __bkeep_preloaded(PAL_CB(user_address_hole.start),
+                                PAL_CB(user_address_hole.end),
+                                PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|VMA_UNMAPPED,
+                                "reserved");
+        if (ret < 0)
+            return ret;
+    }
+
     ret = __bkeep_preloaded(PAL_CB(executable_range.start),
                             PAL_CB(executable_range.end),
                             PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|VMA_UNMAPPED,

+ 6 - 0
LibOS/shim/src/sys/shim_brk.c

@@ -86,6 +86,12 @@ int init_brk_region(void* brk_region, size_t data_segment_size) {
         if (PAL_CB(user_address.end) >= PAL_CB(executable_range.end))
             max_brk = PAL_CB(user_address.end) - PAL_CB(executable_range.end);
 
+        if (PAL_CB(user_address_hole.end) - PAL_CB(user_address_hole.start) > 0) {
+            /* XXX: This assumes that we always want brk to be after the hole. */
+            brk_region = MAX(brk_region, PAL_CB(user_address_hole.end));
+            max_brk = MIN(max_brk, (size_t) (PAL_CB(user_address.end) - PAL_CB(user_address_hole.end)));
+        }
+
         /* Check whether the brk region can potentially be located after exec at all. */
         if (brk_max_size <= max_brk) {
             int try;

+ 3 - 1
Pal/src/db_main.c

@@ -442,7 +442,9 @@ noreturn void pal_main (
     __pal_control.first_thread       = first_thread;
 
     _DkGetAvailableUserAddressRange(&__pal_control.user_address.start,
-                                    &__pal_control.user_address.end);
+                                    &__pal_control.user_address.end,
+                                    &__pal_control.user_address_hole.start,
+                                    &__pal_control.user_address_hole.end);
 
     __pal_control.pagesize           = pal_state.pagesize;
     __pal_control.alloc_align        = pal_state.alloc_align;

+ 6 - 1
Pal/src/host/FreeBSD/db_main.c

@@ -135,7 +135,8 @@ unsigned long _DkGetAllocationAlignment (void)
     return pagesz;
 }
 
-void _DkGetAvailableUserAddressRange (PAL_PTR * start, PAL_PTR * end)
+void _DkGetAvailableUserAddressRange (PAL_PTR * start, PAL_PTR * end,
+                                      PAL_PTR * hole_start, PAL_PTR * hole_end)
 {
     void * end_addr, * start_addr;
 
@@ -171,6 +172,10 @@ void _DkGetAvailableUserAddressRange (PAL_PTR * start, PAL_PTR * end)
 
     *end   = (PAL_PTR) end_addr;
     *start = (PAL_PTR) start_addr;
+
+    // Not used, so set it to an empty range.
+    *hole_start = start_addr;
+    *hole_end = start_addr;
 }
 
 PAL_NUM _DkGetProcessId (void)

+ 6 - 3
Pal/src/host/Linux-SGX/db_main.c

@@ -57,10 +57,13 @@ unsigned long _DkGetAllocationAlignment (void)
     return pagesz;
 }
 
-void _DkGetAvailableUserAddressRange (PAL_PTR * start, PAL_PTR * end)
+void _DkGetAvailableUserAddressRange (PAL_PTR * start, PAL_PTR * end,
+                                      PAL_PTR * hole_start, PAL_PTR * hole_end)
 {
     *start = (PAL_PTR) pal_sec.heap_min;
     *end = (PAL_PTR) get_reserved_pages(NULL, pagesz);
+    *hole_start = SATURATED_P_SUB(pal_sec.exec_addr, MEMORY_GAP, *start);
+    *hole_end = SATURATED_P_ADD(pal_sec.exec_addr + pal_sec.exec_size, MEMORY_GAP, *end);
 }
 
 PAL_NUM _DkGetProcessId (void)
@@ -231,8 +234,8 @@ void pal_linux_main(char * uptr_args, uint64_t args_size,
     void* zero2_end = pal_sec.heap_max;
 
     if (pal_sec.exec_addr != NULL) {
-        zero1_end = MIN(zero1_end, pal_sec.exec_addr);
-        zero2_start = MIN(zero2_start, pal_sec.exec_addr + pal_sec.exec_size);
+        zero1_end = MIN(zero1_end, SATURATED_P_SUB(pal_sec.exec_addr, MEMORY_GAP, 0));
+        zero2_start = SATURATED_P_ADD(pal_sec.exec_addr + pal_sec.exec_size, MEMORY_GAP, zero2_end);
     }
 
     memset(zero1_start, 0, zero1_end - zero1_start);

+ 8 - 5
Pal/src/host/Linux-SGX/enclave_pages.c

@@ -29,19 +29,22 @@ struct atomic_int alloced_pages, max_alloced_pages;
 
 void init_pages (void)
 {
+    uint64_t reserved_for_exec = 0;
+
     heap_base = pal_sec.heap_min;
     heap_size = pal_sec.heap_max - pal_sec.heap_min;
 
-    SGX_DBG(DBG_M, "available heap size: %lu M\n",
-           (heap_size - pal_sec.exec_size) / 1024 / 1024);
-
     if (pal_sec.exec_size) {
         struct heap_vma * vma = malloc(sizeof(struct heap_vma));
-        vma->top = pal_sec.exec_addr + pal_sec.exec_size;
-        vma->bottom = pal_sec.exec_addr;
+        vma->bottom = SATURATED_P_SUB(pal_sec.exec_addr, MEMORY_GAP, pal_sec.heap_min);
+        vma->top = SATURATED_P_ADD(pal_sec.exec_addr + pal_sec.exec_size, MEMORY_GAP, pal_sec.heap_max);
+        reserved_for_exec = vma->top - vma->bottom;
         INIT_LIST_HEAD(vma, list);
         LISTP_ADD(vma, &heap_vma_list, list);
     }
+
+    SGX_DBG(DBG_M, "available heap size: %lu M\n",
+           (heap_size - reserved_for_exec) / 1024 / 1024);
 }
 
 #define ASSERT_VMA          0

+ 4 - 7
Pal/src/host/Linux-SGX/sgx_main.c

@@ -394,10 +394,7 @@ int initialize_enclave (struct pal_enclave * enclave)
         if (areas[i].addr)
             continue;
         areas[i].addr = populating - areas[i].size;
-        if (&areas[i] == exec_area)
-            populating = areas[i].addr;
-        else
-            populating = areas[i].addr - MEMORY_GAP;
+        populating = SATURATED_P_SUB(areas[i].addr, MEMORY_GAP, 0);
     }
 
     enclave_entry_addr += pal_area->addr;
@@ -409,9 +406,9 @@ int initialize_enclave (struct pal_enclave * enclave)
             goto out;
         }
 
-        if (exec_area->addr + exec_area->size < populating) {
+        if (exec_area->addr + exec_area->size + MEMORY_GAP < populating) {
             if (populating > heap_min) {
-                unsigned long addr = exec_area->addr + exec_area->size;
+                unsigned long addr = exec_area->addr + exec_area->size + MEMORY_GAP;
                 if (addr < heap_min)
                     addr = heap_min;
 
@@ -423,7 +420,7 @@ int initialize_enclave (struct pal_enclave * enclave)
                 area_num++;
             }
 
-            populating = exec_area->addr;
+            populating = SATURATED_P_SUB(exec_area->addr, MEMORY_GAP, 0);
         }
     }
 

+ 4 - 7
Pal/src/host/Linux-SGX/signer/pal-sgx-sign

@@ -457,20 +457,17 @@ def populate_memory_areas(attr, areas):
         area.addr = populating - area.size
         if area.addr < enclave_heap_min:
             raise Exception("Enclave size is not large enough")
-        if area.desc == 'exec':
-            populating = area.addr
-        else:
-            populating = area.addr - MEMORY_GAP
+        populating = max(area.addr - MEMORY_GAP, 0)
 
     free_areas = []
     for area in areas:
-        if area.addr + area.size < populating:
-            addr = area.addr + area.size
+        if area.addr + area.size + MEMORY_GAP < populating:
+            addr = area.addr + area.size + MEMORY_GAP
             flags = PAGEINFO_R | PAGEINFO_W | PAGEINFO_X | PAGEINFO_REG
             free_areas.append(
                 MemoryArea('free', addr=addr, size=populating - addr,
                            flags=flags, measure=False))
-            populating = area.addr
+            populating = max(area.addr - MEMORY_GAP, 0)
 
     if populating > enclave_heap_min:
         flags = PAGEINFO_R | PAGEINFO_W | PAGEINFO_X | PAGEINFO_REG

+ 6 - 1
Pal/src/host/Linux/db_main.c

@@ -147,7 +147,8 @@ unsigned long _DkGetAllocationAlignment (void)
     return pagesz;
 }
 
-void _DkGetAvailableUserAddressRange (PAL_PTR * start, PAL_PTR * end)
+void _DkGetAvailableUserAddressRange (PAL_PTR * start, PAL_PTR * end,
+                                      PAL_PTR * hole_start, PAL_PTR * hole_end)
 {
     void * end_addr = (void *) ALLOC_ALIGNDOWN(TEXT_START);
     void * start_addr = (void *) USER_ADDRESS_LOWEST;
@@ -174,6 +175,10 @@ void _DkGetAvailableUserAddressRange (PAL_PTR * start, PAL_PTR * end)
 
     *end   = (PAL_PTR) end_addr;
     *start = (PAL_PTR) start_addr;
+
+    // Not used, so set it to an empty range.
+    *hole_start = start_addr;
+    *hole_end = start_addr;
 }
 
 PAL_NUM _DkGetProcessId (void)

+ 2 - 1
Pal/src/host/Skeleton/db_main.c

@@ -45,7 +45,8 @@ unsigned long _DkGetAllocationAlignment (void)
     return 0;
 }
 
-void _DkGetAvailableUserAddressRange (PAL_PTR * start, PAL_PTR * end)
+void _DkGetAvailableUserAddressRange (PAL_PTR * start, PAL_PTR * end,
+                                      PAL_PTR * hole_start, PAL_PTR * hole_end)
 {
     /* need to be implemented */
 }

+ 4 - 0
Pal/src/pal.h

@@ -195,6 +195,10 @@ typedef struct {
     /***** Memory layout ******/
     /* The range of user address */
     PAL_PTR_RANGE user_address;
+    /* Reserved memory range inside of user address.
+     * Used for example by SGX for exec area (including memory gap) in the
+     * middle of the heap. If unused set start == end. */
+    PAL_PTR_RANGE user_address_hole;
     /* address where executable is loaded */
     PAL_PTR_RANGE executable_range;
     /* manifest preloaded here */

+ 1 - 1
Pal/src/pal_internal.h

@@ -263,7 +263,7 @@ noreturn void pal_main (
 /* For initialization */
 unsigned long _DkGetPagesize (void);
 unsigned long _DkGetAllocationAlignment (void);
-void _DkGetAvailableUserAddressRange (PAL_PTR * start, PAL_PTR * end);
+void _DkGetAvailableUserAddressRange (PAL_PTR * start, PAL_PTR * end, PAL_PTR * hole_start, PAL_PTR * hole_end);
 bool _DkCheckMemoryMappable (const void * addr, size_t size);
 PAL_NUM _DkGetProcessId (void);
 PAL_NUM _DkGetHostId (void);