mirror of
				https://git.proxmox.com/git/mirror_zfs.git
				synced 2025-10-26 18:05:04 +03:00 
			
		
		
		
	Linux: zfs_fillpage() should handle partial pages from end of file
After89cd2197b9was merged, Clang's static analyzer began complaining about a dead assignment in `zfs_fillpage()`. Upon inspection, I noticed that the dead assignment was because we are not using the calculated io_len that we should use to avoid asking the DMU to read past the end of a file. This should result in `dmu_buf_hold_array_by_dnode()` calling `zfs_panic_recover()`. This issue predates89cd2197b9, but its simplification of zfs_fillpage() eliminated the only use of the assignment to io_len, which made Clang's static analyzer complain about the issue. Also, as a precaution, we add an assertion that io_offset < i_size. If this ever fails, bad things will happen. Otherwise, we are blindly trusting the kernel not to give us invalid offsets. We continue to blindly trust it on non-debug kernels. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Brian Atkinson <batkinson@lanl.gov> Signed-off-by: Richard Yao <richard.yao@alumni.stonybrook.edu> Closes #14534
This commit is contained in:
		
							parent
							
								
									0f9ed58f43
								
							
						
					
					
						commit
						dd108f5d73
					
				| @ -3977,12 +3977,16 @@ zfs_fillpage(struct inode *ip, struct page *pp) | |||||||
| 	u_offset_t io_off = page_offset(pp); | 	u_offset_t io_off = page_offset(pp); | ||||||
| 	size_t io_len = PAGE_SIZE; | 	size_t io_len = PAGE_SIZE; | ||||||
| 
 | 
 | ||||||
|  | 	ASSERT3U(io_off, <, i_size); | ||||||
|  | 
 | ||||||
| 	if (io_off + io_len > i_size) | 	if (io_off + io_len > i_size) | ||||||
| 		io_len = i_size - io_off; | 		io_len = i_size - io_off; | ||||||
| 
 | 
 | ||||||
| 	void *va = kmap(pp); | 	void *va = kmap(pp); | ||||||
| 	int error = dmu_read(zfsvfs->z_os, ITOZ(ip)->z_id, io_off, | 	int error = dmu_read(zfsvfs->z_os, ITOZ(ip)->z_id, io_off, | ||||||
| 	    PAGE_SIZE, va, DMU_READ_PREFETCH); | 	    io_len, va, DMU_READ_PREFETCH); | ||||||
|  | 	if (io_len != PAGE_SIZE) | ||||||
|  | 		memset((char *)va + io_len, 0, PAGE_SIZE - io_len); | ||||||
| 	kunmap(pp); | 	kunmap(pp); | ||||||
| 
 | 
 | ||||||
| 	if (error) { | 	if (error) { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Richard Yao
						Richard Yao