base: genlock: protect kref counting with spinlock
A race condition exists where the attach may not kref_get
before the kref_put finished. The genlock_file_lock was
originally added to protect against this case however it
was not protecting the kref.
CRs-fixed: 359649
Change-Id: Iab1fc847c2d3357ec1be79b7cc3e004643126dec
Signed-off-by: Jeff Boody <jboody@codeaurora.org>
diff --git a/drivers/base/genlock.c b/drivers/base/genlock.c
index 5e1d7af..0686d20 100644
--- a/drivers/base/genlock.c
+++ b/drivers/base/genlock.c
@@ -56,7 +56,7 @@
* released while another process tries to attach it
*/
-static DEFINE_SPINLOCK(genlock_file_lock);
+static DEFINE_SPINLOCK(genlock_ref_lock);
static void genlock_destroy(struct kref *kref)
{
@@ -68,10 +68,8 @@
* still active after the lock gets released
*/
- spin_lock(&genlock_file_lock);
if (lock->file)
lock->file->private_data = NULL;
- spin_unlock(&genlock_file_lock);
kfree(lock);
}
@@ -203,19 +201,20 @@
* released and then attached
*/
- spin_lock(&genlock_file_lock);
+ spin_lock(&genlock_ref_lock);
lock = file->private_data;
- spin_unlock(&genlock_file_lock);
fput(file);
if (lock == NULL) {
+ spin_unlock(&genlock_ref_lock);
GENLOCK_LOG_ERR("File descriptor is invalid\n");
return ERR_PTR(-EINVAL);
}
handle->lock = lock;
kref_get(&lock->refcount);
+ spin_unlock(&genlock_ref_lock);
return lock;
}
@@ -595,7 +594,9 @@
}
spin_unlock_irqrestore(&handle->lock->lock, flags);
+ spin_lock(&genlock_ref_lock);
kref_put(&handle->lock->refcount, genlock_destroy);
+ spin_unlock(&genlock_ref_lock);
handle->lock = NULL;
handle->active = 0;
}