qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Warner Losh <imp@bsdimp.com>
To: qemu-devel@nongnu.org
Cc: Peter Maydell <peter.maydell@linaro.org>,
	Stacey Son <sson@FreeBSD.org>, Kyle Evans <kevans@freebsd.org>,
	Richard Henderson <richard.henderson@linaro.org>,
	def@FreeBSD.org, jrtc27@FreeBSD.org, Warner Losh <imp@bsdimp.com>
Subject: [PATCH v2 36/40] bsd-user/signal.c: implement do_sigaction
Date: Mon, 24 Jan 2022 18:29:43 -0700	[thread overview]
Message-ID: <20220125012947.14974-37-imp@bsdimp.com> (raw)
In-Reply-To: <20220125012947.14974-1-imp@bsdimp.com>

Implement the meat of the sigaction(2) system call with do_sigaction and
helper routiner block_signals (which is also used to implemement signal
masking so it's global).

Signed-off-by: Stacey Son <sson@FreeBSD.org>
Signed-off-by: Kyle Evans <kevans@freebsd.org>
Signed-off-by: Warner Losh <imp@bsdimp.com>

Pending Comments from Peter Maydell <peter.maydell@linaro.org>

(1) in block_signals, sigprocmast
For linux-user we rely on sigprocmask() in a multithreaded
program setting the signal mask for only the calling thread,
which isn't POSIX-mandated. (Arguably we should use
pthread_sigmask() instead, but we don't for basically
historical reasons since linux-user is host-OS-specific anyway.)
Does BSD have the same "this changes this thread's signal mask"
semantics for sigprocmask()?

(2) do_sigaction, first if validating which signals can be sent
Kernel seems to allow SIGKILL and SIGSTOP unless act is
non-NULL and act->sa_handler is SIG_DFL ?
https://github.com/freebsd/freebsd-src/blob/main/sys/kern/kern_sig.c#L747
(Compare linux-user commit ee3500d33a7431, a recent bugfix.)

(3) Noting confusion in do_sigaction between host and target
errnos (they are identical on BSD, but we should still return
the right sort in case it ever does matter).
---
 bsd-user/signal-common.h | 22 ++++++++++++
 bsd-user/signal.c        | 76 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 98 insertions(+)

diff --git a/bsd-user/signal-common.h b/bsd-user/signal-common.h
index 786ec592d18..7ff8e8f2e40 100644
--- a/bsd-user/signal-common.h
+++ b/bsd-user/signal-common.h
@@ -9,7 +9,29 @@
 #ifndef SIGNAL_COMMON_H
 #define SIGNAL_COMMON_H
 
+/**
+ * block_signals: block all signals while handling this guest syscall
+ *
+ * Block all signals, and arrange that the signal mask is returned to
+ * its correct value for the guest before we resume execution of guest code.
+ * If this function returns non-zero, then the caller should immediately
+ * return -TARGET_ERESTARTSYS to the main loop, which will take the pending
+ * signal and restart execution of the syscall.
+ * If block_signals() returns zero, then the caller can continue with
+ * emulation of the system call knowing that no signals can be taken
+ * (and therefore that no race conditions will result).
+ * This should only be called once, because if it is called a second time
+ * it will always return non-zero. (Think of it like a mutex that can't
+ * be recursively locked.)
+ * Signals will be unblocked again by process_pending_signals().
+ *
+ * Return value: non-zero if there was a pending signal, zero if not.
+ */
+int block_signals(void); /* Returns non zero if signal pending */
+
 long do_rt_sigreturn(CPUArchState *env);
+int do_sigaction(int sig, const struct target_sigaction *act,
+                struct target_sigaction *oact);
 abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
 long do_sigreturn(CPUArchState *env, abi_ulong addr);
 void force_sig_fault(int sig, int code, abi_ulong addr);
diff --git a/bsd-user/signal.c b/bsd-user/signal.c
index 05caf812ccb..42021556d65 100644
--- a/bsd-user/signal.c
+++ b/bsd-user/signal.c
@@ -309,6 +309,22 @@ static void tswap_siginfo(target_siginfo_t *tinfo, const target_siginfo_t *info)
     }
 }
 
+int block_signals(void)
+{
+    TaskState *ts = (TaskState *)thread_cpu->opaque;
+    sigset_t set;
+
+    /*
+     * It's OK to block everything including SIGSEGV, because we won't run any
+     * further guest code before unblocking signals in
+     * process_pending_signals().
+     */
+    sigfillset(&set);
+    sigprocmask(SIG_SETMASK, &set, 0);
+
+    return qatomic_xchg(&ts->signal_pending, 1);
+}
+
 /* Returns 1 if given signal should dump core if not handled. */
 static int core_dump_signal(int sig)
 {
@@ -554,6 +570,66 @@ static void host_signal_handler(int host_sig, siginfo_t *info, void *puc)
     cpu_exit(thread_cpu);
 }
 
