mbox series

[0/4] linux-user: fix use of SIGRTMIN

Message ID 20200201122746.1478003-1-laurent@vivier.eu
Headers show
Series linux-user: fix use of SIGRTMIN | expand

Message

Laurent Vivier Feb. 1, 2020, 12:27 p.m. UTC
This series fixes the problem of the first real-time signals already
in use by the glibc that are not available for the target glibc.

Instead of reverting the first and last real-time signals we rely on
the value provided by the glibc (SIGRTMIN) to know the first available
signal and we map all the signals from this value to SIGRTMAX on top
of TARGET_SIGRTMIN. So the consequence is we have less available signals
in the target (generally 2) but all seems fine as at least 30 signals are
still available.

This has been tested with Go (golang 1.10.1 linux/arm64, bionic) on x86_64
fedora 31. We can avoid the failure in this case allowing the unsupported
signals when we don't provide the "act" parameters to sigaction, only the
"oldact" one. I have also run the LTP suite with several target and debian
based distros.

Laurent Vivier (4):
  linux-user: add missing TARGET_SIGRTMIN for hppa
  linux-user: cleanup signal.c
  linux-user: fix TARGET_NSIG and _NSIG uses
  linux-user: fix use of SIGRTMIN

 linux-user/hppa/target_signal.h |   1 +
 linux-user/signal.c             | 110 +++++++++++++++++++++++---------
 linux-user/trace-events         |   3 +
 3 files changed, 85 insertions(+), 29 deletions(-)

Comments

Taylor Simpson Feb. 3, 2020, 10:50 p.m. UTC | #1
FWIW, this removes the need for the target-specific code for Hexagon in signal.c.

Thanks,
Taylor

PS  Stay tuned for a Hexagon target patch series once this is merged.

> -----Original Message-----
> From: Laurent Vivier <laurent@vivier.eu>
> Sent: Saturday, February 1, 2020 6:28 AM
> To: qemu-devel@nongnu.org
> Cc: Josh Kunz <jkz@google.com>; milos.stojanovic@rt-rk.com; Matus Kysel
> <mkysel@tachyum.com>; Aleksandar Markovic <aleksandar.markovic@rt-
> rk.com>; Marlies Ruck <marlies.ruck@gmail.com>; Laurent Vivier
> <laurent@vivier.eu>; Peter Maydell <peter.maydell@linaro.org>; Taylor
> Simpson <tsimpson@quicinc.com>; Riku Voipio <riku.voipio@iki.fi>
> Subject: [PATCH 0/4] linux-user: fix use of SIGRTMIN
>
> This series fixes the problem of the first real-time signals already in use by
> the glibc that are not available for the target glibc.
>
> Instead of reverting the first and last real-time signals we rely on the value
> provided by the glibc (SIGRTMIN) to know the first available signal and we
> map all the signals from this value to SIGRTMAX on top of
> TARGET_SIGRTMIN. So the consequence is we have less available signals in
> the target (generally 2) but all seems fine as at least 30 signals are still
> available.
>
> This has been tested with Go (golang 1.10.1 linux/arm64, bionic) on x86_64
> fedora 31. We can avoid the failure in this case allowing the unsupported
> signals when we don't provide the "act" parameters to sigaction, only the
> "oldact" one. I have also run the LTP suite with several target and debian
> based distros.
>
> Laurent Vivier (4):
>   linux-user: add missing TARGET_SIGRTMIN for hppa
>   linux-user: cleanup signal.c
>   linux-user: fix TARGET_NSIG and _NSIG uses
>   linux-user: fix use of SIGRTMIN
>
>  linux-user/hppa/target_signal.h |   1 +
>  linux-user/signal.c             | 110 +++++++++++++++++++++++---------
>  linux-user/trace-events         |   3 +
>  3 files changed, 85 insertions(+), 29 deletions(-)
>
> --
> 2.24.1
>
Josh Kunz Feb. 4, 2020, 12:03 a.m. UTC | #2
On Sat, Feb 1, 2020 at 4:27 AM Laurent Vivier <laurent@vivier.eu> wrote:
> This has been tested with Go (golang 1.10.1 linux/arm64, bionic) on x86_64
> fedora 31. We can avoid the failure in this case allowing the unsupported
> signals when we don't provide the "act" parameters to sigaction, only the
> "oldact" one. I have also run the LTP suite with several target and debian
> based distros.

This breaks with go1.13+ (I also verified at hash 753d56d364)[1]. I
tested using an aarch64 guest on an x86 system, but this should
manifest on any architecture when the guest/host have the same number
of signals (and glibc reserves some host signals). From the traceback,
you can see it dies in `initsig` which is called at startup. Any Go
program should fail.

Since go does not use a libc, it assumes that all signals from
[1.._NSIG) are available[2], and will panic if it cannot do an
rt_sigaction for all of them. Go already has some special handling for
QEMU where it silently discards failing rt_sigaction calls to signals
32, 33, and 64 [3]. Since this patch reserves an extra signal for
__SIGRTMIN+1 as well, it blocks out guest signal 63 and Go fails to
initialize.

