qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] Signal handling bugs (and proposed fixes)


From: Andrei E. Warkentin
Subject: [Qemu-devel] Signal handling bugs (and proposed fixes)
Date: Wed, 2 Apr 2014 18:04:17 -0400

Hiya,

I found a couple of corner cases where signal handling fails in QEMU
linux-user support. "Signal handling" here being just a symptom -
actual problems are in TB / page management.

Here are a couple of simple tests
(https://github.com/andreiw/andreiw-wip/tree/master/qemu/tests). The
test:
1) Creates a page with two instructions - an illegal instruction and a 'ret'.
2) Sets up two handlers - SIGILL and SIGSEGV. On SIGILL, the page with
the instructions is unmapped (in sigtest.c, and set to PROT_NONE in
sigtest_mprotect.c), and the instruction pointer is set to point to
the next instruction - the ret. On SIGSEGV, the page is mapped back in
and the execution is supposed to continue successfully.

The first problem is a bug in page_check_range that cuts the loop
after the first page that needs to be  unprotected (whereas all pages
need to be checked in the range).

https://github.com/andreiw/andreiw-wip/blob/master/qemu/0001-qemu-fix-page_check_range.patch

With this patch, the above tests now hang instead of segfaulting QEMU.

The second problem is a bit more involved - the code generator assumes
that the translated code is always present. Jumping to NULL to land in
a SIGSEGV handler, or expecting to "fault in" code like the tests
above do, results in a deadlock condition. On a signal, QEMU tries
delivering the signal, longjmps back to cpu_loop, but the
tcg_ctx.tb_ctx.tb_lock is still held. So tb_gen_code must allow
backing out gracefully if the memory is unreadable.

I took the simpler approach - making sure the page didn't look
unmapped or mprotected to PROT_NONE. Checking explicit access bits is
a bad idea because different arches have different implicit access
right (i.e. X implies R, or W implies R, or R implies X, etc). Another
alternative is to have a safe memory probe function - i.e. take a
SIGSEGV and patch the return to return EFAULT (like a kernel ;-)), but
this would need an implementation for every arch QEMU runs on.

Verified both on AArch64 and i386 linux-user targets. Both tests
successfully exit.

https://github.com/andreiw/andreiw-wip/blob/master/qemu/0002-qemu-handle-tb_gen_code-getting-called-for-unmapped-.patch
https://github.com/andreiw/andreiw-wip/blob/master/qemu/0003-x86-implement-EXCP_TB_EFAULT.patch

(I initially reported this to Peter Maydell, and he suggested I should
post here instead)

-- 
A



reply via email to

[Prev in Thread] Current Thread [Next in Thread]