video: tegra: nvmap: Fix race condition in dupes dec
Krishna Reddy [Fri, 1 Feb 2013 20:29:54 +0000 (12:29 -0800)]
- Handle reference could be freed in the slow path. Hence, keep a copy
  of handle ptr.

Bug 1221693

Change-Id: Ia63df654c3f6f8eb2fcabbff13d413cf32251c42
Signed-off-by: Raghavendra VK <rvk@nvidia.com>
Reviewed-on: http://git-master/r/196545
Reviewed-by: Simone Willett <swillett@nvidia.com>
Tested-by: Simone Willett <swillett@nvidia.com>

drivers/video/tegra/nvmap/nvmap_handle.c

index 4195744..50bc73f 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Handle allocation and freeing routines for nvmap
  *
- * Copyright (c) 2009-2012, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2009-2013, NVIDIA CORPORATION. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -881,11 +881,17 @@ out:
  */
 void _nvmap_free(struct nvmap_client *client, struct nvmap_handle_ref *r)
 {
+       int dupes;
+       struct nvmap_handle *h = r->handle;
+
        nvmap_ref_lock(client);
-       if (r->handle->owner == client && atomic_read(&r->dupes) > 1) {
-               atomic_dec(&r->dupes);
+retry:
+       dupes = atomic_read(&r->dupes);
+       if (r->handle->owner == client && dupes > 1) {
+               if (atomic_cmpxchg(&r->dupes, dupes, dupes - 1) != dupes)
+                       goto retry;
                nvmap_ref_unlock(client);
-               nvmap_handle_put(r->handle);
+               nvmap_handle_put(h);
                return;
        } else {
                /* slow path */