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 <rageltman@sempervictus>
Reviewed-by: Rob Norris <robn@despairlabs.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: bspengler-oss <94915855+bspengler-oss@users.noreply.github.com>
Closes #15668
Closes #18030
This commit is contained in:
bspengler-oss 2025-11-17 20:56:07 -05:00 committed by Brian Behlendorf
parent 5946eeb8df
commit 25d755e108

View File

@ -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);