From patchwork Fri Dec 20 01:36:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Collingbourne X-Patchwork-Id: 11304641 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id EDEFD921 for ; Fri, 20 Dec 2019 01:37:30 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C66E52465E for ; Fri, 20 Dec 2019 01:37:30 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="KBjf0eTP"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=google.com header.i=@google.com header.b="J143fqLZ" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C66E52465E Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:To:From:Subject:References:Mime-Version :Message-Id:In-Reply-To:Date:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=aYDRNrYHvOnWW0uu6Lrlk9AZJUWEc+Bf95UNHW6JnyU=; b=KBjf0eTP0XKOhL ApZvouvXWBGkzgB2Z7QTx87CwWKXKt2BSwcSqF1oN0odkTRySik+PfGH0+T/IW4MXNB+Kg/rE5HSJ HExUl/OwOU6P/dnZez5JI7uVct7k97asLgZ2YRaBqBxVW8XBMvl0CZTcI7jCAKt1mrVrxp++Yb7c5 hnQz4rS4buS4QoT224D8CzgT9rqZ8WOKBtrLPIzdTvBX4GHJejwJxft0GmRubxDlulTOw+OIS2fBv /xWRLqFesU0A3Zii91f3gMFC2JbQ04InzKAL6GFBLJNZ7YCsmBmTMA23wvbzFXEZg7bD+bz8kLMGv NSlGmBDh6C3/m8Zw6Sbw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1ii7EO-0003Cq-JK; Fri, 20 Dec 2019 01:37:28 +0000 Received: from mail-pg1-x54a.google.com ([2607:f8b0:4864:20::54a]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1ii7EL-0003CH-CP for linux-arm-kernel@lists.infradead.org; Fri, 20 Dec 2019 01:37:27 +0000 Received: by mail-pg1-x54a.google.com with SMTP id x189so4266543pgd.9 for ; Thu, 19 Dec 2019 17:37:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc:content-transfer-encoding; bh=ZRY76nUi493+xuL7Tm0FlcOAyz0Ji1nFyA0Xlgk3AOY=; b=J143fqLZK4/lFzYrCfOIl3+2NbBbgVzLDSm4kEMxZktRis7lgreOCdxYJMeKPplkMr hSvPqstpn+bS83eJywSg4D1b1NnNaZKth1RGcbxQlbJXzymKqYCrpDhspOdmjZMZJAIa EVq6a8wp2BjjNPZhfifKOfE32LIe7ZDb7s537MMfK6RKt8WDX/8AlrlzRPwiyiVL+gdM o+H4bB45aiSA0r6k6yUMWDXVt6zN/mn+OF9zD5qopCyG4wLAKpciAbuN1IyLqfDzPqaR sK9p/dlPN2mXF3aCcHsGnVmUdCw2leQQMuwTxhXwL7/tkka64TwMlx9H42rQnN2jcNOi fntQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc:content-transfer-encoding; bh=ZRY76nUi493+xuL7Tm0FlcOAyz0Ji1nFyA0Xlgk3AOY=; b=GdQBJaJ82V3pu2lVn1c39J6VUst3hESuYBsrknaJ0KDZd3TQiKWEzhCZyMTwwI6yxE 3kXQwyeaBJvXxNmUdjHw2JFj94ri9lAsOJ3NjKv9mu5LAyTl3PWGa6032pAWPWWepeAv VbTzVhv6DnPwzce8X34vjF0o/7doVeTcT5KJnw1fdOseoVAxYH6qVNhfcRkUSSSCDZd0 a3ziAcAdBZj68r4VnwFDkdH45mh5TS4Ixcu4PYMNOmkdSrImFQmLwsv6TAxbIjb1pe2C Rl0EQC/7svTB76hK8dn/0iSBmPsmpc9SqCnVivDi3ici0cfILIAt7pGvlPx6Rb2lWzim ar+w== X-Gm-Message-State: APjAAAVcI/noEYku0dPDA/yCJj8UcnP6wkxZ3aEN+1yS31AkrUqNJ5B0 4X7yhyU7uZGjHWBWnb8qjE+DUIc= X-Google-Smtp-Source: APXvYqxaNmZqoXs4tYB6snO5BmWk18re5etHg7lWZji+j3yxRsEA601c51JheS86Ob+7tZu24lPAgpI= X-Received: by 2002:a63:f107:: with SMTP id f7mr12336875pgi.76.1576805843222; Thu, 19 Dec 2019 17:37:23 -0800 (PST) Date: Thu, 19 Dec 2019 17:36:39 -0800 In-Reply-To: <20191217180152.GO5624@arrakis.emea.arm.com> Message-Id: <20191220013639.212396-1-pcc@google.com> Mime-Version: 1.0 References: <20191217180152.GO5624@arrakis.emea.arm.com> X-Mailer: git-send-email 2.24.1.735.g03f4e72817-goog Subject: [PATCH] arm64: mte: Do not service syscalls after async tag fault From: Peter Collingbourne To: Catalin Marinas X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20191219_173725_448593_7DED5214 X-CRM114-Status: GOOD ( 26.28 ) X-Spam-Score: -7.7 (-------) X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary: Content analysis details: (-7.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -7.5 USER_IN_DEF_DKIM_WL From: address is in the default DKIM white-list -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:54a listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.0 DKIMWL_WL_MED DKIMwl.org - Medium sender X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-arch@vger.kernel.org, Richard Earnshaw , Will Deacon , linux-mm@kvack.org, Szabolcs Nagy , Marc Zyngier , Kevin Brodsky , Kostya Serebryany , Evgenii Stepanov , Andrey Konovalov , Vincenzo Frascino , Peter Collingbourne , Linux ARM Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org When entering the kernel after an async tag fault due to a syscall, rather than for another reason (e.g. preemption), we don't want to service the syscall as it may mask the tag fault. Rewind the PC to the svc instruction in order to give a userspace signal handler an opportunity to handle the fault and resume, and skip all other syscall processing. Signed-off-by: Peter Collingbourne Tested-by: Peter Collingbourne --- On Tue, Dec 17, 2019 at 10:01 AM Catalin Marinas wrote: > > On Fri, Dec 13, 2019 at 05:43:15PM -0800, Peter Collingbourne wrote: > > On Wed, Dec 11, 2019 at 10:44 AM Catalin Marinas > > wrote: > > > diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c > > > index dd2cdc0d5be2..41fae64af82a 100644 > > > --- a/arch/arm64/kernel/signal.c > > > +++ b/arch/arm64/kernel/signal.c > > > @@ -730,6 +730,9 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka, > > >         regs->regs[29] = (unsigned long)&user->next_frame->fp; > > >         regs->pc = (unsigned long)ka->sa.sa_handler; > > > > > > +       /* TCO (Tag Check Override) always cleared for signal handlers */ > > > +       regs->pstate &= ~PSR_TCO_BIT; > > > + > > >         if (ka->sa.sa_flags & SA_RESTORER) > > >                 sigtramp = ka->sa.sa_restorer; > > >         else > > > @@ -921,6 +924,11 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, > > >                         if (thread_flags & _TIF_UPROBE) > > >                                 uprobe_notify_resume(regs); > > > > > > +                       if (thread_flags & _TIF_MTE_ASYNC_FAULT) { > > > +                               clear_thread_flag(TIF_MTE_ASYNC_FAULT); > > > +                               force_signal_inject(SIGSEGV, SEGV_MTEAERR, 0); > > > > In the case where the kernel is entered due to a syscall, this will > > inject a signal, but only after servicing the syscall. This means > > that, for example, if the syscall is exit(), the async tag check > > failure will be silently ignored. I can reproduce the problem with the > > program below: > [...] > > This patch fixes the problem for me: > > > > diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c > > index 9a9d98a443fc..d0c8918dee00 100644 > > --- a/arch/arm64/kernel/syscall.c > > +++ b/arch/arm64/kernel/syscall.c > > @@ -94,6 +94,8 @@ static void el0_svc_common(struct pt_regs *regs, int > > scno, int sc_nr, > >                            const syscall_fn_t syscall_table[]) > >  { > >         unsigned long flags = current_thread_info()->flags; > > +       if (flags & _TIF_MTE_ASYNC_FAULT) > > +               return; > > It needs a bit of thinking. This one wouldn't work if you want to handle > the signal and resume since it would skip the SVC instruction. We'd need > at least to do a regs->pc -= 4 and probably move it further down in this > function. Okay, how does this look? Peter arch/arm64/kernel/syscall.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c index 9a9d98a443fc..49ea9bb47190 100644 --- a/arch/arm64/kernel/syscall.c +++ b/arch/arm64/kernel/syscall.c @@ -95,13 +95,29 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr, { unsigned long flags = current_thread_info()->flags; - regs->orig_x0 = regs->regs[0]; - regs->syscallno = scno; - cortex_a76_erratum_1463225_svc_handler(); local_daif_restore(DAIF_PROCCTX); user_exit(); +#ifdef CONFIG_ARM64_MTE + if (flags & _TIF_MTE_ASYNC_FAULT) { + /* + * We entered the kernel after an async tag fault due to a + * syscall, rather than for another reason (e.g. preemption). + * In this case, we don't want to service the syscall as it may + * mask the tag fault. Rewind the PC to the svc instruction in + * order to give a userspace signal handler an opportunity to + * handle the fault and resume, and skip all other syscall + * processing. + */ + regs->pc -= 4; + return; + } +#endif + + regs->orig_x0 = regs->regs[0]; + regs->syscallno = scno; + if (has_syscall_work(flags)) { /* set default errno for user-issued syscall(-1) */ if (scno == NO_SYSCALL)