Skip to content

Commit 4a5950a

Browse files
ryaobehlendorf
authored andcommitted
Linux: zfs_fillpage() should handle partial pages from end of file
After 89cd219 was 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 predates 89cd219, 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 <[email protected]> Reviewed-by: Brian Atkinson <[email protected]> Signed-off-by: Richard Yao <[email protected]> Closes #14534
1 parent c7db374 commit 4a5950a

File tree

1 file changed

+5
-1
lines changed

1 file changed

+5
-1
lines changed

module/os/linux/zfs/zfs_vnops_os.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3784,12 +3784,16 @@ zfs_fillpage(struct inode *ip, struct page *pp)
37843784
u_offset_t io_off = page_offset(pp);
37853785
size_t io_len = PAGE_SIZE;
37863786

3787+
ASSERT3U(io_off, <, i_size);
3788+
37873789
if (io_off + io_len > i_size)
37883790
io_len = i_size - io_off;
37893791

37903792
void *va = kmap(pp);
37913793
int error = dmu_read(zfsvfs->z_os, ITOZ(ip)->z_id, io_off,
3792-
PAGE_SIZE, va, DMU_READ_PREFETCH);
3794+
io_len, va, DMU_READ_PREFETCH);
3795+
if (io_len != PAGE_SIZE)
3796+
memset((char *)va + io_len, 0, PAGE_SIZE - io_len);
37933797
kunmap(pp);
37943798

37953799
if (error) {

0 commit comments

Comments
 (0)