Merge tag 'vfio-v5.7-rc4' of git://github.com/awilliam/linux-vfio
[linux-2.6-microblaze.git] / mm / vmalloc.c
index 6b8eeb0..9a8227a 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/llist.h>
 #include <linux/bitops.h>
 #include <linux/rbtree_augmented.h>
+#include <linux/overflow.h>
 
 #include <linux/uaccess.h>
 #include <asm/tlbflush.h>
@@ -3054,6 +3055,7 @@ finished:
  * @vma:               vma to cover
  * @uaddr:             target user address to start at
  * @kaddr:             virtual address of vmalloc kernel memory
+ * @pgoff:             offset from @kaddr to start at
  * @size:              size of map area
  *
  * Returns:    0 for success, -Exxx on failure
@@ -3066,9 +3068,15 @@ finished:
  * Similar to remap_pfn_range() (see mm/memory.c)
  */
 int remap_vmalloc_range_partial(struct vm_area_struct *vma, unsigned long uaddr,
-                               void *kaddr, unsigned long size)
+                               void *kaddr, unsigned long pgoff,
+                               unsigned long size)
 {
        struct vm_struct *area;
+       unsigned long off;
+       unsigned long end_index;
+
+       if (check_shl_overflow(pgoff, PAGE_SHIFT, &off))
+               return -EINVAL;
 
        size = PAGE_ALIGN(size);
 
@@ -3082,8 +3090,10 @@ int remap_vmalloc_range_partial(struct vm_area_struct *vma, unsigned long uaddr,
        if (!(area->flags & (VM_USERMAP | VM_DMA_COHERENT)))
                return -EINVAL;
 
-       if (kaddr + size > area->addr + get_vm_area_size(area))
+       if (check_add_overflow(size, off, &end_index) ||
+           end_index > get_vm_area_size(area))
                return -EINVAL;
+       kaddr += off;
 
        do {
                struct page *page = vmalloc_to_page(kaddr);
@@ -3122,7 +3132,7 @@ int remap_vmalloc_range(struct vm_area_struct *vma, void *addr,
                                                unsigned long pgoff)
 {
        return remap_vmalloc_range_partial(vma, vma->vm_start,
-                                          addr + (pgoff << PAGE_SHIFT),
+                                          addr, pgoff,
                                           vma->vm_end - vma->vm_start);
 }
 EXPORT_SYMBOL(remap_vmalloc_range);
@@ -3368,7 +3378,7 @@ retry:
                        goto overflow;
 
                /*
-                * If required width exeeds current VA block, move
+                * If required width exceeds current VA block, move
                 * base downwards and then recheck.
                 */
                if (base + end > va->va_end) {