msm: kgsl: improved bounds checking on user-specified parameters

Verify that the user specified length for a PMEM region is smaller than the
size of the entire region as reported by the kernel APIs.

Change-Id: Ic0dedbad0127bdaed70eafc00238b44f982b093b
Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Iliyan Malchev <malchev@google.com>
This commit is contained in:
Ajay Dudani 2012-09-11 16:38:13 -06:00 committed by Iliyan Malchev
parent b6c60c851b
commit 5f63a32adc
2 changed files with 31 additions and 20 deletions

View file

@ -1543,42 +1543,51 @@ static int kgsl_setup_phys_file(struct kgsl_mem_entry *entry,
if (ret)
return ret;
ret = -ERANGE;
if (phys == 0) {
ret = -EINVAL;
KGSL_CORE_ERR("kgsl_get_phys_file returned phys=0\n");
goto err;
}
if (offset >= len) {
ret = -EINVAL;
/* Make sure the length of the region, the offset and the desired
* size are all page aligned or bail
*/
if ((len & ~PAGE_MASK) ||
(offset & ~PAGE_MASK) ||
(size & ~PAGE_MASK)) {
KGSL_CORE_ERR("length %lu, offset %u or size %u "
"is not page aligned\n",
len, offset, size);
goto err;
}
/* The size or offset can never be greater than the PMEM length */
if (offset >= len || size > len) {
KGSL_CORE_ERR("offset %u or size %u "
"exceeds pmem length %lu\n",
offset, size, len);
goto err;
}
/* If size is 0, then adjust it to default to the size of the region
* minus the offset. If size isn't zero, then make sure that it will
* fit inside of the region.
*/
if (size == 0)
size = len;
size = len - offset;
/* Adjust the size of the region to account for the offset */
size += offset & ~PAGE_MASK;
size = ALIGN(size, PAGE_SIZE);
if (_check_region(offset & PAGE_MASK, size, len)) {
KGSL_CORE_ERR("Offset (%ld) + size (%d) is larger"
"than pmem region length %ld\n",
offset & PAGE_MASK, size, len);
ret = -EINVAL;
else if (_check_region(offset, size, len))
goto err;
}
entry->priv_data = filep;
entry->memdesc.pagetable = pagetable;
entry->memdesc.size = size;
entry->memdesc.physaddr = phys + (offset & PAGE_MASK);
entry->memdesc.hostptr = (void *) (virt + (offset & PAGE_MASK));
entry->memdesc.physaddr = phys + offset;
entry->memdesc.hostptr = (void *) (virt + offset);
ret = memdesc_sg_phys(&entry->memdesc,
phys + (offset & PAGE_MASK), size);
ret = memdesc_sg_phys(&entry->memdesc, phys + offset, size);
if (ret)
goto err;

View file

@ -117,6 +117,8 @@ memdesc_sg_phys(struct kgsl_memdesc *memdesc,
unsigned int physaddr, unsigned int size)
{
memdesc->sg = kgsl_sg_alloc(1);
if (!memdesc->sg)
return -ENOMEM;
kmemleak_not_leak(memdesc->sg);