diff --git a/mm/shmem.c b/mm/shmem.c index 774f4b18ff5c..8ea776e52823 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -3617,6 +3617,7 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset, struct shmem_inode_info *info = SHMEM_I(inode); struct shmem_falloc shmem_falloc; pgoff_t start, index, end, undo_fallocend; + loff_t aligned_end; int error; if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) @@ -3673,8 +3674,15 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset, goto out; } + /* Check for wraparound */ + if (check_add_overflow(offset + len, (loff_t)PAGE_SIZE - 1, + &aligned_end)) { + error = -EFBIG; + goto out; + } + start = offset >> PAGE_SHIFT; - end = (offset + len + PAGE_SIZE - 1) >> PAGE_SHIFT; + end = aligned_end >> PAGE_SHIFT; /* Try to avoid a swapstorm if len is impossible to satisfy */ if (sbinfo->max_blocks && end - start > sbinfo->max_blocks) { error = -ENOSPC;