From: Yousef Alhouseen <[email protected]> Sent: Wednesday, June 24, 2026 10:22 AM
> Subject: [PATCH] hyperv: mshv: zero VTL hypercall output page There was a recent discussion about what prefix to use in the patch "Subject:" field for changes to MSHV VTL code. The agreement was to use just "mshv_vtl:". See [1]. [1] https://lore.kernel.org/linux-hyperv/[email protected]/ > > mshv_vtl_hvcall_call() copies output_size bytes from a freshly allocated > hypercall output page back to userspace. The page is currently allocated > without __GFP_ZERO, so any bytes not written by the hypervisor are copied > from stale page contents. This is a good find! Even though the VTL user space code is somewhat trusted, there should not be any circumstances where the kernel could copy random garbage to user space. > > Allocate the output page zeroed before issuing the hypercall. Hypercall output is usually no more than a few tens of bytes. Zeroing the entire page is a bit expensive. It would be sufficient to just zero output_size bytes. Standard practice is to *not* zero to the hypercall output area, since the hypercall invoker knows exactly how many bytes Hyper-V will return for a particular hypercall, and Hyper-V is responsible for not leaving any garbage. So it would be good to leave a code comment here about why the output area is being zero'ed contrary to that standard practice. I would note that many hypercalls don't return any output other than the hypercall status. If output_size is zero, allocating the output page could be skipped. But that's a further optimization for another patch. > Also check > both bounce-page allocations before using them so memory pressure cannot > turn the copy paths into NULL pointer dereferences. > > Signed-off-by: Yousef Alhouseen <[email protected]> > --- > drivers/hv/mshv_vtl_main.c | 12 +++++++++--- > 1 file changed, 9 insertions(+), 3 deletions(-) > > diff --git a/drivers/hv/mshv_vtl_main.c b/drivers/hv/mshv_vtl_main.c > index 0d3d41619..0365d207c 100644 > --- a/drivers/hv/mshv_vtl_main.c > +++ b/drivers/hv/mshv_vtl_main.c > @@ -1147,7 +1147,11 @@ static int mshv_vtl_hvcall_call(struct > mshv_vtl_hvcall_fd *fd, > * TODO: Take care of this when CVM support is added. > */ > in = (void *)__get_free_page(GFP_KERNEL); > - out = (void *)__get_free_page(GFP_KERNEL); > + out = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO); > + if (!in || !out) { > + ret = -ENOMEM; > + goto free_pages; > + } > > if (copy_from_user(in, (void __user *)hvcall.input_ptr, > hvcall.input_size)) { > ret = -EFAULT; > @@ -1162,8 +1166,10 @@ static int mshv_vtl_hvcall_call(struct > mshv_vtl_hvcall_fd *fd, > } > ret = put_user(hvcall.status, &hvcall_user->status); > free_pages: > - free_page((unsigned long)in); > - free_page((unsigned long)out); > + if (in) > + free_page((unsigned long)in); > + if (out) > + free_page((unsigned long)out); Testing "in" and "out" here isn't necessary. free_page() already has code to do nothing if its argument is zero. Michael > > return ret; > } > -- > 2.54.0 >

