mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-12-30 01:46:30 -05:00
103 lines
3.2 KiB
Diff
103 lines
3.2 KiB
Diff
|
From 0c46fc0f8fb7ffd26557b51b235d463a01ee75f5 Mon Sep 17 00:00:00 2001
|
||
|
From: Divya Ponnusamy <pdivya@codeaurora.org>
|
||
|
Date: Fri, 6 May 2016 13:24:37 -0600
|
||
|
Subject: msm: kgsl: Avoid race condition in ioctl_syncsource_destroy
|
||
|
|
||
|
If the ioctl syncsource_destroy is accessed by parallel
|
||
|
threads, where the spinlock is acquired by threads after
|
||
|
getting syncsource, then the simultaneous processes try
|
||
|
to remove the already destroyed syncsource->refcount by
|
||
|
the first thread that acquires this spinlock. This leads
|
||
|
to race condition while removing syncsource->idr.
|
||
|
|
||
|
Avoid separate lock inside getting syncsource, instead
|
||
|
acquire spinlock before we get the syncsource in
|
||
|
destroy ioctl so that the threads access the spinlock
|
||
|
and operate on syncsource without use-after-free issue.
|
||
|
|
||
|
Change-Id: I6add3800c40cd09f6e6e0cf2720e69059bd83cbc
|
||
|
Signed-off-by: Divya Ponnusamy <pdivya@codeaurora.org>
|
||
|
---
|
||
|
drivers/gpu/msm/kgsl_sync.c | 36 +++++++++++++++++-------------------
|
||
|
1 file changed, 17 insertions(+), 19 deletions(-)
|
||
|
|
||
|
diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c
|
||
|
index 44a0f11..df181ad 100644
|
||
|
--- a/drivers/gpu/msm/kgsl_sync.c
|
||
|
+++ b/drivers/gpu/msm/kgsl_sync.c
|
||
|
@@ -1,4 +1,4 @@
|
||
|
-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
|
||
|
+/* Copyright (c) 2012-2016, The Linux Foundation. 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 version 2 and
|
||
|
@@ -473,23 +473,23 @@ long kgsl_ioctl_syncsource_create(struct kgsl_device_private *dev_priv,
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
+ kref_init(&syncsource->refcount);
|
||
|
+ syncsource->private = private;
|
||
|
+
|
||
|
idr_preload(GFP_KERNEL);
|
||
|
spin_lock(&private->syncsource_lock);
|
||
|
id = idr_alloc(&private->syncsource_idr, syncsource, 1, 0, GFP_NOWAIT);
|
||
|
- spin_unlock(&private->syncsource_lock);
|
||
|
- idr_preload_end();
|
||
|
-
|
||
|
if (id > 0) {
|
||
|
- kref_init(&syncsource->refcount);
|
||
|
syncsource->id = id;
|
||
|
- syncsource->private = private;
|
||
|
-
|
||
|
param->id = id;
|
||
|
ret = 0;
|
||
|
} else {
|
||
|
ret = id;
|
||
|
}
|
||
|
|
||
|
+ spin_unlock(&private->syncsource_lock);
|
||
|
+ idr_preload_end();
|
||
|
+
|
||
|
out:
|
||
|
if (ret) {
|
||
|
if (syncsource && syncsource->oneshot)
|
||
|
@@ -547,25 +547,23 @@ long kgsl_ioctl_syncsource_destroy(struct kgsl_device_private *dev_priv,
|
||
|
{
|
||
|
struct kgsl_syncsource_destroy *param = data;
|
||
|
struct kgsl_syncsource *syncsource = NULL;
|
||
|
- struct kgsl_process_private *private;
|
||
|
-
|
||
|
- syncsource = kgsl_syncsource_get(dev_priv->process_priv,
|
||
|
- param->id);
|
||
|
+ struct kgsl_process_private *private = dev_priv->process_priv;
|
||
|
|
||
|
- if (syncsource == NULL)
|
||
|
- return -EINVAL;
|
||
|
+ spin_lock(&private->syncsource_lock);
|
||
|
+ syncsource = idr_find(&private->syncsource_idr, param->id);
|
||
|
|
||
|
- private = syncsource->private;
|
||
|
+ if (syncsource) {
|
||
|
+ idr_remove(&private->syncsource_idr, param->id);
|
||
|
+ syncsource->id = 0;
|
||
|
+ }
|
||
|
|
||
|
- spin_lock(&private->syncsource_lock);
|
||
|
- idr_remove(&private->syncsource_idr, param->id);
|
||
|
- syncsource->id = 0;
|
||
|
spin_unlock(&private->syncsource_lock);
|
||
|
|
||
|
+ if (syncsource == NULL)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
/* put reference from syncsource creation */
|
||
|
kgsl_syncsource_put(syncsource);
|
||
|
- /* put reference from getting the syncsource above */
|
||
|
- kgsl_syncsource_put(syncsource);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
--
|
||
|
cgit v1.1
|
||
|
|