forked from mirrors/linux
		
	vfs: forbid write access when reading a file into memory
This patch is based on top of the "vfs: support for a common kernel file loader" patch set. In general when the kernel is reading a file into memory it does not want anything else writing to it. The kernel currently only forbids write access to a file being executed. This patch extends this locking to files being read by the kernel. Changelog: - moved function to kernel_read_file() - Mimi - updated patch description - Mimi Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@huawei.com> Cc: Al Viro <viro@ZenIV.linux.org.uk> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com> Reviewed-by: Luis R. Rodriguez <mcgrof@kernel.org> Acked-by: Kees Cook <keescook@chromium.org>
This commit is contained in:
		
							parent
							
								
									da20dfe6b5
								
							
						
					
					
						commit
						39d637af5a
					
				
					 1 changed files with 21 additions and 8 deletions
				
			
		
							
								
								
									
										29
									
								
								fs/exec.c
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								fs/exec.c
									
									
									
									
									
								
							| 
						 | 
					@ -850,15 +850,25 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size,
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = deny_write_access(file);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	i_size = i_size_read(file_inode(file));
 | 
						i_size = i_size_read(file_inode(file));
 | 
				
			||||||
	if (max_size > 0 && i_size > max_size)
 | 
						if (max_size > 0 && i_size > max_size) {
 | 
				
			||||||
		return -EFBIG;
 | 
							ret = -EFBIG;
 | 
				
			||||||
	if (i_size <= 0)
 | 
							goto out;
 | 
				
			||||||
		return -EINVAL;
 | 
						}
 | 
				
			||||||
 | 
						if (i_size <= 0) {
 | 
				
			||||||
 | 
							ret = -EINVAL;
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	*buf = vmalloc(i_size);
 | 
						*buf = vmalloc(i_size);
 | 
				
			||||||
	if (!*buf)
 | 
						if (!*buf) {
 | 
				
			||||||
		return -ENOMEM;
 | 
							ret = -ENOMEM;
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pos = 0;
 | 
						pos = 0;
 | 
				
			||||||
	while (pos < i_size) {
 | 
						while (pos < i_size) {
 | 
				
			||||||
| 
						 | 
					@ -876,18 +886,21 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (pos != i_size) {
 | 
						if (pos != i_size) {
 | 
				
			||||||
		ret = -EIO;
 | 
							ret = -EIO;
 | 
				
			||||||
		goto out;
 | 
							goto out_free;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = security_kernel_post_read_file(file, *buf, i_size, id);
 | 
						ret = security_kernel_post_read_file(file, *buf, i_size, id);
 | 
				
			||||||
	if (!ret)
 | 
						if (!ret)
 | 
				
			||||||
		*size = pos;
 | 
							*size = pos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out:
 | 
					out_free:
 | 
				
			||||||
	if (ret < 0) {
 | 
						if (ret < 0) {
 | 
				
			||||||
		vfree(*buf);
 | 
							vfree(*buf);
 | 
				
			||||||
		*buf = NULL;
 | 
							*buf = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						allow_write_access(file);
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL_GPL(kernel_read_file);
 | 
					EXPORT_SYMBOL_GPL(kernel_read_file);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue