From nobody Fri May 17 12:14:37 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1564060626; cv=none; d=zoho.com; s=zohoarc; b=Il7StB0xNIfFd0hlye4baBvQn89iZgYCLjkLMsXUfQTkjV5a83aaNy1oRzTDeeCm9AKuhHnsOPFwfc6eJgXRCkvZEKmUegKI/WJQxdZBzNaEGsN6BCQEx7kzrnPyw/l8FOUxgDlEsKO9mM/IljBogowH04azrbER8xhg/vuM7aU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1564060626; h=Content-Transfer-Encoding:Cc:Date:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:To:ARC-Authentication-Results; bh=awbVXWJ0H/ID3VyhdnpYTxFXtlPEQgwVdKk0JkyiGr0=; b=B3orDm/C+m7hTXhDQ2x0EXx3/N1ADZRGXhRwXDp+CdQQyrjYUPsqpTA8Q+nwulsDRbeS0Wvph7C5cLa448OUwh53JVKCJLjHK0SFSL93ApZXKSSpHRjfjVG4GU8xUSIGJYFabZeoIdvVm6SBqBDEm+D943KOKZU1NJC4oKtBwQE= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1564060626136902.4091629795537; Thu, 25 Jul 2019 06:17:06 -0700 (PDT) Received: from localhost ([::1]:60138 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hqdcG-0006Cw-Q9 for importer@patchew.org; Thu, 25 Jul 2019 09:17:04 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:46257) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hqdc3-0005oI-Q3 for qemu-devel@nongnu.org; Thu, 25 Jul 2019 09:16:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hqdc2-0000m8-8G for qemu-devel@nongnu.org; Thu, 25 Jul 2019 09:16:51 -0400 Received: from mail-wm1-x343.google.com ([2a00:1450:4864:20::343]:39854) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hqdc2-0000lw-0w for qemu-devel@nongnu.org; Thu, 25 Jul 2019 09:16:50 -0400 Received: by mail-wm1-x343.google.com with SMTP id u25so34362139wmc.4 for ; Thu, 25 Jul 2019 06:16:49 -0700 (PDT) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [81.2.115.148]) by smtp.gmail.com with ESMTPSA id x185sm38771751wmg.46.2019.07.25.06.16.47 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Thu, 25 Jul 2019 06:16:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=awbVXWJ0H/ID3VyhdnpYTxFXtlPEQgwVdKk0JkyiGr0=; b=jOoZUSkMmj/j/ogJ+DXzuExrj5flQkoMEBUUMI/CUrVc/GUPlgv/xUxNnnwLJcntKa b3D0UrRetimHCtlB8G5EYJbgESo2lE2Q1O9XdeIT0d+8AL7PXcTHNcRtxoLmnjb/0AoY COmuDDWv8D88hJ6KqtvsDTcGlfemxzykO1Cetj+lsgxbeKv9iksZbEusgNlDnoDY2G8Y WrtF8PW9NReTBdbiWIdkbvBaeJky2Km51YC4KkbP2wrBHTAIEn2QmrO4Awyh+aeEeug7 hFss4GkCrT27aQrsE6GlO8Oh9STM5Z/cD4oOd2aCRr155q+X2PY5rUs29UIElrpLpv/U V4iA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=awbVXWJ0H/ID3VyhdnpYTxFXtlPEQgwVdKk0JkyiGr0=; b=PWjRzJjvz9TN+Rm/N8a7l79NgXvr6FjF3vjbJIDsaBtdtAkt5SZ7QSQPOXGRz7Bm6q O7ewYP5Oq+0ZIVt9SXnO/cUoDjUi1FVpvdDCMtSE67SbR8t0l0kB66Gsm3edEIPimMD0 GqX29M908PRqPN9vLTJLS/+JnkHsoLly5OKTMM+7FOqB+hsUWu3wDhHY1Gk1uNUgyNfq AXb26lwpd5+xOF1SayduAOcaB8FyphkjpoXp6HITtG6cDplUI96npnxG1SS8KNLcEFxr UOMoRCCJcECrVIQegaDXms5BhiYVIw99YclRmLSL/RorE3kC/dUCrsmeywagBkBNjLtt Milg== X-Gm-Message-State: APjAAAWg5+XBo8q1Tp82/Q/CvOX45ojGzpPmgoBaQGBRb9QjiYPux7T/ hzz1qoLml8tNJzdmjjoGrvyGx+DPrtHctg== X-Google-Smtp-Source: APXvYqxxMId0LL7ZwUHEf25SkHDjH9pwlWEmWCExQfn6ZZ66hbpZrnbkLcunjYx71yn8EtLjG0R46w== X-Received: by 2002:a1c:ab06:: with SMTP id u6mr78455815wme.125.1564060608558; Thu, 25 Jul 2019 06:16:48 -0700 (PDT) From: Peter Maydell To: qemu-devel@nongnu.org Date: Thu, 25 Jul 2019 14:16:45 +0100 Message-Id: <20190725131645.19501-1-peter.maydell@linaro.org> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::343 Subject: [Qemu-devel] [PATCH for-4.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: Riku Voipio , Laurent Vivier , patches@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" 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: Laurent Vivier Reviewed-by: Richard Henderson Tested-by: Laurent Vivier --- I've marked this as "for-4.1" but it is quite late in the release cycle and I think this could use more testing than I have given it... Thanks are due to: * the original bug reporter, for providing a nice simple test case * rr, for allowing me to capture and forensically examine a single example of the failure * the Go project for having a good clear HACKING.md that explained their stack usage and mentioned specifically that signal stacks are per-thread (per-M, in their terms) * a colleague, for prodding me into actually spending the necessary two days grovelling through gdb sessions and logs to figure out what was actually going wrong --- linux-user/qemu.h | 2 ++ linux-user/signal-common.h | 1 - linux-user/hppa/signal.c | 3 ++- linux-user/main.c | 5 +++++ linux-user/signal.c | 35 +++++++++++++++++++---------------- 5 files changed, 28 insertions(+), 18 deletions(-) diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 4258e4162d2..aac03346270 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -151,6 +151,8 @@ typedef struct TaskState { */ int signal_pending; =20 + /* This thread's sigaltstack, if it has one */ + struct target_sigaltstack sigaltstack_used; } __attribute__((aligned(16))) TaskState; =20 extern char *exec_path; diff --git a/linux-user/signal-common.h b/linux-user/signal-common.h index 51030a93069..1df1068552f 100644 --- a/linux-user/signal-common.h +++ b/linux-user/signal-common.h @@ -19,7 +19,6 @@ =20 #ifndef SIGNAL_COMMON_H #define SIGNAL_COMMON_H -extern struct target_sigaltstack target_sigaltstack_used; =20 int on_sig_stack(unsigned long sp); int sas_ss_flags(unsigned long sp); diff --git a/linux-user/hppa/signal.c b/linux-user/hppa/signal.c index b6927ee6735..d1a58feeb36 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 =3D (TaskState *)thread_cpu->opaque; =20 sp =3D get_sp_from_cpustate(env); if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) { - sp =3D (target_sigaltstack_used.ss_sp + 0x7f) & ~0x3f; + sp =3D (ts->sigaltstack_used.ss_sp + 0x7f) & ~0x3f; } frame_addr =3D QEMU_ALIGN_UP(sp, 64); sp =3D frame_addr + PARISC_RT_SIGFRAME_SIZE32; diff --git a/linux-user/main.c b/linux-user/main.c index a59ae9439de..8ffc5251955 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 =3D 1; + ts->sigaltstack_used =3D (struct target_sigaltstack) { + .ss_sp =3D 0, + .ss_size =3D 0, + .ss_flags =3D TARGET_SS_DISABLE, + }; } =20 CPUArchState *cpu_copy(CPUArchState *env) diff --git a/linux-user/signal.c b/linux-user/signal.c index 5cd237834d9..5ca6d62b15d 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -25,12 +25,6 @@ #include "trace.h" #include "signal-common.h" =20 -struct target_sigaltstack target_sigaltstack_used =3D { - .ss_sp =3D 0, - .ss_size =3D 0, - .ss_flags =3D TARGET_SS_DISABLE, -}; - static struct target_sigaction sigact_table[TARGET_NSIG]; =20 static void host_signal_handler(int host_signum, siginfo_t *info, @@ -251,13 +245,17 @@ void set_sigmask(const sigset_t *set) =20 int on_sig_stack(unsigned long sp) { - return (sp - target_sigaltstack_used.ss_sp - < target_sigaltstack_used.ss_size); + TaskState *ts =3D (TaskState *)thread_cpu->opaque; + + return (sp - ts->sigaltstack_used.ss_sp + < ts->sigaltstack_used.ss_size); } =20 int sas_ss_flags(unsigned long sp) { - return (target_sigaltstack_used.ss_size =3D=3D 0 ? SS_DISABLE + TaskState *ts =3D (TaskState *)thread_cpu->opaque; + + return (ts->sigaltstack_used.ss_size =3D=3D 0 ? SS_DISABLE : on_sig_stack(sp) ? SS_ONSTACK : 0); } =20 @@ -266,17 +264,21 @@ abi_ulong target_sigsp(abi_ulong sp, struct target_si= gaction *ka) /* * This is the X/Open sanctioned signal stack switching. */ + TaskState *ts =3D (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; } =20 void target_save_altstack(target_stack_t *uss, CPUArchState *env) { - __put_user(target_sigaltstack_used.ss_sp, &uss->ss_sp); + TaskState *ts =3D (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); } =20 /* 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 =3D (TaskState *)thread_cpu->opaque; =20 /* 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); } =20 @@ -760,8 +763,8 @@ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong u= oss_addr, abi_ulong sp) } } =20 - target_sigaltstack_used.ss_sp =3D ss.ss_sp; - target_sigaltstack_used.ss_size =3D ss.ss_size; + ts->sigaltstack_used.ss_sp =3D ss.ss_sp; + ts->sigaltstack_used.ss_size =3D ss.ss_size; } =20 if (uoss_addr) { --=20 2.20.1