Fix multi-threaded go runtime crash

-----BEGIN PGP SIGNATURE-----
 
 iQJGBAABCAAwFiEEzS913cjjpNwuT1Fz8ww4vT8vvjwFAl07OYgSHGxhdXJlbnRA
 dml2aWVyLmV1AAoJEPMMOL0/L748pj0P/R7v5AhooXuIMfbOfXR1pn2c3P7lxyEV
 uPZD+Q+VRHqATQoSOdFlX8Ky4B4vC8VMl/1ruABhwNOJtTbRdpdQtw4mG05qSyt6
 MZLq2diNgYRlc91Mt8gPrNc4jW7keeOONWXDCUXcJG22uLaoV+h4AHXiu/Y29whu
 3ESkr9fgcg4JgPggN8+IpBdfsEjiKZTvmKi4d0/61J9Umbv8MMeHpC1g84P6K17L
 xEjw7JlEnl65SwfAx96iEQuBonCzMexItlVcl6k+QBuJLXcss3m9P8tq6FGQMqN0
 cDgcTq3oEykaiY6ZLIQSwah73ldFmwmQcZSicAdDxlPqQQeDm31Vj4RFL6lydZDa
 rkR2DXqeBSrimput6/amQJI2NBFRq0b/zle1MOZG4ygHiXmoxrIcsFYM2O0UJhw/
 s3AmmLV7J9cMLDv4TUh5AH/JQhJjRSK28KgZSkEvbV+S9a5MaLCp9B8gF02KAoJE
 M6MFUKk69MG3m/5WuxnIhDxSMpWkAUTBwQP65slrXy3rXvr2ryQ3DbP1IzH/kfDO
 kNvoryfDvaPeqQx8xt8kdKWc3b8Qd9TVNSO+ZBtPaDpfVHmyOXDkkm2fkFEwSj+0
 jbW8RtSTgyZrxWpK6bsPFoIYR/XImWQjBvPhYH0UV+SNCp5sDUabhBvPai2ZyjRt
 TsvKvvBthZPi
 =KSrK
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-4.1-pull-request' into staging

Fix multi-threaded go runtime crash

# gpg: Signature made Fri 26 Jul 2019 18:34:00 BST
# gpg:                using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C
# gpg:                issuer "laurent@vivier.eu"
# gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [full]
# gpg:                 aka "Laurent Vivier <laurent@vivier.eu>" [full]
# gpg:                 aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [full]
# Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F  5173 F30C 38BD 3F2F BE3C

* remotes/vivier2/tags/linux-user-for-4.1-pull-request:
  linux-user: Make sigaltstack stacks per-thread

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2019-07-26 18:36:04 +01:00
commit 0c6f3e948c
5 changed files with 28 additions and 18 deletions

View File

@ -111,10 +111,11 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
abi_ulong frame_addr, sp, haddr; abi_ulong frame_addr, sp, haddr;
struct target_rt_sigframe *frame; struct target_rt_sigframe *frame;
int i; int i;
TaskState *ts = (TaskState *)thread_cpu->opaque;
sp = get_sp_from_cpustate(env); sp = get_sp_from_cpustate(env);
if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) { if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
sp = (target_sigaltstack_used.ss_sp + 0x7f) & ~0x3f; sp = (ts->sigaltstack_used.ss_sp + 0x7f) & ~0x3f;
} }
frame_addr = QEMU_ALIGN_UP(sp, 64); frame_addr = QEMU_ALIGN_UP(sp, 64);
sp = frame_addr + PARISC_RT_SIGFRAME_SIZE32; sp = frame_addr + PARISC_RT_SIGFRAME_SIZE32;

View File

@ -180,6 +180,11 @@ void stop_all_tasks(void)
void init_task_state(TaskState *ts) void init_task_state(TaskState *ts)
{ {
ts->used = 1; ts->used = 1;
ts->sigaltstack_used = (struct target_sigaltstack) {
.ss_sp = 0,
.ss_size = 0,
.ss_flags = TARGET_SS_DISABLE,
};
} }
CPUArchState *cpu_copy(CPUArchState *env) CPUArchState *cpu_copy(CPUArchState *env)

View File

@ -151,6 +151,8 @@ typedef struct TaskState {
*/ */
int signal_pending; int signal_pending;
/* This thread's sigaltstack, if it has one */
struct target_sigaltstack sigaltstack_used;
} __attribute__((aligned(16))) TaskState; } __attribute__((aligned(16))) TaskState;
extern char *exec_path; extern char *exec_path;