+/* do_sigaction() return host values and errnos */
+int do_sigaction(int sig, const struct target_sigaction *act,
+        struct target_sigaction *oact)
+{
+    struct target_sigaction *k;
+    struct sigaction act1;
+    int host_sig;
+    int ret = 0;
+
+    if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL ||
+        sig == TARGET_SIGSTOP) {
+        return -EINVAL;
+    }
+
+    if (block_signals()) {
+        return -TARGET_ERESTART;
+    }
+
+    k = &sigact_table[sig - 1];
+    if (oact) {
+        oact->_sa_handler = tswapal(k->_sa_handler);
+        oact->sa_flags = tswap32(k->sa_flags);
+        oact->sa_mask = k->sa_mask;
+    }
+    if (act) {
+        /* XXX: this is most likely not threadsafe. */
+        k->_sa_handler = tswapal(act->_sa_handler);
+        k->sa_flags = tswap32(act->sa_flags);
+        k->sa_mask = act->sa_mask;
+
+        /* Update the host signal state. */
+        host_sig = target_to_host_signal(sig);
+        if (host_sig != SIGSEGV && host_sig != SIGBUS) {
+            memset(&act1, 0, sizeof(struct sigaction));
+            sigfillset(&act1.sa_mask);
+            act1.sa_flags = SA_SIGINFO;
+            if (k->sa_flags & TARGET_SA_RESTART) {
+                act1.sa_flags |= SA_RESTART;
+            }
+            /*
+             *  Note: It is important to update the host kernel signal mask to
+             *  avoid getting unexpected interrupted system calls.
+             */
+            if (k->_sa_handler == TARGET_SIG_IGN) {
+                act1.sa_sigaction = (void *)SIG_IGN;
+            } else if (k->_sa_handler == TARGET_SIG_DFL) {
+                if (fatal_signal(sig)) {
+                    act1.sa_sigaction = host_signal_handler;
+                } else {
+                    act1.sa_sigaction = (void *)SIG_DFL;
+                }
+            } else {
+                act1.sa_sigaction = host_signal_handler;
+            }
+            ret = sigaction(host_sig, &act1, NULL);
+        }
+    }
+    return ret;
+}
+
 static inline abi_ulong get_sigframe(struct target_sigaction *ka,
         CPUArchState *env, size_t frame_size)
 {
-- 
2.33.1



  parent reply	other threads:[~2022-01-25  2:04 UTC|newest]

Thread overview: 72+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-25  1:29 [PATCH v2 00/40] bsd-user: upstream our signal implementation Warner Losh
2022-01-25  1:29 ` [PATCH v2 01/40] bsd-user: Complete FreeBSD siginfo Warner Losh
2022-01-27  5:43   ` Richard Henderson
2022-01-25  1:29 ` [PATCH v2 02/40] bsd-user: Create setup_sigframe_arch to setup sigframe context Warner Losh
2022-01-27  5:45   ` Richard Henderson
2022-01-25  1:29 ` [PATCH v2 03/40] bsd-user/arm/signal.c: Implement setup_sigframe_arch for arm Warner Losh
2022-01-27  5:56   ` Richard Henderson
2022-01-27 16:42     ` Warner Losh
2022-01-25  1:29 ` [PATCH v2 04/40] bsd-user/arm/signal.c: get_mcontext should zero vfp data Warner Losh
2022-01-27  5:59   ` Richard Henderson
2022-01-27 15:44     ` Warner Losh
2022-01-25  1:29 ` [PATCH v2 05/40] bsd-user: Remove vestiges of signal queueing code Warner Losh
2022-01-27  6:16   ` Richard Henderson
2022-01-25  1:29 ` [PATCH v2 06/40] bsd-user: Bring in docs from linux-user for signal_pending Warner Losh
2022-01-27  6:16   ` Richard Henderson
2022-01-25  1:29 ` [PATCH v2 07/40] bsd-user/arm/target_arch_cpu.h: Move EXCP_ATOMIC to match linux-user Warner Losh
2022-01-25  1:29 ` [PATCH v2 08/40] bsd-user/signal.c: implement force_sig_fault Warner Losh
2022-01-25  1:29 ` [PATCH v2 09/40] bsd-user/signal-common.h: Move signal functions prototypes to here Warner Losh
2022-01-27  6:17   ` Richard Henderson
2022-01-25  1:29 ` [PATCH v2 10/40] bsd-user/signal.c: Implement cpu_loop_exit_sigsegv Warner Losh
2022-01-25  1:29 ` [PATCH v2 11/40] bsd-user/signal.c: implement cpu_loop_exit_sigbus Warner Losh
2022-01-25  1:29 ` [PATCH v2 12/40] bsd-user/arm/arget_arch_cpu.h: Move EXCP_DEBUG and EXCP_BKPT together Warner Losh
2022-01-25  1:29 ` [PATCH v2 13/40] bsd-user/arm/target_arch_cpu.h: Correct code pointer Warner Losh
2022-01-25  1:29 ` [PATCH v2 14/40] bsd-user/arm/target_arch_cpu.h: Use force_sig_fault for EXCP_UDEF Warner Losh
2022-01-27  6:27   ` Richard Henderson
2022-01-27 15:40     ` Warner Losh
2022-01-25  1:29 ` [PATCH v2 15/40] bsd-user/arm/target_arch_cpu.h: Implement data faults Warner Losh
2022-01-25  1:29 ` [PATCH v2 16/40] bsd-user/signal.c: implement abstract target / host signal translation Warner Losh
2022-01-27  6:29   ` Richard Henderson
2022-01-25  1:29 ` [PATCH v2 17/40] bsd-user/signal.c: Implement signal_init() Warner Losh
2022-01-25  1:29 ` [PATCH v2 18/40] bsd-user/signal.c: Add si_type argument to queue_signal Warner Losh
2022-01-27  6:38   ` Richard Henderson
2022-01-25  1:29 ` [PATCH v2 19/40] bsd-user/host/arm/host-signal.h: Implement host_signal_* Warner Losh
2022-01-27  6:38   ` Richard Henderson
2022-01-25  1:29 ` [PATCH v2 20/40] bsd-user/host/i386/host-signal.h: " Warner Losh
2022-01-25  1:29 ` [PATCH v2 21/40] bsd-user/host/x86_64/host-signal.h: " Warner Losh
2022-01-25  1:29 ` [PATCH v2 22/40] bsd-user: Add host signals to the build Warner Losh
2022-01-25  1:29 ` [PATCH v2 23/40] bsd-user: Add trace events for bsd-user Warner Losh
2022-01-25  1:29 ` [PATCH v2 24/40] bsd-user/signal.c: host_to_target_siginfo_noswap Warner Losh
2022-01-27  7:40   ` Richard Henderson
2022-01-25  1:29 ` [PATCH v2 25/40] bsd-user/signal.c: Implement rewind_if_in_safe_syscall Warner Losh
2022-01-25  1:29 ` [PATCH v2 26/40] bsd-user/signal.c: Implement host_signal_handler Warner Losh
2022-01-27  7:42   ` Richard Henderson
2022-01-25  1:29 ` [PATCH v2 27/40] bsd-user/strace.c: print_taken_signal Warner Losh
2022-01-25  1:29 ` [PATCH v2 28/40] bsd-user/signal.c: Implement dump_core_and_abort Warner Losh
2022-01-25  1:29 ` [PATCH v2 29/40] bsd-user/signal.c: Fill in queue_signal Warner Losh
2022-01-27  7:44   ` Richard Henderson
2022-01-27 15:34     ` Warner Losh
2022-01-25  1:29 ` [PATCH v2 30/40] bsd-user/signal.c: sigset manipulation routines Warner Losh
2022-01-27  7:45   ` Richard Henderson
2022-01-25  1:29 ` [PATCH v2 31/40] bsd-user/signal.c: setup_frame Warner Losh
2022-01-27  7:47   ` Richard Henderson
2022-01-27 15:30     ` Warner Losh
2022-01-25  1:29 ` [PATCH v2 32/40] bsd-user/signal.c: handle_pending_signal Warner Losh
2022-01-27  7:51   ` Richard Henderson
2022-01-25  1:29 ` [PATCH v2 33/40] bsd-user/signal.c: tswap_siginfo Warner Losh
2022-01-27  7:52   ` Richard Henderson
2022-01-25  1:29 ` [PATCH v2 34/40] bsd-user/signal.c: process_pending_signals Warner Losh
2022-01-27  7:54   ` Richard Henderson
2022-01-25  1:29 ` [PATCH v2 35/40] bsd-user/signal.c: implement do_sigreturn Warner Losh
2022-01-27 23:05   ` Warner Losh
2022-01-25  1:29 ` Warner Losh [this message]
2022-01-27 22:46   ` [PATCH v2 36/40] bsd-user/signal.c: implement do_sigaction Warner Losh
2022-01-28 10:37     ` Peter Maydell
2022-01-25  1:29 ` [PATCH v2 37/40] bsd-user/signal.c: do_sigaltstack Warner Losh
2022-01-27  8:00   ` Richard Henderson
2022-01-25  1:29 ` [PATCH v2 38/40] MAINTAINERS: Add tests/vm/*bsd to the list to get reviews on Warner Losh
2022-01-27  8:00   ` Richard Henderson
2022-01-25  1:29 ` [PATCH v2 39/40] bsd-user: Rename arg name for target_cpu_reset to env Warner Losh
2022-01-27  8:00   ` Richard Henderson
2022-01-25  1:29 ` [PATCH v2 40/40] bsd-user/freebsd/target_os_ucontext.h: Prefer env as arg name for CPUArchState args Warner Losh
2022-01-27  8:00   ` Richard Henderson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220125012947.14974-37-imp@bsdimp.com \
    --to=imp@bsdimp.com \
    --cc=def@FreeBSD.org \
    --cc=jrtc27@FreeBSD.org \
    --cc=kevans@freebsd.org \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=richard.henderson@linaro.org \
    --cc=sson@FreeBSD.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).