mremap fails with EFAULT if address range overlaps with stack guard
This issue was actually reported earlier and a patch was purposed: https://patchwork.kernel.org/project/qemu-devel/patch/20200305210534.28392-1-tobias.koch@nonterra.com/
However, it seems the patch was abandoned due to undesirable implementation details. I hope this issue can get another look and fixed.
Host environment
- Operating system: any linux
- OS/kernel version: any kernel version
- Architecture: x86_64
- QEMU flavor: qemu-user-static (ARM 32-bit)
- QEMU version: any version
- QEMU command line:
Emulated/Virtualized environment
- Operating system: alpine-linux
- OS/kernel version: host kernel (qemu-user-static)
- Architecture: ARM 32-bit
Description of problem
When running 32-bit user-static on 64-bit host, mremap
behave differently from the kernel. This difference let programs that call pthread_getattr_np
on musl-libc to run into a loop on repeated calling mremap
.
https://git.musl-libc.org/cgit/musl/plain/src/thread/pthread_getattr_np.c
while (mremap(p-l-PAGE_SIZE, PAGE_SIZE, 2*PAGE_SIZE, 0)==MAP_FAILED && errno==ENOMEM)
l += PAGE_SIZE;
Steps to reproduce
Compile the following program against musl-libc arm 32-bit, and run it in qemu-user-static on x86_64 host.
#define _GNU_SOURCE
#include <pthread.h>
int main(int argc, char *argv[]) {
pthread_attr_t attr;
return pthread_getattr_np(pthread_self(), &attr);
}
For example, on x86_64 fedora 38 with podman and qemu-user-static installed, we can reproduce this with alpine container:
$ podman run --rm -it --arch arm/v7 docker.io/library/alpine:latest
/ # apk add alpine-sdk
......
/ # cat test.c
#define _GNU_SOURCE
#include <pthread.h>
int main(int argc, char *argv[]) {
pthread_attr_t attr;
return pthread_getattr_np(pthread_self(), &attr);
}
/ # gcc test.c
/ # ./a.out
Additional information
Original thread on musl mail list where this was initially reported: https://www.openwall.com/lists/musl/2017/06/15/9