Skip to content
This repository was archived by the owner on Jan 20, 2022. It is now read-only.

Commit 5a5b42f

Browse files
omegDmitrii Kuvaiskii
authored and
Dmitrii Kuvaiskii
committed
[LibOS/PAL] Memory corruption fixes
This commit contains the following memory-corruption fixes: - Add a separate debug_print_vma() function - Fix _DkGetAvailableUserAddressRange() returning incorrect memory range - Protect memory occupied by LibOS code from being overwritten - Check return values of init_brk*() calls - Add check for allocation failure in __bkeep_mmap() - Fix initial brk region allocation (previously could overwrite PAL data)
1 parent 15ca4a9 commit 5a5b42f

File tree

12 files changed

+104
-56
lines changed

12 files changed

+104
-56
lines changed

LibOS/shim/include/shim_internal.h

+2
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,8 @@ extern const char ** initial_envp;
745745
void get_brk_region (void ** start, void ** end, void ** current);
746746

747747
int reset_brk (void);
748+
struct shim_handle;
749+
int init_brk_from_executable (struct shim_handle * exec);
748750
int init_brk_region (void * brk_region);
749751
int init_heap (void);
750752
int init_internal_map (void);

LibOS/shim/src/bookkeep/shim_vma.c

+35-22
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,14 @@ int init_vma (void)
306306
if (ret < 0)
307307
return ret;
308308

309+
/* Keep track of LibOS code itself so nothing overwrites it */
310+
ret = __bkeep_preloaded(&__load_address,
311+
ALIGN_UP(&__load_address_end),
312+
PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS|VMA_INTERNAL,
313+
"LibOS");
314+
if (ret < 0)
315+
return ret;
316+
309317
/* Initialize the allocator */
310318

311319
if (!(vma_mgr = create_mem_mgr(init_align_up(VMA_MGR_ALLOC)))) {
@@ -1252,33 +1260,38 @@ BEGIN_CP_FUNC(all_vmas)
12521260
}
12531261
END_CP_FUNC_NO_RS(all_vmas)
12541262

1263+
void debug_print_vma (struct shim_vma *vma)
1264+
{
1265+
const char * type = "", * name = "";
1266+
1267+
if (vma->file) {
1268+
if (!qstrempty(&vma->file->path)) {
1269+
type = " path=";
1270+
name = qstrgetstr(&vma->file->path);
1271+
} else if (!qstrempty(&vma->file->uri)) {
1272+
type = " uri=";
1273+
name = qstrgetstr(&vma->file->uri);
1274+
}
1275+
}
1276+
1277+
SYS_PRINTF("[%p-%p] prot=%08x flags=%08x%s%s offset=%ld%s%s%s%s\n",
1278+
vma->start, vma->end,
1279+
vma->prot,
1280+
vma->flags & ~(VMA_INTERNAL|VMA_UNMAPPED|VMA_TAINTED|VMA_CP),
1281+
type, name,
1282+
vma->offset,
1283+
vma->flags & VMA_INTERNAL ? " (internal)" : "",
1284+
vma->flags & VMA_UNMAPPED ? " (unmapped)" : "",
1285+
vma->comment[0] ? " comment=" : "",
1286+
vma->comment[0] ? vma->comment : "");
1287+
}
1288+
12551289
void debug_print_vma_list (void)
12561290
{
12571291
SYS_PRINTF("vma bookkeeping:\n");
12581292

12591293
struct shim_vma * vma;
12601294
LISTP_FOR_EACH_ENTRY(vma, &vma_list, list) {
1261-
const char * type = "", * name = "";
1262-
1263-
if (vma->file) {
1264-
if (!qstrempty(&vma->file->path)) {
1265-
type = " path=";
1266-
name = qstrgetstr(&vma->file->path);
1267-
} else if (!qstrempty(&vma->file->uri)) {
1268-
type = " uri=";
1269-
name = qstrgetstr(&vma->file->uri);
1270-
}
1271-
}
1272-
1273-
SYS_PRINTF("[%p-%p] prot=%08x flags=%08x%s%s offset=%ld%s%s%s%s\n",
1274-
vma->start, vma->end,
1275-
vma->prot,
1276-
vma->flags & ~(VMA_INTERNAL|VMA_UNMAPPED|VMA_TAINTED|VMA_CP),
1277-
type, name,
1278-
vma->offset,
1279-
vma->flags & VMA_INTERNAL ? " (internal)" : "",
1280-
vma->flags & VMA_UNMAPPED ? " (unmapped)" : "",
1281-
vma->comment[0] ? " comment=" : "",
1282-
vma->comment[0] ? vma->comment : "");
1295+
debug_print_vma(vma);
12831296
}
12841297
}

LibOS/shim/src/elf/shim_rtld.c

