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

Commit 13ea3c2

Browse files
kasper3janvorli
authored andcommitted
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.
1 parent 88db627 commit 13ea3c2

File tree

1 file changed

+6
-12
lines changed

1 file changed

+6
-12
lines changed

src/pal/src/exception/signal.cpp

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,9 @@ BOOL EnsureSignalAlternateStack()
158158
// (see kAltStackSize in compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc)
159159
altStackSize += SIGSTKSZ * 4;
160160
#endif
161-
void* altStack;
162-
int st = posix_memalign(&altStack, GetVirtualPageSize(), altStackSize);
163-
if (st == 0)
161+
altStackSize = ALIGN_UP(altStackSize, GetVirtualPageSize());
162+
void* altStack = mmap(NULL, altStackSize, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_STACK | MAP_PRIVATE, -1, 0);
163+
if (altStack != MAP_FAILED)
164164
{
165165
// create a guard page for the alternate stack
166166
st = mprotect(altStack, GetVirtualPageSize(), PROT_NONE);
@@ -171,17 +171,12 @@ BOOL EnsureSignalAlternateStack()
171171
ss.ss_size = altStackSize;
172172
ss.ss_flags = 0;
173173
st = sigaltstack(&ss, NULL);
174-
if (st != 0)
175-
{
176-
// Installation of the alternate stack failed, so revert the guard page protection
177-
int st2 = mprotect(altStack, GetVirtualPageSize(), PROT_READ | PROT_WRITE);
178-
_ASSERTE(st2 == 0);
179-
}
180174
}
181175

182176
if (st != 0)
183177
{
184-
free(altStack);
178+
int st2 = munmap(altStack, altStackSize);
179+
_ASSERTE(st2 == 0);
185180
}
186181
}
187182
}
@@ -208,9 +203,8 @@ void FreeSignalAlternateStack()
208203
int st = sigaltstack(&ss, &oss);
209204
if ((st == 0) && (oss.ss_flags != SS_DISABLE))
210205
{
211-
int st = mprotect(oss.ss_sp, GetVirtualPageSize(), PROT_READ | PROT_WRITE);
206+
int st = munmap(oss.ss_sp, oss.ss_size);
212207
_ASSERTE(st == 0);
213-
free(oss.ss_sp);
214208
}
215209
}
216210
#endif // !HAVE_MACH_EXCEPTIONS

0 commit comments

Comments
 (0)