[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 19/26] linux-user: SIGSEGV on signal entry need not b
From: |
riku . voipio |
Subject: |
[Qemu-devel] [PULL 19/26] linux-user: SIGSEGV on signal entry need not be fatal |
Date: |
Thu, 22 Sep 2016 15:13:39 +0300 |
From: Peter Maydell <address@hidden>
A failed write to memory trying to set up the signal frame
should trigger a SIGSEGV, but this need not be fatal: the
guest has a chance to catch it. Implement this via a force_sigsegv()
function with the same behaviour as the kernel function of that
name: make sure that we don't try to re-take a failed SIGSEGV,
and force a synchronous signal.
Reviewed-by: Richard Henderson <address@hidden>
Signed-off-by: Peter Maydell <address@hidden>
Signed-off-by: Riku Voipio <address@hidden>
---
linux-user/signal.c | 87 ++++++++++++++++++++++++++++++-----------------------
1 file changed, 49 insertions(+), 38 deletions(-)
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 93a9293..892b527 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -512,6 +512,33 @@ void signal_init(void)
}
}
+#if !((defined(TARGET_ARM) && !defined(TARGET_AARCH64)) || \
+ defined(TARGET_X86_64) || defined(TARGET_UNICORE32))
+
+/* Force a SIGSEGV if we couldn't write to memory trying to set
+ * up the signal frame. oldsig is the signal we were trying to handle
+ * at the point of failure.
+ */
+static void force_sigsegv(int oldsig)
+{
+ CPUState *cpu = thread_cpu;
+ CPUArchState *env = cpu->env_ptr;
+ target_siginfo_t info;
+
+ if (oldsig == SIGSEGV) {
+ /* Make sure we don't try to deliver the signal again; this will
+ * end up with handle_pending_signal() calling force_sig().
+ */
+ sigact_table[oldsig - 1]._sa_handler = TARGET_SIG_DFL;
+ }
+ info.si_signo = TARGET_SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = TARGET_SI_KERNEL;
+ info._sifields._kill._pid = 0;
+ info._sifields._kill._uid = 0;
+ queue_signal(env, info.si_signo, QEMU_SI_KILL, &info);
+}
+#endif
/* abort execution with signal */
static void QEMU_NORETURN force_sig(int target_sig)
@@ -1011,10 +1038,7 @@ static void setup_frame(int sig, struct target_sigaction
*ka,
return;
give_sigsegv:
- if (sig == TARGET_SIGSEGV) {
- ka->_sa_handler = TARGET_SIG_DFL;
- }
- force_sig(TARGET_SIGSEGV /* , current */);
+ force_sigsegv(sig);
}
/* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */
@@ -1084,10 +1108,7 @@ static void setup_rt_frame(int sig, struct
target_sigaction *ka,
return;
give_sigsegv:
- if (sig == TARGET_SIGSEGV) {
- ka->_sa_handler = TARGET_SIG_DFL;
- }
- force_sig(TARGET_SIGSEGV /* , current */);
+ force_sigsegv(sig);
}
static int
@@ -1416,7 +1437,7 @@ static void target_setup_frame(int usig, struct
target_sigaction *ka,
give_sigsegv:
unlock_user_struct(frame, frame_addr, 1);
- force_sig(TARGET_SIGSEGV);
+ force_sigsegv(usig);
}
static void setup_rt_frame(int sig, struct target_sigaction *ka,
@@ -2441,7 +2462,7 @@ sigill_and_return:
#endif
sigsegv:
unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
- force_sig(TARGET_SIGSEGV);
+ force_sigsegv(sig);
}
static void setup_rt_frame(int sig, struct target_sigaction *ka,
@@ -3033,7 +3054,7 @@ static void setup_frame(int sig, struct target_sigaction
* ka,
return;
give_sigsegv:
- force_sig(TARGET_SIGSEGV/*, current*/);
+ force_sigsegv(sig);
}
long do_sigreturn(CPUMIPSState *regs)
@@ -3142,7 +3163,7 @@ static void setup_rt_frame(int sig, struct
target_sigaction *ka,
give_sigsegv:
unlock_user_struct(frame, frame_addr, 1);
- force_sig(TARGET_SIGSEGV/*, current*/);
+ force_sigsegv(sig);
}
long do_rt_sigreturn(CPUMIPSState *env)
@@ -3345,7 +3366,7 @@ static void setup_frame(int sig, struct target_sigaction
*ka,
give_sigsegv:
unlock_user_struct(frame, frame_addr, 1);
- force_sig(TARGET_SIGSEGV);
+ force_sigsegv(sig);
}
static void setup_rt_frame(int sig, struct target_sigaction *ka,
@@ -3405,7 +3426,7 @@ static void setup_rt_frame(int sig, struct
target_sigaction *ka,
give_sigsegv:
unlock_user_struct(frame, frame_addr, 1);
- force_sig(TARGET_SIGSEGV);
+ force_sigsegv(sig);
}
long do_sigreturn(CPUSH4State *regs)
@@ -3652,7 +3673,7 @@ static void setup_frame(int sig, struct target_sigaction
*ka,
unlock_user_struct(frame, frame_addr, 1);
return;
badframe:
- force_sig(TARGET_SIGSEGV);
+ force_sigsegv(sig);
}
static void setup_rt_frame(int sig, struct target_sigaction *ka,
@@ -3822,7 +3843,7 @@ static void setup_frame(int sig, struct target_sigaction
*ka,
unlock_user_struct(frame, frame_addr, 1);
return;
badframe:
- force_sig(TARGET_SIGSEGV);
+ force_sigsegv(sig);
}
static void setup_rt_frame(int sig, struct target_sigaction *ka,
@@ -4061,10 +4082,7 @@ static void setup_rt_frame(int sig, struct
target_sigaction *ka,
give_sigsegv:
unlock_user_struct(frame, frame_addr, 1);
- if (sig == TARGET_SIGSEGV) {
- ka->_sa_handler = TARGET_SIG_DFL;
- }
- force_sig(TARGET_SIGSEGV);
+ force_sigsegv(sig);
}
long do_sigreturn(CPUOpenRISCState *env)
@@ -4245,7 +4263,7 @@ static void setup_frame(int sig, struct target_sigaction
*ka,
return;
give_sigsegv:
- force_sig(TARGET_SIGSEGV);
+ force_sigsegv(sig);
}
static void setup_rt_frame(int sig, struct target_sigaction *ka,
@@ -4300,7 +4318,7 @@ static void setup_rt_frame(int sig, struct
target_sigaction *ka,
return;
give_sigsegv:
- force_sig(TARGET_SIGSEGV);
+ force_sigsegv(sig);
}
static int
@@ -4811,7 +4829,7 @@ static void setup_frame(int sig, struct target_sigaction
*ka,
sigsegv:
unlock_user_struct(frame, frame_addr, 1);
- force_sig(TARGET_SIGSEGV);
+ force_sigsegv(sig);
}
static void setup_rt_frame(int sig, struct target_sigaction *ka,
@@ -4906,7 +4924,7 @@ static void setup_rt_frame(int sig, struct
target_sigaction *ka,
sigsegv:
unlock_user_struct(rt_sf, rt_sf_addr, 1);
- force_sig(TARGET_SIGSEGV);
+ force_sigsegv(sig);
}
@@ -5155,7 +5173,7 @@ static void setup_frame(int sig, struct target_sigaction
*ka,
return;
give_sigsegv:
- force_sig(TARGET_SIGSEGV);
+ force_sigsegv(sig);
}
static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
@@ -5294,7 +5312,7 @@ static void setup_rt_frame(int sig, struct
target_sigaction *ka,
give_sigsegv:
unlock_user_struct(frame, frame_addr, 1);
- force_sig(TARGET_SIGSEGV);
+ force_sigsegv(sig);
}
long do_sigreturn(CPUM68KState *env)
@@ -5501,10 +5519,8 @@ static void setup_frame(int sig, struct target_sigaction
*ka,
if (err) {
give_sigsegv:
- if (sig == TARGET_SIGSEGV) {
- ka->_sa_handler = TARGET_SIG_DFL;
- }
- force_sig(TARGET_SIGSEGV);
+ force_sigsegv(sig);
+ return;
}
env->ir[IR_RA] = r26;
@@ -5558,10 +5574,8 @@ static void setup_rt_frame(int sig, struct
target_sigaction *ka,
if (err) {
give_sigsegv:
- if (sig == TARGET_SIGSEGV) {
- ka->_sa_handler = TARGET_SIG_DFL;
- }
- force_sig(TARGET_SIGSEGV);
+ force_sigsegv(sig);
+ return;
}
env->ir[IR_RA] = r26;
@@ -5758,10 +5772,7 @@ static void setup_rt_frame(int sig, struct
target_sigaction *ka,
return;
give_sigsegv:
- if (sig == TARGET_SIGSEGV) {
- ka->_sa_handler = TARGET_SIG_DFL;
- }
- force_sig(TARGET_SIGSEGV /* , current */);
+ force_sigsegv(sig);
}
long do_rt_sigreturn(CPUTLGState *env)
--
2.1.4
- [Qemu-devel] [PULL 11/26] linux-user: Fix incorrect use of host errno in do_ioctl_dm(), (continued)
- [Qemu-devel] [PULL 11/26] linux-user: Fix incorrect use of host errno in do_ioctl_dm(), riku . voipio, 2016/09/22
- [Qemu-devel] [PULL 10/26] linux-user: Check lock_user() return value for NULL, riku . voipio, 2016/09/22
- [Qemu-devel] [PULL 13/26] linux-user: Check dump_write() return in elf_core_dump(), riku . voipio, 2016/09/22
- [Qemu-devel] [PULL 15/26] linux-user: Use correct target SHMLBA in shmat(), riku . voipio, 2016/09/22
- [Qemu-devel] [PULL 14/26] linux-user: Use glib malloc functions in load_symbols(), riku . voipio, 2016/09/22
- [Qemu-devel] [PULL 12/26] linux-user: Fix error handling in flatload.c target_pread(), riku . voipio, 2016/09/22
- [Qemu-devel] [PULL 16/26] linux-user: ppc64: set MSR_CM bit for BookE 2.06 MMU, riku . voipio, 2016/09/22
- [Qemu-devel] [PULL 17/26] linux-user: Recheck for pending synchronous signals too, riku . voipio, 2016/09/22
- [Qemu-devel] [PULL 18/26] linux-user: Pass si_type information to queue_signal() explicitly, riku . voipio, 2016/09/22
- [Qemu-devel] [PULL 24/26] linux-user: Sanity check clone flags, riku . voipio, 2016/09/22
- [Qemu-devel] [PULL 19/26] linux-user: SIGSEGV on signal entry need not be fatal,
riku . voipio <=
- [Qemu-devel] [PULL 20/26] linux-user: ARM: Give SIGSEGV if signal frame setup fails, riku . voipio, 2016/09/22
- [Qemu-devel] [PULL 21/26] linux-user: SIGSEGV from sigreturn need not be fatal, riku . voipio, 2016/09/22
- [Qemu-devel] [PULL 22/26] linux-user: Implement force_sigsegv() via force_sig(), riku . voipio, 2016/09/22
- [Qemu-devel] [PULL 23/26] linux-user: Remove unnecessary nptl_flags variable from do_fork(), riku . voipio, 2016/09/22
- [Qemu-devel] [PULL 25/26] linux-user: Fix incorrect offset of tuc_stack in ARM do_sigframe_return_v2, riku . voipio, 2016/09/22
- [Qemu-devel] [PULL 26/26] linux-user: fix TARGET_NR_select, riku . voipio, 2016/09/22
- Re: [Qemu-devel] [PULL 00/26] linux-user update, no-reply, 2016/09/22
- Re: [Qemu-devel] [PULL 00/26] linux-user update, Peter Maydell, 2016/09/22