From 25d755e1084878250a2f1ca9bd8a9c3402b28844 Mon Sep 17 00:00:00 2001 From: bspengler-oss <94915855+bspengler-oss@users.noreply.github.com> Date: Mon, 17 Nov 2025 20:56:07 -0500 Subject: [PATCH] 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. Reviewed-by: RageLtMan Reviewed-by: Rob Norris Reviewed-by: Brian Behlendorf Signed-off-by: bspengler-oss <94915855+bspengler-oss@users.noreply.github.com> Closes #15668 Closes #18030 --- module/os/linux/zfs/zfs_uio.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/module/os/linux/zfs/zfs_uio.c b/module/os/linux/zfs/zfs_uio.c index d282f6d95..8f9b16199 100644 --- a/module/os/linux/zfs/zfs_uio.c +++ b/module/os/linux/zfs/zfs_uio.c @@ -100,15 +100,17 @@ zfs_uiomove_bvec_impl(void *p, size_t n, zfs_uio_rw_t rw, zfs_uio_t *uio) while (n && uio->uio_resid) { void *paddr; - cnt = MIN(bv->bv_len - skip, n); + size_t offset = bv->bv_offset + skip; + cnt = MIN(PAGE_SIZE - (offset & ~PAGE_MASK), + MIN(bv->bv_len - skip, n)); - paddr = zfs_kmap_local(bv->bv_page); + paddr = zfs_kmap_local(bv->bv_page + (offset >> PAGE_SHIFT)); if (rw == UIO_READ) { /* Copy from buffer 'p' to the bvec data */ - memcpy(paddr + bv->bv_offset + skip, p, cnt); + memcpy(paddr + (offset & ~PAGE_MASK), p, cnt); } else { /* Copy from bvec data to buffer 'p' */ - memcpy(p, paddr + bv->bv_offset + skip, cnt); + memcpy(p, paddr + (offset & ~PAGE_MASK), cnt); } zfs_kunmap_local(paddr);