[PATCH 0/3] linux-user: Implement x86_64 vsyscalls

Richard Henderson posted 3 patches 1 week ago
Test docker-mingw@fedora passed
Test checkpatch passed
Test docker-quick@centos7 passed
Test FreeBSD passed
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20200114210921.11216-1-richard.henderson@linaro.org
Maintainers: Paolo Bonzini <pbonzini@redhat.com>, Riku Voipio <riku.voipio@iki.fi>, Richard Henderson <rth@twiddle.net>, Eduardo Habkost <ehabkost@redhat.com>, Laurent Vivier <laurent@vivier.eu>
target/i386/cpu.h          |   6 +-
linux-user/i386/cpu_loop.c | 197 ++++++++++++++++++++++++++-----------
target/i386/translate.c    |  16 ++-
3 files changed, 155 insertions(+), 64 deletions(-)

[PATCH 0/3] linux-user: Implement x86_64 vsyscalls

Posted by Richard Henderson 1 week ago
The x86_64 abi has a legacy vsyscall page.  The kernel folk
have been trying to deprecate this since at least v3.1, but

(1) We don't implement the vdso that replaces vsyscalls,
(2) As of v5.5, the vsyscall page is still enabled by default.

This lack is affecting Peter's linux-user testing.

The dependency is not obvious because Peter is running the tests
on x86_64, so the host is providing a vsyscall page to qemu.

Because of how user-only memory operations are handled, with no
validation of guest vs host pages, so long as qemu chooses to
run with guest_base == 0, the guest may Just So Happen to read
the host's vsyscall page.

Complicating this, new OS releases may use a kernel configured
with CONFIG_LEGACY_VSYSCALL_XONLY=y, which means the the vsyscall
page cannot be read, only executed.  Which means that the guest
then cannot read the host vsyscall page during translation and
will SIGSEGV.

Exactly which of these many variables is affecting Peter's testing
with Ubuntu 18.04 of my TCG merge, I'm not exactly sure.  I suspect
that it is the change to drop the textseg_addr adjustment to user-only
static binaries.  IIRC bionic does not support -static-pie, which is
the preferred replacement.  This could mean that the host and guest
binaries overlap, which leads to guest_base != 0.

I vaguely remember someone (Paolo?) implementing something like
this many years ago, but clearly it never got merged.

In any case, this emulation has been missing for too long.


r~


Richard Henderson (3):
  target/i386: Renumber EXCP_SYSCALL
  linux-user/i386: Split out gen_signal
  linux-user/i386: Emulate x86_64 vsyscalls

 target/i386/cpu.h          |   6 +-
 linux-user/i386/cpu_loop.c | 197 ++++++++++++++++++++++++++-----------
 target/i386/translate.c    |  16 ++-
 3 files changed, 155 insertions(+), 64 deletions(-)

-- 
2.20.1


Re: [PATCH 0/3] linux-user: Implement x86_64 vsyscalls

Posted by Alex Bennée 1 week ago
Richard Henderson <richard.henderson@linaro.org> writes:

> The x86_64 abi has a legacy vsyscall page.  The kernel folk
> have been trying to deprecate this since at least v3.1, but
>
> (1) We don't implement the vdso that replaces vsyscalls,
> (2) As of v5.5, the vsyscall page is still enabled by default.
>
> This lack is affecting Peter's linux-user testing.
>
> The dependency is not obvious because Peter is running the tests
> on x86_64, so the host is providing a vsyscall page to qemu.
>
> Because of how user-only memory operations are handled, with no
> validation of guest vs host pages, so long as qemu chooses to
> run with guest_base == 0, the guest may Just So Happen to read
> the host's vsyscall page.
>
> Complicating this, new OS releases may use a kernel configured
> with CONFIG_LEGACY_VSYSCALL_XONLY=y, which means the the vsyscall
> page cannot be read, only executed.  Which means that the guest
> then cannot read the host vsyscall page during translation and
> will SIGSEGV.
>
> Exactly which of these many variables is affecting Peter's testing
> with Ubuntu 18.04 of my TCG merge, I'm not exactly sure.  I suspect
> that it is the change to drop the textseg_addr adjustment to user-only
> static binaries.  IIRC bionic does not support -static-pie, which is
> the preferred replacement.  This could mean that the host and guest
> binaries overlap, which leads to guest_base != 0.
>
> I vaguely remember someone (Paolo?) implementing something like
> this many years ago, but clearly it never got merged.
>
> In any case, this emulation has been missing for too long.
>
>
> r~
>
>
> Richard Henderson (3):
>   target/i386: Renumber EXCP_SYSCALL
>   linux-user/i386: Split out gen_signal
>   linux-user/i386: Emulate x86_64 vsyscalls

And realising I didn't read it properly:

/x86_64-linux-user/qemu-x86_64 ~/lsrc/linux.git/tools/testing/selftests/x86/test_vsyscall_64
[WARN]  failed to find vDSO
        no vsyscall map in /proc/self/maps
