Commit 0c6f3e94 authored by Peter Maydell's avatar Peter Maydell
Browse files

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: default avatarPeter Maydell <peter.maydell@linaro.org>
parents fff31599 5bfce0b7
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -111,10 +111,11 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
    abi_ulong frame_addr, sp, haddr;
    struct target_rt_sigframe *frame;
    int i;
    TaskState *ts = (TaskState *)thread_cpu->opaque;

    sp = get_sp_from_cpustate(env);
    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);
    sp = frame_addr + PARISC_RT_SIGFRAME_SIZE32;
+5 −0
Original line number Diff line number Diff line
@@ -180,6 +180,11 @@ void stop_all_tasks(void)
void init_task_state(TaskState *ts)
{
    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)
+2 −0
Original line number Diff line number Diff line
@@ -151,6 +151,8 @@ typedef struct TaskState {
     */
    int signal_pending;

    /* This thread's sigaltstack, if it has one */
    struct target_sigaltstack sigaltstack_used;
} __attribute__((aligned(16))) TaskState;

extern char *exec_path;
+0 −1
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@

#ifndef SIGNAL_COMMON_H
#define SIGNAL_COMMON_H
extern struct target_sigaltstack target_sigaltstack_used;

int on_sig_stack(unsigned long sp);
int sas_ss_flags(unsigned long sp);
+19 −16
Original line number Diff line number Diff line
@@ -25,12 +25,6 @@
#include "trace.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 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)
{
    return (sp - target_sigaltstack_used.ss_sp
            < target_sigaltstack_used.ss_size);
    TaskState *ts = (TaskState *)thread_cpu->opaque;

    return (sp - ts->sigaltstack_used.ss_sp
            < ts->sigaltstack_used.ss_size);
}

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);
}

@@ -266,17 +264,21 @@ abi_ulong target_sigsp(abi_ulong sp, struct target_sigaction *ka)
    /*
     * 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)) {
        return target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
        return ts->sigaltstack_used.ss_sp + ts->sigaltstack_used.ss_size;
    }
    return sp;
}

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(target_sigaltstack_used.ss_size, &uss->ss_size);
    __put_user(ts->sigaltstack_used.ss_size, &uss->ss_size);
}

/* siginfo conversion */
@@ -708,12 +710,13 @@ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
{
    int ret;
    struct target_sigaltstack oss;
    TaskState *ts = (TaskState *)thread_cpu->opaque;

    /* XXX: test errors */
    if(uoss_addr)
    {
        __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
        __put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
        __put_user(ts->sigaltstack_used.ss_sp, &oss.ss_sp);
        __put_user(ts->sigaltstack_used.ss_size, &oss.ss_size);
        __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;
        target_sigaltstack_used.ss_size = ss.ss_size;
        ts->sigaltstack_used.ss_sp = ss.ss_sp;
        ts->sigaltstack_used.ss_size = ss.ss_size;
    }

    if (uoss_addr) {