[PATCH 56/60] linux-user/x86_64: Handle the vsyscall page in open_self_maps_{2, 4}

Richard Henderson posted 60 patches 1 year, 11 months ago
Maintainers: Richard Henderson <richard.henderson@linaro.org>, Paolo Bonzini <pbonzini@redhat.com>, Riku Voipio <riku.voipio@iki.fi>, Warner Losh <imp@bsdimp.com>, Kyle Evans <kevans@freebsd.org>, Stefan Berger <stefanb@linux.vnet.ibm.com>, Eduardo Habkost <eduardo@habkost.net>, Marcel Apfelbaum <marcel.apfelbaum@gmail.com>, "Philippe Mathieu-Daudé" <philmd@linaro.org>, Yanan Wang <wangyanan55@huawei.com>, Laurent Vivier <laurent@vivier.eu>, Peter Xu <peterx@redhat.com>, Fabiano Rosas <farosas@suse.de>, David Hildenbrand <david@redhat.com>, Peter Maydell <peter.maydell@linaro.org>, Nicholas Piggin <npiggin@gmail.com>, Daniel Henrique Barboza <danielhb413@gmail.com>, "Cédric Le Goater" <clg@kaod.org>, "Alex Bennée" <alex.bennee@linaro.org>, Yoshinori Sato <ysato@users.sourceforge.jp>
There is a newer version of this series
[PATCH 56/60] linux-user/x86_64: Handle the vsyscall page in open_self_maps_{2, 4}
Posted by Richard Henderson 1 year, 11 months ago
This is the only case in which we expect to have no host memory backing
for a guest memory page, because in general linux user processes cannot
map any pages in the top half of the 64-bit address space.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2170
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index e384e14248..bc8c06522f 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7994,6 +7994,10 @@ static void open_self_maps_4(const struct open_self_maps_data *d,
         path = "[heap]";
     } else if (start == info->vdso) {
         path = "[vdso]";
+#ifdef TARGET_X86_64
+    } else if (start == TARGET_VSYSCALL_PAGE) {
+        path = "[vsyscall]";
+#endif
     }
 
     /* Except null device (MAP_ANON), adjust offset for this fragment. */
@@ -8082,6 +8086,18 @@ static int open_self_maps_2(void *opaque, target_ulong guest_start,
     uintptr_t host_start = (uintptr_t)g2h_untagged(guest_start);
     uintptr_t host_last = (uintptr_t)g2h_untagged(guest_end - 1);
 
+#ifdef TARGET_X86_64
+    /*
+     * Because of the extremely high position of the page within the guest
+     * virtual address space, this is not backed by host memory at all.
+     * Therefore the loop below would fail.  This is the only instance
+     * of not having host backing memory.
+     */
+    if (guest_start == TARGET_VSYSCALL_PAGE) {
+        return open_self_maps_3(opaque, guest_start, guest_end, flags);
+    }
+#endif
+
     while (1) {
         IntervalTreeNode *n =
             interval_tree_iter_first(d->host_maps, host_start, host_start);
-- 
2.34.1


Re: [PATCH 56/60] linux-user/x86_64: Handle the vsyscall page in open_self_maps_{2, 4}
Posted by Michael Tokarev 1 year, 10 months ago
On 3/2/24 02:06, Richard Henderson wrote:
> This is the only case in which we expect to have no host memory backing
> for a guest memory page, because in general linux user processes cannot
> map any pages in the top half of the 64-bit address space.
> 
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2170
> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

This change fixes a real bug reported against debian qemu package,
https://bugs.debian.org/1068740 .

It looks like it should be picked up for stable-8.2.  And it looks
like I missed this one when it's been applied to master - usually
I take a look at all stuff going to master and pick fixes from there,
but not this time.  Is there anything else from this series which
needs to go to stable too?

Thanks,

/mjt

>   linux-user/syscall.c | 16 ++++++++++++++++
>   1 file changed, 16 insertions(+)
> 
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index e384e14248..bc8c06522f 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -7994,6 +7994,10 @@ static void open_self_maps_4(const struct open_self_maps_data *d,
>           path = "[heap]";
>       } else if (start == info->vdso) {
>           path = "[vdso]";
> +#ifdef TARGET_X86_64
> +    } else if (start == TARGET_VSYSCALL_PAGE) {
> +        path = "[vsyscall]";
> +#endif
>       }
>   
>       /* Except null device (MAP_ANON), adjust offset for this fragment. */
> @@ -8082,6 +8086,18 @@ static int open_self_maps_2(void *opaque, target_ulong guest_start,
>       uintptr_t host_start = (uintptr_t)g2h_untagged(guest_start);
>       uintptr_t host_last = (uintptr_t)g2h_untagged(guest_end - 1);
>   
> +#ifdef TARGET_X86_64
> +    /*
> +     * Because of the extremely high position of the page within the guest
> +     * virtual address space, this is not backed by host memory at all.
> +     * Therefore the loop below would fail.  This is the only instance
> +     * of not having host backing memory.
> +     */
> +    if (guest_start == TARGET_VSYSCALL_PAGE) {
> +        return open_self_maps_3(opaque, guest_start, guest_end, flags);
> +    }
> +#endif
> +
>       while (1) {
>           IntervalTreeNode *n =
>               interval_tree_iter_first(d->host_maps, host_start, host_start);