Browse Source

fbdev: improve fb_mmap bounds checks

Improve fb_mmap bounds checks in gbefb, smscufx, udlfb and vfb drivers to
prevent possible uint overflows.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Cc: Steve Glendinning <steve.glendinning@smsc.com>
Cc: Bernie Thompson <bernie@plugable.com>
Tomi Valkeinen 12 years ago
parent
commit
04f8afbec3
4 changed files with 18 additions and 5 deletions
  1. 3 1
      drivers/video/gbefb.c
  2. 5 1
      drivers/video/smscufx.c
  3. 5 1
      drivers/video/udlfb.c
  4. 5 2
      drivers/video/vfb.c

+ 3 - 1
drivers/video/gbefb.c

@@ -1016,7 +1016,9 @@ static int gbefb_mmap(struct fb_info *info,
 	/* check range */
 	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
 		return -EINVAL;
-	if (offset + size > gbe_mem_size)
+	if (size > gbe_mem_size)
+		return -EINVAL;
+	if (offset > gbe_mem_size - size)
 		return -EINVAL;
 
 	/* remap using the fastest write-through mode on architecture */

+ 5 - 1
drivers/video/smscufx.c

@@ -782,7 +782,11 @@ static int ufx_ops_mmap(struct fb_info *info, struct vm_area_struct *vma)
 	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
 	unsigned long page, pos;
 
-	if (offset + size > info->fix.smem_len)
+	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+		return -EINVAL;
+	if (size > info->fix.smem_len)
+		return -EINVAL;
+	if (offset > info->fix.smem_len - size)
 		return -EINVAL;
 
 	pos = (unsigned long)info->fix.smem_start + offset;

+ 5 - 1
drivers/video/udlfb.c

@@ -324,7 +324,11 @@ static int dlfb_ops_mmap(struct fb_info *info, struct vm_area_struct *vma)
 	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
 	unsigned long page, pos;
 
-	if (offset + size > info->fix.smem_len)
+	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+		return -EINVAL;
+	if (size > info->fix.smem_len)
+		return -EINVAL;
+	if (offset > info->fix.smem_len - size)
 		return -EINVAL;
 
 	pos = (unsigned long)info->fix.smem_start + offset;

+ 5 - 2
drivers/video/vfb.c

@@ -420,9 +420,12 @@ static int vfb_mmap(struct fb_info *info,
 	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
 	unsigned long page, pos;
 
-	if (offset + size > info->fix.smem_len) {
+	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+		return -EINVAL;
+	if (size > info->fix.smem_len)
+		return -EINVAL;
+	if (offset > info->fix.smem_len - size)
 		return -EINVAL;
-	}
 
 	pos = (unsigned long)info->fix.smem_start + offset;