On 27 February 2014 13:20, Michael Matz matz@suse.de wrote:
On Wed, 26 Feb 2014, Dann Frazier wrote:
I've narrowed down the changes that seem to prevent both types of segfaults to the following changes that introduce a wrapper around sigprocmask:
https://github.com/susematz/qemu/commit/f1542ae9fe10d5a241fc2624ecaef5f0948e... https://github.com/susematz/qemu/commit/4e5e1607758841c760cda4652b0ee7a6bc6e... https://github.com/susematz/qemu/commit/63eb8d3ea58f58d5857153b0c632def1bbd0...
I'm not sure if this is a real fix or just papering over my issue -
I've cleaned up these a bit (and added a bunch of missing wrapper calls) and am testing them now. I'll post them to qemu-devel when that's done.
It's fixing the issue, but strictly speaking introduces an QoI problem. SIGSEGV must not be controllable by the guest, it needs to be always deliverable to qemu; that is what's fixed.
The QoI problem introduced is that with the implementation as is, the fiddling with SIGSEGV is detectable by the guest. E.g. if it installs a segv handler, blocks segv, then forces a segfault, checks that it didn't arrive, then unblocks segv and checks that it now arrives, such testcase would be able to detect that in fact it couldn't block SIGSEGV.
My rework opts to track with a flag whether SIGSEGV is blocked by the guest or not; this is fairly straightforward.
To fix also that latter part it'd need a further per-thread flag segv_blocked_p which needs to be checked before actually delivering a guest-directed SIGSEGV (in comparison to a qemu-directed SEGV), and otherwise requeue it. That's made a bit complicated when the SEGV was process-directed (not thread-directed) because in that case it needs to be delivered as long as there's _any_ thread which has it unblocked. So given the above undefinedness for sane uses of SEGVs it didn't seem worth the complication of having an undetectable virtualization of SIGSEGV.
I don't bother to emulate to this level though -- if we get a guest directed SIGSEGV and the target has it blocked then we assume it was a from-the-kernel SEGV (ie guest dereferenced NULL or similar) and treat it as the kernel force_sig_info() does: behave as if the default SEGV handler was installed. This seems a reasonable compromise since I assume people don't typically go around sending manual SEGVs to other processes and threads.
thanks -- PMM