Merge "msm: kgsl: Improved bounds checking on user specified parameters"
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 4ed9497..5904abb 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1443,42 +1443,43 @@
if (ret)
return ret;
- if (phys == 0) {
- ret = -EINVAL;
+ ret = -ERANGE;
+
+ if (phys == 0)
+ goto err;
+
+ /* 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 offset or size is not page aligned\n");
goto err;
}
- if (offset >= len) {
- ret = -EINVAL;
+ /* The size or offset can never be greater than the PMEM length */
+ if (offset >= len || 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;