summaryrefslogtreecommitdiff
path: root/src/pal/src/exception
diff options
context:
space:
mode:
authorJan Vorlicek <janvorli@microsoft.com>2018-05-10 15:33:54 +0200
committerGitHub <noreply@github.com>2018-05-10 15:33:54 +0200
commitb50ce91e9bd75170ef6aaeb65b9b80824539919c (patch)
treec9fd4aed8a23b1c22ffa3d9e76a3cf4ced048a1d /src/pal/src/exception
parent1ecd2be3cebc4b791d559d162228aa1ddf388564 (diff)
downloadcoreclr-b50ce91e9bd75170ef6aaeb65b9b80824539919c.tar.gz
coreclr-b50ce91e9bd75170ef6aaeb65b9b80824539919c.tar.bz2
coreclr-b50ce91e9bd75170ef6aaeb65b9b80824539919c.zip
Fix alternate stack for Alpine docker on SELinux (#17936)
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.
Diffstat (limited to 'src/pal/src/exception')
-rw-r--r--src/pal/src/exception/signal.cpp18
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