From 1745825e81ff26d44f963cd4a05a3fd75c12e3a6 Mon Sep 17 00:00:00 2001 From: "Hui, Chunyang" Date: Mon, 18 Oct 2021 11:11:55 +0000 Subject: [PATCH] Add support for mprotect PROT_GROWSDOWN --- src/libos/src/vm/vm_perms.rs | 8 ++++++-- test/mmap/main.c | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/libos/src/vm/vm_perms.rs b/src/libos/src/vm/vm_perms.rs index 933f3203..3bd9e325 100644 --- a/src/libos/src/vm/vm_perms.rs +++ b/src/libos/src/vm/vm_perms.rs @@ -8,6 +8,7 @@ bitflags! { const EXEC = 0x4; const DEFAULT = Self::READ.bits | Self::WRITE.bits; const ALL = Self::DEFAULT.bits | Self::EXEC.bits; + const GROWSDOWN = 0x01000000; // For x86, stack direction always grow downwards. } } @@ -46,8 +47,11 @@ impl VMPerms { let mut retval = 0; let addr = protect_range.start() as *const c_void; let len = protect_range.size(); - let prot = perms.bits() as i32; - let sgx_status = occlum_ocall_mprotect(&mut retval, addr, len, prot); + // PT_GROWSDOWN should only be applied to stack segment or a segment mapped with the MAP_GROWSDOWN flag set. + // Since the memory are managed by our own, mprotect ocall shouldn't use this flag. Otherwise, EINVAL will be thrown. + let mut prot = perms.clone(); + prot.remove(VMPerms::GROWSDOWN); + let sgx_status = occlum_ocall_mprotect(&mut retval, addr, len, prot.bits() as i32); assert!(sgx_status == sgx_status_t::SGX_SUCCESS && retval == 0); } } diff --git a/test/mmap/main.c b/test/mmap/main.c index 44010d4d..e9dfd5a7 100644 --- a/test/mmap/main.c +++ b/test/mmap/main.c @@ -1086,6 +1086,23 @@ int test_mprotect_multiple_vmas() { return 0; } +int test_mprotect_grow_down() { + int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN; + void *buf = mmap(0, PAGE_SIZE * 2, PROT_NONE, flags, -1, 0); + if (buf == MAP_FAILED) { + THROW_ERROR("mmap failed"); + } + + // Mprotect can use PROT_GROWSDOWN on a stack segment or a segment mapped with the MAP_GROWSDOWN flag set + int ret = mprotect(buf, 2 * PAGE_SIZE, + PROT_READ | PROT_WRITE | PROT_EXEC | PROT_GROWSDOWN); + if (ret < 0) { + THROW_ERROR("mprotect failed"); + } + + return 0; +} + int check_file_first_four_page(char *file_path, int first_page_val, int secend_page_val, int third_page_val, int fourth_page_val) { int fd = open(file_path, O_RDONLY); @@ -1289,6 +1306,7 @@ static test_case_t test_cases[] = { TEST_CASE(test_mprotect_with_invalid_prot), TEST_CASE(test_mprotect_with_non_page_aligned_size), TEST_CASE(test_mprotect_multiple_vmas), + TEST_CASE(test_mprotect_grow_down), }; int main() {