diff options
Diffstat (limited to 'fs/open.c')
| -rw-r--r-- | fs/open.c | 39 | 
1 files changed, 25 insertions, 14 deletions
diff --git a/fs/open.c b/fs/open.c index 50e45bc7c4d8..22adbef7ecc2 100644 --- a/fs/open.c +++ b/fs/open.c @@ -247,6 +247,7 @@ int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)  {  	struct inode *inode = file_inode(file);  	long ret; +	loff_t sum;  	if (offset < 0 || len <= 0)  		return -EINVAL; @@ -319,8 +320,11 @@ int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)  	if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))  		return -ENODEV; -	/* Check for wrap through zero too */ -	if (((offset + len) > inode->i_sb->s_maxbytes) || ((offset + len) < 0)) +	/* Check for wraparound */ +	if (check_add_overflow(offset, len, &sum)) +		return -EFBIG; + +	if (sum > inode->i_sb->s_maxbytes)  		return -EFBIG;  	if (!file->f_op->fallocate) @@ -982,12 +986,11 @@ static int do_dentry_open(struct file *f,  	 */  	if (f->f_mode & FMODE_WRITE) {  		/* -		 * Paired with smp_mb() in collapse_file() to ensure nr_thps -		 * is up to date and the update to i_writecount by -		 * get_write_access() is visible. Ensures subsequent insertion -		 * of THPs into the page cache will fail. +		 * Depends on full fence from get_write_access() to synchronize +		 * against collapse_file() regarding i_writecount and nr_thps +		 * updates. Ensures subsequent insertion of THPs into the page +		 * cache will fail.  		 */ -		smp_mb();  		if (filemap_nr_thps(inode->i_mapping)) {  			struct address_space *mapping = inode->i_mapping; @@ -1004,11 +1007,6 @@ static int do_dentry_open(struct file *f,  		}  	} -	/* -	 * Once we return a file with FMODE_OPENED, __fput() will call -	 * fsnotify_close(), so we need fsnotify_open() here for symmetry. -	 */ -	fsnotify_open(f);  	return 0;  cleanup_all: @@ -1085,8 +1083,19 @@ EXPORT_SYMBOL(file_path);   */  int vfs_open(const struct path *path, struct file *file)  { +	int ret; +  	file->f_path = *path; -	return do_dentry_open(file, NULL); +	ret = do_dentry_open(file, NULL); +	if (!ret) { +		/* +		 * Once we return a file with FMODE_OPENED, __fput() will call +		 * fsnotify_close(), so we need fsnotify_open() here for +		 * symmetry. +		 */ +		fsnotify_open(file); +	} +	return ret;  }  struct file *dentry_open(const struct path *path, int flags, @@ -1177,8 +1186,10 @@ struct file *kernel_file_open(const struct path *path, int flags,  	error = do_dentry_open(f, NULL);  	if (error) {  		fput(f); -		f = ERR_PTR(error); +		return ERR_PTR(error);  	} + +	fsnotify_open(f);  	return f;  }  EXPORT_SYMBOL_GPL(kernel_file_open);  |