From faaf431eeaa660994705364fd96ab72cb94ea41b Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi <stefanha@redhat.com>
Date: Sat, 20 Jun 2015 06:26:11 -0400
Subject: [PATCH] posix-aio-compat: fix acb->ev_signo race condition

RH-Author: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: <1434781571-31074-2-git-send-email-stefanha@redhat.com>
Patchwork-id: 66338
O-Subject: [RHEL-6.7 qemu-kvm PATCH 1/1] posix-aio-compat: fix acb->ev_signo race condition
Bugzilla: 1233292
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Jeff Nelson <jenelson@redhat.com>
RH-Acked-by: Richard Jones <rjones@redhat.com>

aiocb->ev_signo is used after aiocb->ret has been filled in and the list
lock has been released.  If posix_aio_read() is run in another thread at
the same time, aiocb->ev_signo may be fetched after acb has been freed.

This race condition results in spurious "kill failed failed: Invalid
argument" error messages and the QEMU process aborts.

Drop the ev_signo field since its value is always SIGUSR2.  This
eliminates the unsafe aiocb->ev_signo access.

Reported-by: Richard Jones <rjones@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Jeff E. Nelson <jen@redhat.com>
---
 posix-aio-compat.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/posix-aio-compat.c b/posix-aio-compat.c
index df09e38..f8c70d8 100644
--- a/posix-aio-compat.c
+++ b/posix-aio-compat.c
@@ -43,7 +43,6 @@ struct qemu_paiocb {
     int aio_niov;
     size_t aio_nbytes;
 #define aio_ioctl_cmd   aio_nbytes /* for QEMU_AIO_IOCTL */
-    int ev_signo;
     off_t aio_offset;
 
     QTAILQ_ENTRY(qemu_paiocb) node;
@@ -382,7 +381,7 @@ static void *aio_thread(void *unused)
         idle_threads++;
         mutex_unlock(&lock);
 
-        if (kill(pid, aiocb->ev_signo)) die("kill failed");
+        if (kill(pid, SIGUSR2)) die("kill failed");
     }
 
     idle_threads--;
@@ -560,7 +559,6 @@ BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
     acb = qemu_aio_get(&raw_aiocb_info, bs, cb, opaque);
     acb->aio_type = type;
     acb->aio_fildes = fd;
-    acb->ev_signo = SIGUSR2;
 
     if (qiov) {
         acb->aio_iov = qiov->iov;
@@ -588,7 +586,6 @@ BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd,
         return NULL;
     acb->aio_type = QEMU_AIO_IOCTL;
     acb->aio_fildes = fd;
-    acb->ev_signo = SIGUSR2;
     acb->aio_offset = 0;
     acb->aio_ioctl_buf = buf;
     acb->aio_ioctl_cmd = req;
-- 
1.8.3.1