[RUN]   test gettimeofday()
[RUN]   test time()
[RUN]   getcpu() on CPU 0
[RUN]   getcpu() on CPU 1
[RUN]   Checking read access to the vsyscall page
[OK]    We do not have read access: #PF(0x4)
[RUN]   Make sure that vsyscalls really page fault
**
ERROR:/home/alex/lsrc/qemu.git/linux-user/x86_64/../i386/cpu_loop.c:185:emulate_vsyscall: assertion failed: (ret != -TARGET_EFAULT)
qemu:handle_cpu_signal received signal outside vCPU context @ pc=0x7f6eed31b613

-- 
Alex Bennée

Re: [PATCH 0/3] linux-user: Implement x86_64 vsyscalls

Posted by Richard Henderson 1 week ago
On 1/16/20 4:30 AM, Alex Bennée wrote:
> /x86_64-linux-user/qemu-x86_64 ~/lsrc/linux.git/tools/testing/selftests/x86/test_vsyscall_64
> [WARN]  failed to find vDSO
>         no vsyscall map in /proc/self/maps
> [RUN]   test gettimeofday()
> [RUN]   test time()
> [RUN]   getcpu() on CPU 0
> [RUN]   getcpu() on CPU 1
> [RUN]   Checking read access to the vsyscall page
> [OK]    We do not have read access: #PF(0x4)
> [RUN]   Make sure that vsyscalls really page fault
> **
> ERROR:/home/alex/lsrc/qemu.git/linux-user/x86_64/../i386/cpu_loop.c:185:emulate_vsyscall: assertion failed: (ret != -TARGET_EFAULT)
> qemu:handle_cpu_signal received signal outside vCPU context @ pc=0x7f6eed31b613

Ok, thanks.


r~


Re: [PATCH 0/3] linux-user: Implement x86_64 vsyscalls

Posted by Alex Bennée 1 week ago
Richard Henderson <richard.henderson@linaro.org> writes:

> The x86_64 abi has a legacy vsyscall page.  The kernel folk
> have been trying to deprecate this since at least v3.1, but
>
> (1) We don't implement the vdso that replaces vsyscalls,
> (2) As of v5.5, the vsyscall page is still enabled by default.
>
> This lack is affecting Peter's linux-user testing.
>
> The dependency is not obvious because Peter is running the tests
> on x86_64, so the host is providing a vsyscall page to qemu.
>
> Because of how user-only memory operations are handled, with no
> validation of guest vs host pages, so long as qemu chooses to
> run with guest_base == 0, the guest may Just So Happen to read
> the host's vsyscall page.
>
> Complicating this, new OS releases may use a kernel configured
> with CONFIG_LEGACY_VSYSCALL_XONLY=y, which means the the vsyscall
> page cannot be read, only executed.  Which means that the guest
> then cannot read the host vsyscall page during translation and
> will SIGSEGV.
>
> Exactly which of these many variables is affecting Peter's testing
> with Ubuntu 18.04 of my TCG merge, I'm not exactly sure.  I suspect
> that it is the change to drop the textseg_addr adjustment to user-only
> static binaries.  IIRC bionic does not support -static-pie, which is
> the preferred replacement.  This could mean that the host and guest
> binaries overlap, which leads to guest_base != 0.
>
> I vaguely remember someone (Paolo?) implementing something like
> this many years ago, but clearly it never got merged.
>
> In any case, this emulation has been missing for too long.

It turns out the /sbin/ldconfig crash is a regression w.r.t from
stretch->buster so unrelated to these patches. However I've been giving
them a spin with the linux vdso selftests and stuff is breaking which I
guess means it's incomplete?

alex@23eb55f27ff8:~/lsrc/linux.git/tools/testing/selftests/x86$ make test_vdso
gcc -m64 -o /home/alex/lsrc/linux.git/tools/testing/selftests/x86/test_vdso_64 -O2 -g -std=gnu99 -pthread -Wall -no-pie -DCAN_BUILD_64 test_vdso.c -lrt -ldl
alex@23eb55f27ff8:~/lsrc/linux.git/tools/testing/selftests/x86$ ./test_vdso_64 
[WARN]  failed to find vDSO
[RUN]   Testing clock_gettime for clock CLOCK_REALTIME (0)...
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
Segmentation fault (core dumped)

Also from selftests/vDSO:

alex@23eb55f27ff8:~/lsrc/linux.git/tools/testing/selftests/vDSO$ ./vdso_test 
AT_SYSINFO_EHDR is not present!

vdso_standalone_test_x86 just exits with a non-zero value. I'm still
looking into that one.

>
>
> r~
>
>
> Richard Henderson (3):
>   target/i386: Renumber EXCP_SYSCALL
>   linux-user/i386: Split out gen_signal
>   linux-user/i386: Emulate x86_64 vsyscalls
>
>  target/i386/cpu.h          |   6 +-
>  linux-user/i386/cpu_loop.c | 197 ++++++++++++++++++++++++++-----------
>  target/i386/translate.c    |  16 ++-
>  3 files changed, 155 insertions(+), 64 deletions(-)


