|
@@ -1324,6 +1324,35 @@ static inline int mlock_future_check(struct mm_struct *mm,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static inline u64 file_mmap_size_max(struct file *file, struct inode *inode)
|
|
|
|
+{
|
|
|
|
+ if (S_ISREG(inode->i_mode))
|
|
|
|
+ return inode->i_sb->s_maxbytes;
|
|
|
|
+
|
|
|
|
+ if (S_ISBLK(inode->i_mode))
|
|
|
|
+ return MAX_LFS_FILESIZE;
|
|
|
|
+
|
|
|
|
+ /* Special "we do even unsigned file positions" case */
|
|
|
|
+ if (file->f_mode & FMODE_UNSIGNED_OFFSET)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ /* Yes, random drivers might want more. But I'm tired of buggy drivers */
|
|
|
|
+ return ULONG_MAX;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static inline bool file_mmap_ok(struct file *file, struct inode *inode,
|
|
|
|
+ unsigned long pgoff, unsigned long len)
|
|
|
|
+{
|
|
|
|
+ u64 maxsize = file_mmap_size_max(file, inode);
|
|
|
|
+
|
|
|
|
+ if (maxsize && len > maxsize)
|
|
|
|
+ return false;
|
|
|
|
+ maxsize -= len;
|
|
|
|
+ if (pgoff > maxsize >> PAGE_SHIFT)
|
|
|
|
+ return false;
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* The caller must hold down_write(¤t->mm->mmap_sem).
|
|
* The caller must hold down_write(¤t->mm->mmap_sem).
|
|
*/
|
|
*/
|
|
@@ -1409,6 +1438,9 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
|
|
struct inode *inode = file_inode(file);
|
|
struct inode *inode = file_inode(file);
|
|
unsigned long flags_mask;
|
|
unsigned long flags_mask;
|
|
|
|
|
|
|
|
+ if (!file_mmap_ok(file, inode, pgoff, len))
|
|
|
|
+ return -EOVERFLOW;
|
|
|
|
+
|
|
flags_mask = LEGACY_MAP_MASK | file->f_op->mmap_supported_flags;
|
|
flags_mask = LEGACY_MAP_MASK | file->f_op->mmap_supported_flags;
|
|
|
|
|
|
switch (flags & MAP_TYPE) {
|
|
switch (flags & MAP_TYPE) {
|