DivestOS/Patches/Linux_CVEs/CVE-2016-2504/3.4-^3.10/0001.patch

165 lines
5.5 KiB
Diff
Raw Normal View History

2017-11-07 17:32:46 -05:00
From f7c8dfd7060867d71fc370527e2e2278ffc3ba5e Mon Sep 17 00:00:00 2001
From: Sunil Khatri <sunilkh@codeaurora.org>
2017-11-07 17:32:46 -05:00
Date: Wed, 25 May 2016 21:13:46 +0530
Subject: msm: kgsl: Defer adding the mem entry to a process
If we add the mem entry pointer in the process idr and rb tree
too early, other threads can do operations on the entry by
guessing the ID or GPU address before the object gets returned
by the creating operation.
Allocate an ID for the object but don't assign the pointer until
right before the creating function returns ensuring that another
operation can't access it until it is ready.
CRs-Fixed: 1002974
Change-Id: Ic0dedbadc0dd2125bd2a7bcc152972c0555e07f8
Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Sunil Khatri <sunilkh@codeaurora.org>
---
2017-11-07 17:32:46 -05:00
drivers/gpu/msm/kgsl.c | 62 +++++++++++++++++++++++++++++++++++---------------
1 file changed, 44 insertions(+), 18 deletions(-)
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
2017-11-07 17:32:46 -05:00
index e1fd99e..ad1e4e0 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-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
2017-11-07 17:32:46 -05:00
@@ -296,27 +296,20 @@ kgsl_mem_entry_destroy(struct kref *kref)
EXPORT_SYMBOL(kgsl_mem_entry_destroy);
/**
- * kgsl_mem_entry_track_gpuaddr - Insert a mem_entry in the address tree and
- * assign it with a gpu address space before insertion
+ * kgsl_mem_entry_track_gpuaddr - Get the entry gpu address space before
+ * insertion to the process
* @process: the process that owns the memory
* @entry: the memory entry
*
- * @returns - 0 on succcess else error code
+ * @returns - 0 on success else error code
*
- * Insert the kgsl_mem_entry in to the rb_tree for searching by GPU address.
- * The assignment of gpu address and insertion into list needs to
- * happen with the memory lock held to avoid race conditions between
- * gpu address being selected and some other thread looking through the
- * rb list in search of memory based on gpuaddr
* This function should be called with processes memory spinlock held
2017-11-07 17:32:46 -05:00
- */
+*/
static int
2017-11-07 17:32:46 -05:00
kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process,
struct kgsl_mem_entry *entry)
{
int ret = 0;
- struct rb_node **node;
- struct rb_node *parent = NULL;
struct kgsl_pagetable *pagetable = process->pagetable;
assert_spin_locked(&process->mem_lock);
@@ -337,11 +330,22 @@ kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process,
pagetable = pagetable->mmu->securepagetable;
ret = kgsl_mmu_get_gpuaddr(pagetable, &entry->memdesc);
- if (ret)
- goto done;
- node = &process->mem_rb.rb_node;
+done:
+ return ret;
+}
2017-11-07 17:32:46 -05:00
+
+static void kgsl_mem_entry_commit_mem_list(struct kgsl_process_private *process,
2017-11-07 17:32:46 -05:00
+ struct kgsl_mem_entry *entry)
+{
+ struct rb_node **node;
+ struct rb_node *parent = NULL;
+
+ if (!entry->memdesc.gpuaddr)
+ return;
2017-11-07 17:32:46 -05:00
+ /* Insert mem entry in mem_rb tree */
+ node = &process->mem_rb.rb_node;
while (*node) {
struct kgsl_mem_entry *cur;
@@ -356,9 +360,20 @@ kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process,
rb_link_node(&entry->node, parent, node);
rb_insert_color(&entry->node, &process->mem_rb);
+}
-done:
- return ret;
+static void kgsl_mem_entry_commit_process(struct kgsl_process_private *process,
2017-11-07 17:32:46 -05:00
+ struct kgsl_mem_entry *entry)
+{
+ if (!entry)
+ return;
+
+ spin_lock(&entry->priv->mem_lock);
+ /* Insert mem entry in mem_rb tree */
+ kgsl_mem_entry_commit_mem_list(process, entry);
+ /* Replace mem entry in mem_idr using id */
+ idr_replace(&entry->priv->mem_idr, entry, entry->id);
+ spin_unlock(&entry->priv->mem_lock);
}
/**
@@ -407,7 +422,8 @@ kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry,
return -EBADF;
idr_preload(GFP_KERNEL);
spin_lock(&process->mem_lock);
- id = idr_alloc(&process->mem_idr, entry, 1, 0, GFP_NOWAIT);
+ /* Allocate the ID but don't attach the pointer just yet */
+ id = idr_alloc(&process->mem_idr, NULL, 1, 0, GFP_NOWAIT);
spin_unlock(&process->mem_lock);
idr_preload_end();
2017-11-07 17:32:46 -05:00
@@ -3279,6 +3295,7 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv,
trace_kgsl_mem_map(entry, param->fd);
+ kgsl_mem_entry_commit_process(private, entry);
return result;
error_attach:
2017-11-07 17:32:46 -05:00
@@ -3633,6 +3650,8 @@ long kgsl_ioctl_gpumem_alloc(struct kgsl_device_private *dev_priv,
param->gpuaddr = entry->memdesc.gpuaddr;
param->size = entry->memdesc.size;
param->flags = entry->memdesc.flags;
+
+ kgsl_mem_entry_commit_process(private, entry);
return result;
err:
kgsl_sharedmem_free(&entry->memdesc);
2017-11-07 17:32:46 -05:00
@@ -3678,6 +3697,8 @@ long kgsl_ioctl_gpumem_alloc_id(struct kgsl_device_private *dev_priv,
param->size = entry->memdesc.size;
param->mmapsize = kgsl_memdesc_mmapsize(&entry->memdesc);
param->gpuaddr = entry->memdesc.gpuaddr;
+
+ kgsl_mem_entry_commit_process(private, entry);
return result;
err:
if (entry)
2017-11-07 17:32:46 -05:00
@@ -4201,6 +4222,11 @@ static int kgsl_check_gpu_addr_collision(
spin_lock(&private->mem_lock);
kgsl_mem_entry_untrack_gpuaddr(private, entry);
spin_unlock(&private->mem_lock);
+ } else {
+ /* Insert mem entry in mem_rb tree */
+ spin_lock(&private->mem_lock);
+ kgsl_mem_entry_commit_mem_list(private, entry);
+ spin_unlock(&private->mem_lock);
}
} else {
trace_kgsl_mem_unmapped_area_collision(entry, addr, len,
2017-11-07 17:32:46 -05:00
--
cgit v1.1