Thank you for your contribution! Sashiko AI review found 1 potential issue(s) 
to consider:
- [Critical] Passing a Hyper-V PFN directly to `pfn_to_page()` causes 
out-of-bounds memory accesses on architectures where `PAGE_SIZE > 4KB` (e.g., 
ARM64 with 64KB pages), and loses the intra-page chunk offset.
--

commit a844fbf018cd37eedc9a1f0aea79d6235c00bec3
Author: Anton Leontev <[email protected]>

hv_netvsc: use kmap_local_page in netvsc_copy_to_send_buf

This commit replaces phys_to_virt() with kmap_local_page() in
netvsc_copy_to_send_buf() to map skb fragment pages. This is intended to
fix a fatal transmit softirq fault on 32-bit x86 configurations with
HIGHMEM, where phys_to_virt() is only valid for LOWMEM addresses.

> diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
> index 59e95341f9b1e..6984f6c97257d 100644
> --- a/drivers/net/hyperv/netvsc.c
> +++ b/drivers/net/hyperv/netvsc.c

[ ... ]

> @@ -965,11 +966,13 @@ static void netvsc_copy_to_send_buf(struct 
> netvsc_device *net_device,
>       }
>  
>       for (i = 0; i < page_count; i++) {
> -             char *src = phys_to_virt(pb[i].pfn << HV_HYP_PAGE_SHIFT);
> +             struct page *page = pfn_to_page(pb[i].pfn);
> +             char *src = kmap_local_page(page);

[Severity: Critical]
Does this cause out-of-bounds memory accesses on architectures with a native
page size greater than 4KB?

The pb[i].pfn field contains a Hyper-V PFN, which always operates at 4KB
granularity. Passing this directly to pfn_to_page() assumes it is a native
Linux PFN.

On architectures where the native page size is larger than 4KB (such as
ARM64 with 64KB pages), the Hyper-V PFN is significantly larger than the
corresponding native Linux PFN. Using it with pfn_to_page() would return an
invalid struct page pointer.

Calling kmap_local_page() on this invalid pointer in
netvsc_copy_to_send_buf() and subsequently reading from it could lead to
memory corruption, out-of-bounds accesses, or kernel panics.

Could this also lose the native page offset of the original 4KB chunk within
the larger Linux page, resulting in an incorrect read offset during the
subsequent memcpy?

>               u32 offset = pb[i].offset;
>               u32 len = pb[i].len;
>  
>               memcpy(dest, (src + offset), len);
> +             kunmap_local(src);
>               dest += len;
>       }

-- 
Sashiko AI review ยท 
https://sashiko.dev/#/patchset/[email protected]?part=1

Reply via email to