On Tue, Apr 11, 2017 at 03:51:58PM -0700, Mike Kravetz wrote: ... > diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c > index 7163fe0..dde8613 100644 > --- a/fs/hugetlbfs/inode.c > +++ b/fs/hugetlbfs/inode.c > @@ -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_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)) > return -EINVAL; > > 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; Andrew sent this patch to Linus today, so I know it's a little too late, but I think that getting len directly from vma like below might be a simpler fix. len = (loff_t)(vma->vm_end - vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT)); This shouldn't overflow because vma->vm_{end|start|pgoff} are unsigned long, but if worried you can add VM_BUG_ON_VMA(len < 0, vma). Thanks, Naoya Horiguchi > > inode_lock(inode); > file_accessed(file); > > ret = -ENOMEM; > - len = vma_len + ((loff_t)vma->vm_pgoff << PAGE_SHIFT); > - > if (hugetlb_reserve_pages(inode, > vma->vm_pgoff >> huge_page_order(h), > 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; > if (vma->vm_flags & VM_WRITE && inode->i_size < len) > - inode->i_size = len; > + i_size_write(inode, len); > out: > inode_unlock(inode); > > -- > 2.7.4 > > -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@xxxxxxxxx. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href