+6-5
Original file line numberDiff line numberDiff line change
@@ -1481,8 +1481,6 @@ int init_internal_map (void)
14811481
return 0;
14821482
}
14831483

1484-
int init_brk_from_executable (struct shim_handle * exec);
1485-
14861484
int init_loader (void)
14871485
{
14881486
struct shim_thread * cur_thread = get_cur_thread();
@@ -1509,7 +1507,9 @@ int init_loader (void)
15091507
exec_map = __search_map_by_handle(exec);
15101508
}
15111509

1512-
init_brk_from_executable(exec);
1510+
ret = init_brk_from_executable(exec);
1511+
if (ret < 0)
1512+
goto out;
15131513

15141514
if (!interp_map
15151515
&& __need_interp(exec_map)
@@ -1525,16 +1525,17 @@ int init_loader (void)
15251525
int init_brk_from_executable (struct shim_handle * exec)
15261526
{
15271527
struct link_map * exec_map = __search_map_by_handle(exec);
1528+
int ret = 0;
15281529

15291530
if (exec_map) {
15301531
/*
15311532
* Chia-Che 8/24/2017:
15321533
* initialize brk region at the end of the executable data segment.
15331534
*/
1534-
init_brk_region((void *) ALIGN_UP(exec_map->l_map_end));
1535+
ret = init_brk_region((void *) ALIGN_UP(exec_map->l_map_end));
15351536
}
15361537

1537-
return 0;
1538+
return ret;
15381539
}
15391540

15401541
int register_library (const char * name, unsigned long load_address)

LibOS/shim/src/sys/shim_brk.c

+45-20
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ int init_brk_region (void * brk_region)
7171
}
7272

7373
int flags = MAP_PRIVATE|MAP_ANONYMOUS;
74+
bool brk_on_heap = true;
75+
const int TRIES = 10;
7476

