* simple aarch64 binary can cause linux-user QEMU to segv in zero_bss()
@ 2020-11-23 19:52 Peter Maydell
2020-11-24 17:18 ` Richard Henderson
0 siblings, 1 reply; 3+ messages in thread
From: Peter Maydell @ 2020-11-23 19:52 UTC (permalink / raw)
To: QEMU Developers, Laurent Vivier, Richard Henderson,
Alex Bennée
Somebody reported this on stackoverflow. Before I spend too
much time thinking about how this ought to work, does anybody
have the elfload.c intended operation in their head still?
Bug description and analysis of what goes wrong below:
https://stackoverflow.com/questions/64956322/alignment-requirements-for-arm64-elf-executables-run-in-qemu-assembled-by-gas
Given this trivial asm:
===begin program.s===
// GNU Assembler, ARM64 Linux
.bss
.lcomm ARRAY, 16
.text
.global _start
_start:
mov x8, 93 // exit sys num
mov x0, 0 // success
svc 0
===endit===
clang -nostdlib -fno-integrated-as -target aarch64-linux-gnu -s
program.s -o program.out
the resulting program.out works fine on a real kernel but makes
qemu-aarch64 SEGV:
$ ./build/x86/qemu-aarch64 /tmp/program.out
Segmentation fault (core dumped)
Looking at it with gdb, the segv is from QEMU itself, in zero_bss():
if (host_start < host_map_start) {
memset((void *)host_start, 0, host_map_start - host_start);
}
We try to clear the memory from 'host_start' to 'host_map_start'
(the latter being the round-up-to-host-page version of the former),
but for this binary we never mmap()ed host_start as writeable,
so we segv inside the memset.
The guest-binary relevant bits of /proc/maps are:
00400000-00401000 r--p 00000000 08:15 5767333
/tmp/program.out
00401000-01411000 ---p 00000000 00:00 0
The program header is:
Program Header:
LOAD off 0x0000000000000000 vaddr 0x0000000000400000 paddr
0x0000000000400000 align 2**16
filesz 0x00000000000000bc memsz 0x00000000000000bc flags r-x
LOAD off 0x00000000000000c0 vaddr 0x00000000004100c0 paddr
0x00000000004100c0 align 2**16
filesz 0x0000000000000000 memsz 0x0000000000000010 flags rw-
and in zero_bss() host_start == 0x4100c0, host_map_start == 0x411000,
last_bss == 0x411000. The code calls
page_set_flags(start = 0x410000, end = 0x411000,
flags=PAGE_VALID|PAGE_READ|PAGE_WRITE)
with, I assume, the intention that that will make the memset() OK,
but page_set_flags() just sets up some data structure bits which will
mean that a subsequent SEGV will cause us to do a page_unprotect() that
sets the page as actually writeable. Unfortunately the SIGSEGV handler
is not installed until quite late in linux-user/main.c, so when the
memset() in zero_bss() SEGVs QEMU just dies.
Should we try to get the SEGV handler working earlier in initialization
(it's pretty hairy machinery so that could be tricky) or should
elfload.c be mprotect()ing things appropriately itself?
thanks
-- PMM
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: simple aarch64 binary can cause linux-user QEMU to segv in zero_bss()
2020-11-23 19:52 simple aarch64 binary can cause linux-user QEMU to segv in zero_bss() Peter Maydell
@ 2020-11-24 17:18 ` Richard Henderson
2020-11-24 17:31 ` Peter Maydell
0 siblings, 1 reply; 3+ messages in thread
From: Richard Henderson @ 2020-11-24 17:18 UTC (permalink / raw)
To: Peter Maydell, QEMU Developers, Laurent Vivier, Alex Bennée
On 11/23/20 11:52 AM, Peter Maydell wrote:
> Somebody reported this on stackoverflow. Before I spend too
> much time thinking about how this ought to work, does anybody
> have the elfload.c intended operation in their head still?
> Bug description and analysis of what goes wrong below:
>
> https://stackoverflow.com/questions/64956322/alignment-requirements-for-arm64-elf-executables-run-in-qemu-assembled-by-gas
>
> Given this trivial asm:
>
> ===begin program.s===
> // GNU Assembler, ARM64 Linux
>
> .bss
>
> .lcomm ARRAY, 16
>
> .text
>
> .global _start
>
> _start:
> mov x8, 93 // exit sys num
> mov x0, 0 // success
> svc 0
> ===endit===
...
> Should we try to get the SEGV handler working earlier in initialization
> (it's pretty hairy machinery so that could be tricky) or should
> elfload.c be mprotect()ing things appropriately itself?
elfload should be handling this.
I believe this should be fixed by
https://patchew.org/QEMU/20201118165206.2826-1-steplong@quicinc.com/
r~
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: simple aarch64 binary can cause linux-user QEMU to segv in zero_bss()
2020-11-24 17:18 ` Richard Henderson
@ 2020-11-24 17:31 ` Peter Maydell
0 siblings, 0 replies; 3+ messages in thread
From: Peter Maydell @ 2020-11-24 17:31 UTC (permalink / raw)
To: Richard Henderson; +Cc: Laurent Vivier, Alex Bennée, QEMU Developers
On Tue, 24 Nov 2020 at 17:18, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> On 11/23/20 11:52 AM, Peter Maydell wrote:
> > Somebody reported this on stackoverflow. Before I spend too
> > much time thinking about how this ought to work, does anybody
> > have the elfload.c intended operation in their head still?
> > Should we try to get the SEGV handler working earlier in initialization
> > (it's pretty hairy machinery so that could be tricky) or should
> > elfload.c be mprotect()ing things appropriately itself?
>
> elfload should be handling this.
>
> I believe this should be fixed by
>
> https://patchew.org/QEMU/20201118165206.2826-1-steplong@quicinc.com/
That does indeed seem to fix things. I have a couple of questions
about the patch that I'll make in that thread...
-- PMM
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2020-11-24 17:34 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-11-23 19:52 simple aarch64 binary can cause linux-user QEMU to segv in zero_bss() Peter Maydell
2020-11-24 17:18 ` Richard Henderson
2020-11-24 17:31 ` Peter Maydell
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).