|
@@ -136,17 +136,26 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
|
|
vma->vm_flags |= VM_HUGETLB | VM_DONTEXPAND;
|
|
vma->vm_flags |= VM_HUGETLB | VM_DONTEXPAND;
|
|
vma->vm_ops = &hugetlb_vm_ops;
|
|
vma->vm_ops = &hugetlb_vm_ops;
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Offset passed to mmap (before page shift) could have been
|
|
|
|
+ * negative when represented as a (l)off_t.
|
|
|
|
+ */
|
|
|
|
+ if (((loff_t)vma->vm_pgoff << PAGE_SHIFT) < 0)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
if (vma->vm_pgoff & (~huge_page_mask(h) >> PAGE_SHIFT))
|
|
if (vma->vm_pgoff & (~huge_page_mask(h) >> PAGE_SHIFT))
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
vma_len = (loff_t)(vma->vm_end - vma->vm_start);
|
|
vma_len = (loff_t)(vma->vm_end - vma->vm_start);
|
|
|
|
+ len = vma_len + ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
|
|
|
|
+ /* check for overflow */
|
|
|
|
+ if (len < vma_len)
|
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
inode_lock(inode);
|
|
inode_lock(inode);
|
|
file_accessed(file);
|
|
file_accessed(file);
|
|
|
|
|
|
ret = -ENOMEM;
|
|
ret = -ENOMEM;
|
|
- len = vma_len + ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
|
|
|
|
-
|
|
|
|
if (hugetlb_reserve_pages(inode,
|
|
if (hugetlb_reserve_pages(inode,
|
|
vma->vm_pgoff >> huge_page_order(h),
|
|
vma->vm_pgoff >> huge_page_order(h),
|
|
len >> huge_page_shift(h), vma,
|
|
len >> huge_page_shift(h), vma,
|
|
@@ -155,7 +164,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
|
|
|
|
|
|
ret = 0;
|
|
ret = 0;
|
|
if (vma->vm_flags & VM_WRITE && inode->i_size < len)
|
|
if (vma->vm_flags & VM_WRITE && inode->i_size < len)
|
|
- inode->i_size = len;
|
|
|
|
|
|
+ i_size_write(inode, len);
|
|
out:
|
|
out:
|
|
inode_unlock(inode);
|
|
inode_unlock(inode);
|
|
|
|
|