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>
This commit is contained in:
parent
38edeeedb5
commit
4ae2e3bd18
1 changed files with 15 additions and 19 deletions
|
@ -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
|
* 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
|
* 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;
|
long ret = 0;
|
||||||
bool full_flush = false;
|
bool full_flush = false;
|
||||||
uint64_t size = 0;
|
uint64_t size = 0;
|
||||||
int i, count = 0;
|
int i;
|
||||||
void __user *ptr;
|
void __user *ptr;
|
||||||
|
|
||||||
if (param->count == 0 || param->count > 128)
|
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);
|
entries = kzalloc(param->count * sizeof(*entries), GFP_KERNEL);
|
||||||
if (entries == NULL) {
|
if (entries == NULL) {
|
||||||
ret = -ENOMEM;
|
kfree(objs);
|
||||||
goto out;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr = to_user_ptr(param->objs);
|
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)
|
if (entries[i] == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
count++;
|
|
||||||
|
|
||||||
if (!(objs[i].op & KGSL_GPUMEM_CACHE_RANGE))
|
if (!(objs[i].op & KGSL_GPUMEM_CACHE_RANGE))
|
||||||
size += entries[i]->memdesc.size;
|
size += entries[i]->memdesc.size;
|
||||||
else if (objs[i].offset < entries[i]->memdesc.size)
|
else if (objs[i].offset < entries[i]->memdesc.size)
|
||||||
size += (entries[i]->memdesc.size - objs[i].offset);
|
size += (entries[i]->memdesc.size - objs[i].offset);
|
||||||
|
|
||||||
full_flush = check_full_flush(size, objs[i].op);
|
full_flush = check_full_flush(size, objs[i].op);
|
||||||
if (full_flush)
|
if (full_flush) {
|
||||||
break;
|
trace_kgsl_mem_sync_full_cache(i, size);
|
||||||
|
flush_cache_all();
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
ptr += sizeof(*objs);
|
ptr += sizeof(*objs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (full_flush) {
|
for (i = 0; !ret && i < param->count; i++)
|
||||||
trace_kgsl_mem_sync_full_cache(count, size);
|
if (entries[i])
|
||||||
flush_cache_all();
|
ret = _kgsl_gpumem_sync_cache(entries[i],
|
||||||
} else {
|
objs[i].offset, objs[i].length,
|
||||||
for (i = 0; !ret && i < param->count; i++)
|
objs[i].op);
|
||||||
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++)
|
for (i = 0; i < param->count; i++)
|
||||||
if (entries[i])
|
if (entries[i])
|
||||||
kgsl_mem_entry_put(entries[i]);
|
kgsl_mem_entry_put(entries[i]);
|
||||||
|
|
||||||
out:
|
|
||||||
kfree(entries);
|
kfree(entries);
|
||||||
kfree(objs);
|
kfree(objs);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue