Skip to content

Commit 166c635

Browse files
bspengler-ossRageLtMan
authored andcommitted
Fix HIGHMEM/kmap API violation in zfs_uiomove_bvec_impl()
Fix another instance where ZFS assumes multiple pages can be mapped at once via zfs_kmap_local(), resulting in crashes and potential memory corruption on HIGHMEM-enabled (typically 32-bit) systems. Signed-off-by: bspengler-oss <94915855+bspengler-oss@users.noreply.github.com>
1 parent 7b17cc5 commit 166c635

File tree

1 file changed

+5
-4
lines changed

1 file changed

+5
-4
lines changed

module/os/linux/zfs/zfs_uio.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,15 +100,16 @@ zfs_uiomove_bvec_impl(void *p, size_t n, zfs_uio_rw_t rw, zfs_uio_t *uio)
100100

101101
while (n && uio->uio_resid) {
102102
void *paddr;
103-
cnt = MIN(bv->bv_len - skip, n);
103+
size_t offset = bv->bv_offset + skip;
104+
cnt = MIN(PAGE_SIZE - (offset & ~PAGE_MASK), MIN(bv->bv_len - skip, n));
104105

105-
paddr = zfs_kmap_local(bv->bv_page);
106+
paddr = zfs_kmap_local(bv->bv_page + (offset >> PAGE_SHIFT));
106107
if (rw == UIO_READ) {
107108
/* Copy from buffer 'p' to the bvec data */
108-
memcpy(paddr + bv->bv_offset + skip, p, cnt);
109+
memcpy(paddr + (offset & ~PAGE_MASK), p, cnt);
109110
} else {
110111
/* Copy from bvec data to buffer 'p' */
111-
memcpy(p, paddr + bv->bv_offset + skip, cnt);
112+
memcpy(p, paddr + (offset & ~PAGE_MASK), cnt);
112113
}
113114
zfs_kunmap_local(paddr);
114115

0 commit comments

Comments
 (0)