diff options
author | kasper3 <33230602+kasper3@users.noreply.github.com> | 2018-06-01 15:22:43 +0300 |
---|---|---|
committer | Jan Vorlicek <janvorli@microsoft.com> | 2018-06-01 14:22:43 +0200 |
commit | 13ea3c2c8e1eec2d511e005265978b9f4197c319 (patch) | |
tree | 1a68a383e4e4902e3042edd7d1165f50b2f7fb3d | |
parent | 88db627a97d91acce0638ed195072080089b9ff1 (diff) | |
download | coreclr-13ea3c2c8e1eec2d511e005265978b9f4197c319.tar.gz coreclr-13ea3c2c8e1eec2d511e005265978b9f4197c319.tar.bz2 coreclr-13ea3c2c8e1eec2d511e005265978b9f4197c319.zip |
Fix alternate stack for Alpine docker on SELinux (#17936) (#17975)
For some reason, the Alpine docker container running on a SELinux host maps
heap as RWX. When we allocate alternate stack from the heap, we also
change the protection of the first page to PROT_NONE so that it can
serve as a guard page to catch stack overflow. And when we free the
alternate stack, we restore the protection back to PROT_READ |
PROT_WRITE. The restoration fails in Alpine docker container running on
a SELinux host with EPROT failure and the SELinux log reports that an
attempt to change heap to executable was made. So it looks like the
kernel has added the PERM_EXEC to the permissions we have passed to the
mprotect call. There is a code in the mprotect implementation that can
do that, although I don't fully understand the conditions under which it
happens. This is driven by the VM_MAYEXEC flag in the internal VMA block
structure.
To fix that, I've modified the alternate stack allocation to use mmap /
munmap instead of C heap allocation.
-rw-r--r-- | src/pal/src/exception/signal.cpp | 18 |
1 files changed, 6 insertions, 12 deletions
diff --git a/src/pal/src/exception/signal.cpp b/src/pal/src/exception/signal.cpp index 0a3840a479..458e331698 100644 --- a/src/pal/src/exception/signal.cpp +++ b/src/pal/src/exception/signal.cpp @@ -158,9 +158,9 @@ BOOL EnsureSignalAlternateStack() // (see kAltStackSize in compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc) altStackSize += SIGSTKSZ * 4; #endif - void* altStack; - int st = posix_memalign(&altStack, GetVirtualPageSize(), altStackSize); - if (st == 0) + altStackSize = ALIGN_UP(altStackSize, GetVirtualPageSize()); + void* altStack = mmap(NULL, altStackSize, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_STACK | MAP_PRIVATE, -1, 0); + if (altStack != MAP_FAILED) { // create a guard page for the alternate stack st = mprotect(altStack, GetVirtualPageSize(), PROT_NONE); @@ -171,17 +171,12 @@ BOOL EnsureSignalAlternateStack() ss.ss_size = altStackSize; ss.ss_flags = 0; st = sigaltstack(&ss, NULL); - if (st != 0) - { - // Installation of the alternate stack failed, so revert the guard page protection - int st2 = mprotect(altStack, GetVirtualPageSize(), PROT_READ | PROT_WRITE); - _ASSERTE(st2 == 0); - } } if (st != 0) { - free(altStack); + int st2 = munmap(altStack, altStackSize); + _ASSERTE(st2 == 0); } } } @@ -208,9 +203,8 @@ void FreeSignalAlternateStack() int st = sigaltstack(&ss, &oss); if ((st == 0) && (oss.ss_flags != SS_DISABLE)) { - int st = mprotect(oss.ss_sp, GetVirtualPageSize(), PROT_READ | PROT_WRITE); + int st = munmap(oss.ss_sp, oss.ss_size); _ASSERTE(st == 0); - free(oss.ss_sp); } } #endif // !HAVE_MACH_EXCEPTIONS |