While I personally support this patch series (current handling of
guest glibc signals is broken), it *will* break Go binaries. I don't
know of a way to avoid this while supporting guest __SIGRTMIN+1,
without either doing true signal multiplexing, or patching Go.

[1] https://gist.github.com/joshkunz/b6c80724072cc1dce79a6253d40b016f
[2] https://github.com/golang/go/blob/67f0f83216930e053441500e2b28c3fa2b667581/src/runtime/signal_unix.go#L123
[3] https://github.com/golang/go/blob/master/src/runtime/os_linux.go#L466-L473

>
> Laurent Vivier (4):
>   linux-user: add missing TARGET_SIGRTMIN for hppa
>   linux-user: cleanup signal.c
>   linux-user: fix TARGET_NSIG and _NSIG uses
>   linux-user: fix use of SIGRTMIN
>
>  linux-user/hppa/target_signal.h |   1 +
>  linux-user/signal.c             | 110 +++++++++++++++++++++++---------
>  linux-user/trace-events         |   3 +
>  3 files changed, 85 insertions(+), 29 deletions(-)
>
> --
> 2.24.1
>
Laurent Vivier Feb. 4, 2020, 11:55 a.m. UTC | #3
Le 04/02/2020 à 01:03, Josh Kunz a écrit :
> On Sat, Feb 1, 2020 at 4:27 AM Laurent Vivier <laurent@vivier.eu> wrote:
>> This has been tested with Go (golang 1.10.1 linux/arm64, bionic) on x86_64
>> fedora 31. We can avoid the failure in this case allowing the unsupported
>> signals when we don't provide the "act" parameters to sigaction, only the
>> "oldact" one. I have also run the LTP suite with several target and debian
>> based distros.
> 
> This breaks with go1.13+ (I also verified at hash 753d56d364)[1]. I
> tested using an aarch64 guest on an x86 system, but this should
> manifest on any architecture when the guest/host have the same number
> of signals (and glibc reserves some host signals). From the traceback,
> you can see it dies in `initsig` which is called at startup. Any Go
> program should fail.

I reproduced the problem with aarch64/eoan, go1.12.10. Thank you.

> Since go does not use a libc, it assumes that all signals from
> [1.._NSIG) are available[2], and will panic if it cannot do an
> rt_sigaction for all of them. Go already has some special handling for
> QEMU where it silently discards failing rt_sigaction calls to signals
> 32, 33, and 64 [3]. Since this patch reserves an extra signal for
> __SIGRTMIN+1 as well, it blocks out guest signal 63 and Go fails to
> initialize.

We should add signal 63 here, but it's becoming not very clean.

> While I personally support this patch series (current handling of
> guest glibc signals is broken), it *will* break Go binaries. I don't
> know of a way to avoid this while supporting guest __SIGRTMIN+1,
> without either doing true signal multiplexing, or patching Go.

I think we could also simply ignore the error. As returning an error is
generally an abort condition even if the signal is never used, and it's
what we would do in go to avoid the problem. We will have problem later
with programs that really want to use the signal but I don't think we
can do better (do we know programs using 31 RT signals? or starting by
the end of the list?).

something like:

diff --git a/linux-user/signal.c b/linux-user/signal.c
index c4abacde49a0..169a84afe90b 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -866,8 +866,8 @@ int do_sigaction(int sig, const struct
target_sigaction *act,
         trace_signal_do_sigaction_host(host_sig, TARGET_NSIG);
         if (host_sig > SIGRTMAX) {
             /* we don't have enough host signals to map all target
signals */
-            qemu_log_mask(LOG_UNIMP, "Unsupported target signal #%d\n",
sig);
-            return -TARGET_EINVAL;
+            qemu_log_mask(LOG_UNIMP, "Unsupported target signal #%d,
ignored", sig);
+            return 0;
         }


Thanks,
Laurent
Josh Kunz Feb. 5, 2020, 2 a.m. UTC | #4
On Tue, Feb 4, 2020 at 3:55 AM Laurent Vivier <laurent@vivier.eu> wrote:
> We should add signal 63 here, but it's becoming not very clean.

https://golang.org/issue/33746 has some discussion of the issue. The
Go maintainers wanted to clean this up rather than just adding 63. The
patch is on ice right now because it was unclear if QEMU was going to
add a breaking patch. Now that QEMU has this behavior, I think they
would be willing to accept it, or something similar.

> I think we could also simply ignore the error. As returning an error is
> generally an abort condition even if the signal is never used, and it's
> what we would do in go to avoid the problem. We will have problem later
> with programs that really want to use the signal but I don't think we
> can do better (do we know programs using 31 RT signals? or starting by
> the end of the list?).

My general sense is that RT signals are very rarely used, and the only
uses I can find are based off SIGRTMIN. This sounds reasonable to me.

Josh