-- 
Alex Bennée

Re: [PATCH 0/3] linux-user: Implement x86_64 vsyscalls

Posted by Richard Henderson 1 week ago
On 1/16/20 4:05 AM, Alex Bennée wrote:
> It turns out the /sbin/ldconfig crash is a regression w.r.t from
> stretch->buster so unrelated to these patches. However I've been giving
> them a spin with the linux vdso selftests and stuff is breaking which I
> guess means it's incomplete?
...
> Also from selftests/vDSO:
> 
> alex@23eb55f27ff8:~/lsrc/linux.git/tools/testing/selftests/vDSO$ ./vdso_test 
> AT_SYSINFO_EHDR is not present!

This patch set is for vsyscall only, not vdso.


r~

Re: [PATCH 0/3] linux-user: Implement x86_64 vsyscalls

Posted by Laurent Vivier 1 week ago
Le 14/01/2020 à 22:09, Richard Henderson a écrit :
> The x86_64 abi has a legacy vsyscall page.  The kernel folk
> have been trying to deprecate this since at least v3.1, but
> 
> (1) We don't implement the vdso that replaces vsyscalls,
> (2) As of v5.5, the vsyscall page is still enabled by default.
> 
> This lack is affecting Peter's linux-user testing.
> 
> The dependency is not obvious because Peter is running the tests
> on x86_64, so the host is providing a vsyscall page to qemu.
> 
> Because of how user-only memory operations are handled, with no
> validation of guest vs host pages, so long as qemu chooses to
> run with guest_base == 0, the guest may Just So Happen to read
> the host's vsyscall page.
> 
> Complicating this, new OS releases may use a kernel configured
> with CONFIG_LEGACY_VSYSCALL_XONLY=y, which means the the vsyscall
> page cannot be read, only executed.  Which means that the guest
> then cannot read the host vsyscall page during translation and
> will SIGSEGV.
> 
> Exactly which of these many variables is affecting Peter's testing
> with Ubuntu 18.04 of my TCG merge, I'm not exactly sure.  I suspect
> that it is the change to drop the textseg_addr adjustment to user-only
> static binaries.  IIRC bionic does not support -static-pie, which is
> the preferred replacement.  This could mean that the host and guest
> binaries overlap, which leads to guest_base != 0.
> 
> I vaguely remember someone (Paolo?) implementing something like
> this many years ago, but clearly it never got merged.
> 
> In any case, this emulation has been missing for too long.
> 
> 
> r~
> 
> 
> Richard Henderson (3):
>   target/i386: Renumber EXCP_SYSCALL
>   linux-user/i386: Split out gen_signal
>   linux-user/i386: Emulate x86_64 vsyscalls
> 
>  target/i386/cpu.h          |   6 +-
>  linux-user/i386/cpu_loop.c | 197 ++++++++++++++++++++++++++-----------
>  target/i386/translate.c    |  16 ++-
>  3 files changed, 155 insertions(+), 64 deletions(-)
> 

Thank you Richard.

I'll take this series through the linux-user branch except if you prefer
to do the pull request yourself via another branch (x86 tcg?).

Thanks,
Laurent

Re: [PATCH 0/3] linux-user: Implement x86_64 vsyscalls

Posted by Richard Henderson 1 week ago
On 1/15/20 12:14 AM, Laurent Vivier wrote:
> I'll take this series through the linux-user branch except if you prefer
> to do the pull request yourself via another branch (x86 tcg?).

Through the linux-user branch is the right way, I think.
Thanks,

r~

Re: [PATCH 0/3] linux-user: Implement x86_64 vsyscalls

Posted by Laurent Desnogues 1 week ago
On Tue, Jan 14, 2020 at 10:09 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
[...]
> I vaguely remember someone (Paolo?) implementing something like
> this many years ago, but clearly it never got merged.

That was me back in 2009:

https://lists.gnu.org/archive/html/qemu-devel/2009-07/msg00881.html

Glad it will finally get an official fix.

Thanks,

Laurent

Re: [PATCH 0/3] linux-user: Implement x86_64 vsyscalls

Posted by Paolo Bonzini 1 week ago
On 14/01/20 22:09, Richard Henderson wrote:
> I vaguely remember someone (Paolo?) implementing something like
> this many years ago, but clearly it never got merged.

Nope, certainly not me.

> In any case, this emulation has been missing for too long.
> 
> 
> r~
> 
> 
> Richard Henderson (3):
>   target/i386: Renumber EXCP_SYSCALL
>   linux-user/i386: Split out gen_signal
>   linux-user/i386: Emulate x86_64 vsyscalls
> 
>  target/i386/cpu.h          |   6 +-
>  linux-user/i386/cpu_loop.c | 197 ++++++++++++++++++++++++++-----------
>  target/i386/translate.c    |  16 ++-
>  3 files changed, 155 insertions(+), 64 deletions(-)
> 

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>