View File

@ -19,7 +19,6 @@
#ifndef SIGNAL_COMMON_H #ifndef SIGNAL_COMMON_H
#define SIGNAL_COMMON_H #define SIGNAL_COMMON_H
extern struct target_sigaltstack target_sigaltstack_used;
int on_sig_stack(unsigned long sp); int on_sig_stack(unsigned long sp);
int sas_ss_flags(unsigned long sp); int sas_ss_flags(unsigned long sp);

View File

@ -25,12 +25,6 @@
#include "trace.h" #include "trace.h"
#include "signal-common.h" #include "signal-common.h"
struct target_sigaltstack target_sigaltstack_used = {
.ss_sp = 0,
.ss_size = 0,
.ss_flags = TARGET_SS_DISABLE,
};
static struct target_sigaction sigact_table[TARGET_NSIG]; static struct target_sigaction sigact_table[TARGET_NSIG];
static void host_signal_handler(int host_signum, siginfo_t *info, static void host_signal_handler(int host_signum, siginfo_t *info,
@ -251,13 +245,17 @@ void set_sigmask(const sigset_t *set)
int on_sig_stack(unsigned long sp) int on_sig_stack(unsigned long sp)
{ {
return (sp - target_sigaltstack_used.ss_sp TaskState *ts = (TaskState *)thread_cpu->opaque;
< target_sigaltstack_used.ss_size);
return (sp - ts->sigaltstack_used.ss_sp
< ts->sigaltstack_used.ss_size);
} }
int sas_ss_flags(unsigned long sp) int sas_ss_flags(unsigned long sp)
{ {
return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE TaskState *ts = (TaskState *)thread_cpu->opaque;
return (ts->sigaltstack_used.ss_size == 0 ? SS_DISABLE
: on_sig_stack(sp) ? SS_ONSTACK : 0); : on_sig_stack(sp) ? SS_ONSTACK : 0);
} }
@ -266,17 +264,21 @@ abi_ulong target_sigsp(abi_ulong sp, struct target_sigaction *ka)
/* /*
* This is the X/Open sanctioned signal stack switching. * This is the X/Open sanctioned signal stack switching.
*/ */
TaskState *ts = (TaskState *)thread_cpu->opaque;
if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) { if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
return target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; return ts->sigaltstack_used.ss_sp + ts->sigaltstack_used.ss_size;
} }
return sp; return sp;
} }
void target_save_altstack(target_stack_t *uss, CPUArchState *env) void target_save_altstack(target_stack_t *uss, CPUArchState *env)
{ {
__put_user(target_sigaltstack_used.ss_sp, &uss->ss_sp); TaskState *ts = (TaskState *)thread_cpu->opaque;
__put_user(ts->sigaltstack_used.ss_sp, &uss->ss_sp);
__put_user(sas_ss_flags(get_sp_from_cpustate(env)), &uss->ss_flags); __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &uss->ss_flags);
__put_user(target_sigaltstack_used.ss_size, &uss->ss_size); __put_user(ts->sigaltstack_used.ss_size, &uss->ss_size);
} }
/* siginfo conversion */ /* siginfo conversion */
@ -708,12 +710,13 @@ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
{ {
int ret; int ret;
struct target_sigaltstack oss; struct target_sigaltstack oss;
TaskState *ts = (TaskState *)thread_cpu->opaque;
/* XXX: test errors */ /* XXX: test errors */
if(uoss_addr) if(uoss_addr)
{ {
__put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp); __put_user(ts->sigaltstack_used.ss_sp, &oss.ss_sp);
__put_user(target_sigaltstack_used.ss_size, &oss.ss_size); __put_user(ts->sigaltstack_used.ss_size, &oss.ss_size);
__put_user(sas_ss_flags(sp), &oss.ss_flags); __put_user(sas_ss_flags(sp), &oss.ss_flags);
} }
@ -760,8 +763,8 @@ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
} }
} }
target_sigaltstack_used.ss_sp = ss.ss_sp; ts->sigaltstack_used.ss_sp = ss.ss_sp;
target_sigaltstack_used.ss_size = ss.ss_size; ts->sigaltstack_used.ss_size = ss.ss_size;
} }
if (uoss_addr) { if (uoss_addr) {