All of lore.kernel.org
 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 v3 36/40] bsd-user/signal.c: implement do_sigaction
Date: Fri, 28 Jan 2022 16:28:01 -0700	[thread overview]
Message-ID: <20220128232805.86191-37-imp@bsdimp.com> (raw)
In-Reply-To: <20220128232805.86191-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>
---
 bsd-user/signal-common.h | 22 +++++++++++
 bsd-user/signal.c        | 83 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 105 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 79e1128d4f6..24074d629e2 100644
--- a/bsd-user/signal.c
+++ b/bsd-user/signal.c
@@ -309,6 +309,25 @@ 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(). We depend on the FreeBSD behaivor here where
+     * this will only affect this thread's signal mask. We don't use
+     * pthread_sigmask which might seem more correct because that routine also
+     * does odd things with SIGCANCEL to implement pthread_cancel().
+     */
+    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 +573,70 @@ 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) {
+        return -TARGET_EINVAL;
+    }
+
+    if ((sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP) &&
+        act != NULL && act->_sa_handler != TARGET_SIG_DFL) {
+        return -TARGET_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-29  0:13 UTC|newest]

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

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=20220128232805.86191-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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.