drm/omap: fix leak & crash in omap_gem_op_sync()
authorTomi Valkeinen <tomi.valkeinen@ti.com>
Thu, 3 Dec 2015 15:56:08 +0000 (17:56 +0200)
committerPraneeth Bajjuri <praneeth@ti.com>
Sat, 5 Dec 2015 16:48:48 +0000 (11:48 -0500)
If omap_gem_op_sync is interrupted while it waits for notify to finish,
two issues occur:

 * the waiter struct is not freed
 * the wait condition is on stack, so on return of the
   waiting function, the stack is corrupted

Therefore, the wait is made non-interruptible. So, when omap_gem_op_sync
returns, it is gurranteed that the gem operation is complete.

The downside is that if, for whatever reason, the notify never happens,
the thread waits forever. Fixing this properly would require large
changes to omap_gem.c, and as we should always get a notify, this seems
like an acceptable fix for the time being.

Original patch by Subhajit Paul <subhajit_paul@ti.com>

Change-Id: I143e3a1a259cfc0961821f5a65b1fddf182efa60
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
drivers/gpu/drm/omapdrm/omap_gem.c

index c196c75c9d2b80d6ca81980e0933edf187f9ceee..afb7f93a39adcecf1204c79da07982e685910de9 100644 (file)
@@ -1205,18 +1205,9 @@ int omap_gem_op_sync(struct drm_gem_object *obj, enum omap_gem_op op)
                        SYNC("waited: %p", waiter);
                        list_add_tail(&waiter->list, &waiters);
                        spin_unlock(&sync_lock);
-                       ret = wait_event_interruptible(sync_event,
-                                       (waiter_task == NULL));
+                       wait_event(sync_event, (waiter_task == NULL));
                        spin_lock(&sync_lock);
-                       if (waiter_task) {
-                               SYNC("interrupted: %p", waiter);
-                               /* we were interrupted */
-                               list_del(&waiter->list);
-                               waiter_task = NULL;
-                       } else {
-                               /* freed in sync_op_update() */
-                               waiter = NULL;
-                       }
+                       waiter = NULL;
                }
                spin_unlock(&sync_lock);