summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarter Cooper <ccooper@codeaurora.org>2018-01-17 09:49:00 -0700
committersamit vats <svats@codeaurora.org>2018-02-16 15:22:12 +0530
commit4ae2e3bd187b74b660a341f154ede9159d9301c8 (patch)
tree615a817503900b04df812f5b6f445ccbab180cd9
parent38edeeedb5505a5d6148b8022ca2a5f9f3f4e5f6 (diff)
msm: kgsl: Properly remove ref count on gpuobj_sync failure
The user can pass bad data into kgsl_ioctl_gpuobj_sync(). If _copy_from_user() fails do to bad data, undo any current references taken through this ioctl call. Change-Id: I56195520b9dadba20ee419658fc2cbb282b8449c Signed-off-by: Carter Cooper <ccooper@codeaurora.org> Signed-off-by: samit vats <svats@codeaurora.org>
-rw-r--r--drivers/gpu/msm/kgsl.c34
1 files changed, 15 insertions, 19 deletions
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index de4ba83903f9..294e9ac8dbc6 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2018, 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
@@ -2943,7 +2943,7 @@ long kgsl_ioctl_gpuobj_sync(struct kgsl_device_private *dev_priv,
long ret = 0;
bool full_flush = false;
uint64_t size = 0;
- int i, count = 0;
+ int i;
void __user *ptr;
if (param->count == 0 || param->count > 128)
@@ -2955,8 +2955,8 @@ long kgsl_ioctl_gpuobj_sync(struct kgsl_device_private *dev_priv,
entries = kzalloc(param->count * sizeof(*entries), GFP_KERNEL);
if (entries == NULL) {
- ret = -ENOMEM;
- goto out;
+ kfree(objs);
+ return -ENOMEM;
}
ptr = to_user_ptr(param->objs);
@@ -2973,36 +2973,32 @@ long kgsl_ioctl_gpuobj_sync(struct kgsl_device_private *dev_priv,
if (entries[i] == NULL)
continue;
- count++;
-
if (!(objs[i].op & KGSL_GPUMEM_CACHE_RANGE))
size += entries[i]->memdesc.size;
else if (objs[i].offset < entries[i]->memdesc.size)
size += (entries[i]->memdesc.size - objs[i].offset);
full_flush = check_full_flush(size, objs[i].op);
- if (full_flush)
- break;
+ if (full_flush) {
+ trace_kgsl_mem_sync_full_cache(i, size);
+ flush_cache_all();
+ goto out;
+ }
ptr += sizeof(*objs);
}
- if (full_flush) {
- trace_kgsl_mem_sync_full_cache(count, size);
- flush_cache_all();
- } else {
- for (i = 0; !ret && i < param->count; i++)
- if (entries[i])
- ret = _kgsl_gpumem_sync_cache(entries[i],
- objs[i].offset, objs[i].length,
- objs[i].op);
- }
+ for (i = 0; !ret && i < param->count; i++)
+ if (entries[i])
+ ret = _kgsl_gpumem_sync_cache(entries[i],
+ objs[i].offset, objs[i].length,
+ objs[i].op);
+out:
for (i = 0; i < param->count; i++)
if (entries[i])
kgsl_mem_entry_put(entries[i]);
-out:
kfree(entries);
kfree(objs);