7577
/*
7678
* Chia-Che 8/24/2017
@@ -80,24 +82,52 @@ int init_brk_region (void * brk_region)
8082
* should be within [exec-data-end, exec-data-end + 0x2000000)
8183
*/
8284
if (brk_region) {
83-
while (true) {
84-
uint32_t rand;
85-
int ret = DkRandomBitsRead(&rand, sizeof(rand));
86-
if (ret < 0)
87-
return -convert_pal_errno(-ret);
88-
rand %= 0x2000000;
89-
rand = ALIGN_UP(rand);
90-
91-
struct shim_vma_val vma;
92-
if (lookup_overlap_vma(brk_region + rand, brk_max_size, &vma)
93-
== -ENOENT) {
94-
brk_region += rand;
95-
break;
85+
size_t max_brk = 0;
86+
if (PAL_CB(user_address.end) >= PAL_CB(executable_range.end))
87+
max_brk = PAL_CB(user_address.end) - PAL_CB(executable_range.end);
88+
89+
/* Check whether the brk region can potentially be located after exec at all. */
90+
if (brk_max_size <= max_brk) {
91+
int try;
92+
for (try = TRIES; try > 0; try--) {
93+
uint32_t rand = 0;
94+
#if ENABLE_ASLR == 1
95+
int ret = DkRandomBitsRead(&rand, sizeof(rand));
96+
if (ret < 0)
97+
return -convert_pal_errno(-ret);
98+
rand %= MIN(0x2000000, PAL_CB(user_address.end) - brk_region - brk_max_size);
99+
rand = ALIGN_DOWN(rand);
100+
101+
if (brk_region + rand + brk_max_size >= PAL_CB(user_address.end))
102+
continue;
103+
#else
104+
/* Without randomization there is no point to retry here */
105+
if (brk_region + rand + brk_max_size >= PAL_CB(user_address.end))
106+
break;
107+
#endif
108+
109+
struct shim_vma_val vma;
110+
if (lookup_overlap_vma(brk_region + rand, brk_max_size, &vma) == -ENOENT) {
111+
/* Found a place for brk */
112+
brk_region += rand;
113+
brk_on_heap = false;
114+
break;
115+
}
116+
#if !(ENABLE_ASLR == 1)
117+
/* Without randomization, try memory directly after the overlapping block */
118+
brk_region = vma.addr + vma.length;
119+
#endif
96120
}
97-
98-
brk_region = vma.addr + vma.length;
99121
}
122+
}
100123

124+
if (brk_on_heap) {
125+
brk_region = bkeep_unmapped_heap(brk_max_size, PROT_READ|PROT_WRITE,
126+
flags|VMA_UNMAPPED, NULL, 0, "brk");
127+
if (!brk_region) {
128+
return -ENOMEM;
129+
}
130+
} else {
101131
/*
102132
* Create the bookkeeping before allocating the brk region.
103133
* The bookkeeping should never fail because we've already confirmed
@@ -106,11 +136,6 @@ int init_brk_region (void * brk_region)
106136
if (bkeep_mmap(brk_region, brk_max_size, PROT_READ|PROT_WRITE,
107137
flags|VMA_UNMAPPED, NULL, 0, "brk") < 0)
108138
BUG();
109-
} else {
110-
brk_region = bkeep_unmapped_heap(brk_max_size, PROT_READ|PROT_WRITE,
111-
flags|VMA_UNMAPPED, NULL, 0, "brk");
112-
if (!brk_region)
113-
return -ENOMEM;
114139
}
115140

116141
void * end_brk_region = NULL;

LibOS/shim/src/sys/shim_exec.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,10 @@ int shim_do_execve_rtld (struct shim_handle * hdl, const char ** argv,
178178
if ((ret = load_elf_object(cur_thread->exec, NULL, 0)) < 0)
179179
shim_terminate(ret);
180180

181-
init_brk_from_executable(cur_thread->exec);
181+
ret = init_brk_from_executable(cur_thread->exec);
182+
if (ret < 0)
183+
return ret;
184+
182185
load_elf_interp(cur_thread->exec);
183186

184187
SAVE_PROFILE_INTERVAL(load_new_executable_for_exec);

Pal/lib/api.h

+8-2
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,16 @@ typedef ptrdiff_t ssize_t;
3636
#endif
3737

3838
#ifndef MIN
39-
# define MIN(a, b) ((a) < (b) ? (a) : (b))
39+
#define MIN(a,b) \
40+
({ __typeof__(a) _a = (a); \
41+
__typeof__(b) _b = (b); \
42+
_a < _b ? _a : _b; })
4043
#endif
4144
#ifndef MAX
42-
# define MAX(a, b) ((a) > (b) ? (a) : (b))
45+
#define MAX(a,b) \
46+
({ __typeof__(a) _a = (a); \
47+
__typeof__(b) _b = (b); \
48+
_a > _b ? _a : _b; })
4349
#endif
4450

4551
#define ALIGN_DOWN_PTR(ptr, size) \

Pal/src/host/FreeBSD/db_main.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ void _DkGetAvailableUserAddressRange (PAL_PTR * start, PAL_PTR * end)
169169
start_addr = (void *) ((unsigned long) start_addr << 1);
170170
}
171171

172-
*end = (PAL_PTR) end_addr - USER_ADDRESS_RESERVED;
172+
*end = (PAL_PTR) end_addr;
173173
*start = (PAL_PTR) start_addr;
174174
}
175175

Pal/src/host/FreeBSD/pal_freebsd_defs.h

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#ifndef PAL_FREEBSD_DEFS_H
22
#define PAL_FREEBSD_DEFS_H
33

4-
#define USER_ADDRESS_RESERVED 0x1000000
54
#define USER_ADDRESS_LOWEST 0x10000
65
#define USER_ADDRESS_HIGHEST 0x80000000
76

Pal/src/host/Linux-SGX/enclave_framework.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ int load_trusted_file (PAL_HANDLE file, sgx_stub_t ** stubptr,
332332
* store the data for checksum generation.
333333
*/
334334

335-
#define FILE_CHUNK_SIZE 1024
335+
#define FILE_CHUNK_SIZE 1024UL
336336

337337
uint8_t small_chunk[FILE_CHUNK_SIZE]; /* Buffer for hashing */
338338
size_t chunk_offset = 0;

Pal/src/host/Linux-SGX/pal_linux_defs.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#define DEBUG_ECALL 0
1313
#define DEBUG_OCALL 0
1414

15-
#define TRUSTED_STUB_SIZE (PRESET_PAGESIZE * 4)
15+
#define TRUSTED_STUB_SIZE (PRESET_PAGESIZE * 4UL)
1616

1717
#define CACHE_FILE_STUBS 1
1818

Pal/src/host/Linux/db_main.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ void _DkGetAvailableUserAddressRange (PAL_PTR * start, PAL_PTR * end)
172172
start_addr = (void *) ((unsigned long) start_addr << 1);
173173
}
174174

175-
*end = (PAL_PTR) end_addr - USER_ADDRESS_RESERVED;
175+
*end = (PAL_PTR) end_addr;
176176
*start = (PAL_PTR) start_addr;
177177
}
178178

Pal/src/host/Linux/pal_linux_defs.h

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#ifndef PAL_LINUX_DEFS_H
22
#define PAL_LINUX_DEFS_H
33

4-
#define USER_ADDRESS_RESERVED 0x100000000
54
#define USER_ADDRESS_LOWEST 0x10000
65

76
#define THREAD_STACK_SIZE (PRESET_PAGESIZE * 2)

0 commit comments

Comments
 (0)