diff options
author | 2018-04-17 10:43:57 +0800 | |
---|---|---|
committer | 2018-04-17 10:45:23 +0800 | |
commit | 30596ec32e2cd141d73ee8701386887def9e98c0 (patch) | |
tree | c8b0d725c46fd8fa504ec0bf41c92c6ff680b406 /fs/hugetlbfs/inode.c | |
parent | drm/i915/gvt: Dereference msi eventfd_ctx when it isn't used anymore (diff) | |
parent | Linux 4.17-rc1 (diff) | |
download | linux-dev-30596ec32e2cd141d73ee8701386887def9e98c0.tar.xz linux-dev-30596ec32e2cd141d73ee8701386887def9e98c0.zip |
Back merge 'drm-intel-fixes' into gvt-fixes
Need for 4.17-rc1
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
Diffstat (limited to 'fs/hugetlbfs/inode.c')
-rw-r--r-- | fs/hugetlbfs/inode.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 8fe1b0aa2896..d508c7844681 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -108,6 +108,16 @@ static void huge_pagevec_release(struct pagevec *pvec) pagevec_reinit(pvec); } +/* + * Mask used when checking the page offset value passed in via system + * calls. This value will be converted to a loff_t which is signed. + * Therefore, we want to check the upper PAGE_SHIFT + 1 bits of the + * value. The extra bit (- 1 in the shift value) is to take the sign + * bit into account. + */ +#define PGOFF_LOFFT_MAX \ + (((1UL << (PAGE_SHIFT + 1)) - 1) << (BITS_PER_LONG - (PAGE_SHIFT + 1))) + static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) { struct inode *inode = file_inode(file); @@ -127,12 +137,17 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) vma->vm_ops = &hugetlb_vm_ops; /* - * Offset passed to mmap (before page shift) could have been - * negative when represented as a (l)off_t. + * page based offset in vm_pgoff could be sufficiently large to + * overflow a loff_t when converted to byte offset. This can + * only happen on architectures where sizeof(loff_t) == + * sizeof(unsigned long). So, only check in those instances. */ - if (((loff_t)vma->vm_pgoff << PAGE_SHIFT) < 0) - return -EINVAL; + if (sizeof(unsigned long) == sizeof(loff_t)) { + if (vma->vm_pgoff & PGOFF_LOFFT_MAX) + return -EINVAL; + } + /* must be huge page aligned */ if (vma->vm_pgoff & (~huge_page_mask(h) >> PAGE_SHIFT)) return -EINVAL; |