From c34a46290855467787c14f262926226821f6e26f Mon Sep 17 00:00:00 2001
From: Alexandre Raymond <cerbere@gmail.com>
Date: Mon, 25 Jul 2011 23:25:58 -0400
Subject: [PATCH] Darwin: catch invalid return of sigwait()

For some unknown reason, sigwait() sometimes returns sig=0, which
is an invalid signal number, with rc=0.

This triggers a sequence of events which results in a segfault.

sigwait() returns sig=0, writes it to its pipe, which is picked up by
qemu_iohandler_poll(), which triggers sigfd_handler(), which attempts to
determine the handler for signal 0. Since the return code of sigaction() is not
checked, the code uses a bogus address in memory to call the handler, which
causes the segfault.

Signed-off-by: Alexandre Raymond <cerbere@gmail.com>
---
 compatfd.c |    4 ++++
 cpus.c     |   17 +++++++++++------
 2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/compatfd.c b/compatfd.c
index 31654c6..4a8af04 100644
--- a/compatfd.c
+++ b/compatfd.c
@@ -46,6 +46,10 @@ static void *sigwait_compat(void *opaque)
             struct qemu_signalfd_siginfo buffer;
             size_t offset = 0;
 
+#ifdef __APPLE__
+            if (sig == 0) continue;
+#endif
+
             memset(&buffer, 0, sizeof(buffer));
             buffer.ssi_signo = sig;
 
diff --git a/cpus.c b/cpus.c
index 6bf4e3f..0d9f828 100644
--- a/cpus.c
+++ b/cpus.c
@@ -360,6 +360,7 @@ static void sigfd_handler(void *opaque)
     struct qemu_signalfd_siginfo info;
     struct sigaction action;
     ssize_t len;
+    int rc;
 
     while (1) {
         do {
@@ -375,12 +376,16 @@ static void sigfd_handler(void *opaque)
             return;
         }
 
-        sigaction(info.ssi_signo, NULL, &action);
-        if ((action.sa_flags & SA_SIGINFO) && action.sa_sigaction) {
-            action.sa_sigaction(info.ssi_signo,
-                                (siginfo_t *)&info, NULL);
-        } else if (action.sa_handler) {
-            action.sa_handler(info.ssi_signo);
+        rc = sigaction(info.ssi_signo, NULL, &action);
+        if (rc == 0) {
+            if ((action.sa_flags & SA_SIGINFO) && action.sa_sigaction) {
+                action.sa_sigaction(info.ssi_signo,
+                                    (siginfo_t *)&info, NULL);
+            } else if (action.sa_handler) {
+                action.sa_handler(info.ssi_signo);
+            }
+        } else {
+            fprintf(stderr, "sigaction returned error : %s\n", strerror(errno));
         }
     }
 }
-- 
1.7.5

