[Spice-devel] [PATCH] char-device: spice_char_device_write_to_device: protect against recursion

Uri Lublin uril at redhat.com
Mon Feb 2 06:39:07 PST 2015


This fixes Spice's smart card support and is related to
commit 697f3214fd16adcd524456003619f7f44ddd031b.

Reported-by: Swapna Krishnan <skrishna at redhat.com>

Recursion is now possible starting with spice_char_device_wakeup calling
 spice_char_device_write_to_device that later (after going through qemu)
calls spice_char_device_wakeup.

The protecting code is the same to the one in the read path.

This function call loop makes the program to abort with the following messages:

  usb-ccid: chardev: unexpected message of type 3000000
  qemu: qemu_mutex_lock: Resource deadlock avoided
---

Should I attach the backtrace in the commit message ?

---
 server/char_device.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/server/char_device.c b/server/char_device.c
index c6dc45b..54357f0 100644
--- a/server/char_device.c
+++ b/server/char_device.c
@@ -64,6 +64,7 @@ struct SpiceCharDeviceState {
     SpiceCharDeviceInstance *sin;
 
     int during_read_from_device;
+    int during_write_to_device;
 
     SpiceCharDeviceCallbacks cbs;
     void *opaque;
@@ -437,6 +438,11 @@ static int spice_char_device_write_to_device(SpiceCharDeviceState *dev)
         return 0;
     }
 
+    /* protect against recursion with spice_char_device_wakeup */
+    if (dev->during_write_to_device++ > 0) {
+        return 0;
+    }
+
     spice_char_device_state_ref(dev);
 
     if (dev->write_to_dev_timer) {
@@ -461,6 +467,11 @@ static int spice_char_device_write_to_device(SpiceCharDeviceState *dev)
                     dev->cur_write_buf_pos;
         n = sif->write(dev->sin, dev->cur_write_buf_pos, write_len);
         if (n <= 0) {
+            if (dev->during_write_to_device > 1) {
+                dev->during_write_to_device = 1;
+                continue; /* a wakeup might have been called during the write -
+                             make sure it doesn't get lost */
+            }
             break;
         }
         total += n;
@@ -485,6 +496,7 @@ static int spice_char_device_write_to_device(SpiceCharDeviceState *dev)
         }
         dev->active = dev->active || total;
     }
+    dev->during_write_to_device = 0;
     spice_char_device_state_unref(dev);
     return total;
 }
-- 
2.1.0



More information about the Spice-devel mailing list