From patchwork Fri Jul 26 17:35:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 169863 Delivered-To: patch@linaro.org Received: by 2002:a92:4782:0:0:0:0:0 with SMTP id e2csp339097ilk; Fri, 26 Jul 2019 10:35:44 -0700 (PDT) X-Google-Smtp-Source: APXvYqwm+t8BSlUu6C585L9+6O/6Z5jZt1+sxEToPzbtQaq3kIsUGm0wT0ehOGyHCl7FqCmh/R6t X-Received: by 2002:a50:b3d0:: with SMTP id t16mr83570072edd.158.1564162543952; Fri, 26 Jul 2019 10:35:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1564162543; cv=none; d=google.com; s=arc-20160816; b=RC0fuEsoGFcksNvtyREifIH3Gzq50TR/PqbDeSA9gxoAZHVr0mrk4essSnJlo4BcgG 5DKd9PWqvf+Xaws4I2wrHGbdEOLlhjl3yBHAgRr53yQqL2WVNea3krj8pJNyYf9hpXHo gf+N0C4a1hH/a5CV5kS90YvVyDtCxRBWKs/DH9iFuhtDDwUEdnoTkMqUgF1HFWpsC15g UcWNf8WAo2SOI8MDNsnqClfwAAgI6qXvSqd8CrMh2KZ6mAzl7q3aQDWO+ciI9MAvzmfm E/9gjzWBf5AWtxPZIpMVn48fi8ATLBbdtKfij54DjwFs5mC8NmxCCqC3UdSb8/hpJScV mB7w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from; bh=8lGI78wrSpR0BdVgQvqoOy6RTiTkbA7bZuEK/7GYu8o=; b=wQX0vma8I65WWHSLnRe6mpeomrB9q2gtWAoVGSl2B0b/BnAdx449FLtCZMBvbjh9Rl 4lTEDKTRmkuXFrsuaW9+hDTTtMUKYBhDTugCUF19+HMgqOgsP8tujInGTE4eirS6BYf3 lb/T1/TGwa3mDt+FAiQe42kO41S2dHFm8eVSMg5eXRlx5wKKqbkPAxlOToXpJsYwGoGV WmSTy8+XO85VwJkezY4m3XsHhvR7NOQlibi7Zye9SQKuwDiybAeSKkVEyAWXaBbDc5kr Jmq0SZBDtFXBdHoK+c/m52/4bb311woY3eAgh3DHUKYpNR9P0XOTh0WvqJSlAUdEDhCf WUOQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org" Return-Path: Received: from lists.gnu.org (lists.gnu.org. [209.51.188.17]) by mx.google.com with ESMTPS id g39si14282517edc.434.2019.07.26.10.35.43 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Fri, 26 Jul 2019 10:35:43 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; Authentication-Results: mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org" Received: from localhost ([::1]:42088 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hr485-0003iP-Lf for patch@linaro.org; Fri, 26 Jul 2019 13:35:41 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39436) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hr47s-0003gX-Md for qemu-devel@nongnu.org; Fri, 26 Jul 2019 13:35:30 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hr47p-0004vh-6r for qemu-devel@nongnu.org; Fri, 26 Jul 2019 13:35:27 -0400 Received: from mout.kundenserver.de ([212.227.17.10]:39575) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hr47o-0004my-Sg for qemu-devel@nongnu.org; Fri, 26 Jul 2019 13:35:25 -0400 Received: from localhost.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue108 [212.227.15.183]) with ESMTPSA (Nemesis) id 1N9doJ-1iVe3Y0kDN-015dlg; Fri, 26 Jul 2019 19:35:13 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Date: Fri, 26 Jul 2019 19:35:02 +0200 Message-Id: <20190726173502.17172-2-laurent@vivier.eu> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190726173502.17172-1-laurent@vivier.eu> References: <20190726173502.17172-1-laurent@vivier.eu> MIME-Version: 1.0 X-Provags-ID: V03:K1:eep8em1eVwiv8vqquoYX3hUhv8xPmW/bPAbGohSCE1ZTfu7ldte F9f/+Yml0At7Ng1+9FgBY7shyZ/FRHoIObPT3WQIE3SynAqkioi7eqT6kfhftrZCum1f2f+ ONhsCyzmhYyY8+D/wJ5P/tLWzul8y2IDttTzE9DUXIQEomvfKkT72b8z/mKMVqoYd5rcjpl d69p+XFoburvgq4KRrlBw== X-UI-Out-Filterresults: notjunk:1; V03:K0:QUq0/WEXMBE=:dQUq82Atq5ByJjhBSS9D3m gcHe9ohx/DJeVqTIv++1RfuXveAxLgUv86tLkFJp41H6a6RGd6zObK+eJozCcG7crSkc+mNf4 puXVkalcNWIg6+93VY8IsSxRAPdZJX1fS+e2fFvOJf0Ct+U0+HQ+W+ozbF45l8Y6zU8mgGyoq ke2UUj888Tz0oPh68hkH5xVO5HKzc2C8jP5wkczH7yUkxq5qwvfgpQT+iMHXxanCl+0yP36nq giEFLt47+ViCTr2ESUNwjykfUZ3S/8IpW6B01c/E5MeqpP7hPMt2Oc3yiFgSiGKtcmZj3HAbk 2EEmpq0Mz5/CPMp74JPrZPFD1S6hmuPsvI+tYacy6uluZFhfFXIjv/jRPBIlLCy1y9e7Uy9IN gMa8S1ZZD+Bn0jKxE2Fe3uM4DYiwWaljAVrUj3xrno8jwd+XtuCOzsxsYIFWRRiPKwcSjLcSC vVQDTsHOjCJJLiBZ6E4fP+yz8hwonP8PcxDjKz9OQhbgblBXVKO+ojJgfe3/JlwHtcc90Sod5 dyel77kxbzVrrByoRaKIgRxRf7p1UnYMXbGNb+Ch1NhRX29pwWf6kyArm5z7uHgEsOUcsmlen 1sb76+KQXE0AxTLaGAQThf+87eYg13tEPGws1FDMhZOZR+SNgR8ibZXilMlwtB5xGsJ1/+Ux8 mhkLON/7tFWOMnGFDFLiSLFX+nFgvmfyrB2PnsE4/74zQOs0GxPDrkzGg7p50P5xK6FJSbFNK IJcBdqrGYNPI2cKkumiNpR8gObykTutYiUeozw== X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 212.227.17.10 Subject: [Qemu-devel] [PULL 1/1] linux-user: Make sigaltstack stacks per-thread X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Peter Maydell , Riku Voipio , Richard Henderson , Laurent Vivier Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: Peter Maydell The alternate signal stack set up by the sigaltstack syscall is supposed to be per-thread. We were incorrectly implementing it as process-wide. This causes problems for guest binaries that rely on this. Notably the Go runtime does, and so we were seeing crashes caused by races where two guest threads might incorrectly both execute on the same stack simultaneously. Replace the global target_sigaltstack_used with a field sigaltstack_used in the TaskState, and make all the references to the old global instead get a pointer to the TaskState and use the field. Fixes: https://bugs.launchpad.net/qemu/+bug/1696773 Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Tested-by: Laurent Vivier Reviewed-by: Laurent Vivier Message-Id: <20190725131645.19501-1-peter.maydell@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/hppa/signal.c | 3 ++- linux-user/main.c | 5 +++++ linux-user/qemu.h | 2 ++ linux-user/signal-common.h | 1 - linux-user/signal.c | 35 +++++++++++++++++++---------------- 5 files changed, 28 insertions(+), 18 deletions(-) -- 2.21.0 diff --git a/linux-user/hppa/signal.c b/linux-user/hppa/signal.c index b6927ee67351..d1a58feeb36f 100644 --- a/linux-user/hppa/signal.c +++ b/linux-user/hppa/signal.c @@ -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; diff --git a/linux-user/main.c b/linux-user/main.c index a59ae9439de1..8ffc52519552 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -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) diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 4258e4162d26..aac033462700 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -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; diff --git a/linux-user/signal-common.h b/linux-user/signal-common.h index 51030a93069a..1df1068552fb 100644 --- a/linux-user/signal-common.h +++ b/linux-user/signal-common.h @@ -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); diff --git a/linux-user/signal.c b/linux-user/signal.c index 5cd237834d9a..5ca6d62b15d3 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -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) {