Hi,
I recently tried to run qemu, and it failed with SIGABRT and dmesg
contains:
map stack 0x86277000-0x86378000 of map 0xd5343afc failed: bad protection
map stack for pid 43079 failed
I initially think about missing MAP_STACK. And effectively, the flag is
missing on the port (function qemu_alloc_stack() in util/oslib-posix.c).
But in fact, it seems it isn't underline problem of my failure: even
with MAP_STACK, the program is still aborted at the same place.
The real problem is qemu implements a stackguard protection
from qemu, util/oslib-posix.c (with manually added MAP_STACK):
540 ptr = mmap(NULL, *sz, PROT_READ | PROT_WRITE,
541 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
542 if (ptr == MAP_FAILED) {
543 perror("failed to allocate memory for stack");
544 abort();
545 }
546
547 #if defined(HOST_IA64)
548 /* separate register stack */
549 guardpage = ptr + (((*sz - pagesz) / 2) & ~pagesz);
550 #elif defined(HOST_HPPA)
551 /* stack grows up */
552 guardpage = ptr + *sz - pagesz;
553 #else
554 /* stack grows down */
555 guardpage = ptr;
556 #endif
557
558 if (mprotect(guardpage, pagesz, PROT_NONE) != 0) {
559 perror("failed to set up stack guard page");
560 abort();
561 }
562
and the kernel doesn't like it: in uvm_map_is_stack_remappable(), the
protection check is done by only allowing PROT_READ | PROT_WRITE:
sys/uvm/uvm_map.c
1852 if (iter->protection != (PROT_READ | PROT_WRITE)) {
1853 printf("map stack 0x%lx-0x%lx of map %p failed:
"
1854 "bad protection\n", addr, end, map);
1855 return FALSE;
1856 }
and the guardpage segment is PROT_NONE, resulting an error, and qemu
abort.
If I remove the mprotect(2) call from qemu, the program starts fine (I
didn't test it deeply).
Assuming the check on protection is a bit too restrictive, and it is
fine to have some chunks with PROT_NONE, I think we want something like:
Index: uvm/uvm_map.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_map.c,v
retrieving revision 1.234
diff -u -p -r1.234 uvm_map.c
--- uvm/uvm_map.c 12 Apr 2018 17:13:44 -0000 1.234
+++ uvm/uvm_map.c 16 Apr 2018 15:20:30 -0000
@@ -1849,7 +1849,11 @@ uvm_map_is_stack_remappable(struct vm_ma
#if 0
printf("iter prot: 0x%x\n", iter->protection);
#endif
- if (iter->protection != (PROT_READ | PROT_WRITE)) {
+ switch (iter->protection) {
+ case PROT_READ|PROT_WRITE:
+ case PROT_NONE:
+ break;
+ default:
printf("map stack 0x%lx-0x%lx of map %p failed: "
"bad protection\n", addr, end, map);
return FALSE;
I will send a diff for emulators/qemu to add MAP_STACK after this part
is resolved.
Thanks.
--
Sebastien Marie