From patchwork Fri Jun 16 19:16:55 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: tip-bot2 for Thomas Gleixner X-Patchwork-Id: 109311 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp1563345vqr; Fri, 16 Jun 2023 12:18:41 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ5U2+lY8kw2JdzTtdiBddT7pA0zsbuBJfkbm0tZYYvWVGUZs+LplpA4Gsgi7PpvACmC1ffL X-Received: by 2002:a05:6a00:804:b0:64b:50:2410 with SMTP id m4-20020a056a00080400b0064b00502410mr3688836pfk.19.1686943121275; Fri, 16 Jun 2023 12:18:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1686943121; cv=none; d=google.com; s=arc-20160816; b=OUPweSneduE+iuMS1bCNmpb/ZXZyfUzi1TZnE/IqxlyLaCdsGnlYSYzxj4O4fjoohy 6eojZLD8BN9dI4ku/s5BTcnc+dZwV8BcRk4HJ63wVn1nF4eZhtvYV/49YLIP6C0Jcuj5 36GYFlWel+RZfStqN/DhR3w8X1XqfQw7eqsoZj5IuU5FyTs1dSRfFUW1VpKttIVfx2iU eFci26DwqGKJGSAGOhLHBhYW6HHupqAbo1Mqmz26UMjIv6cjCwMfZM2RDEAgg7HWJOqB 0xBOpyEbmWhsvRFnPx5Apqc5YNkPDG1dKgCy37b/MY1w5l19aNfIUoKN9T4TI9XQ21Kl IThw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:robot-unsubscribe :robot-id:message-id:mime-version:cc:subject:to:reply-to:sender:from :dkim-signature:dkim-signature:date; bh=M7XgB0OGOPsFYGZZ/z92GXf6OToxqzkZZ/QyKcnapfA=; b=hbhlxSBVt42i9ozwDJbqeft6PbqYrxG3w3YLeMcdWN5kxQsWpblaA0ekXlYoL+qiet cBD0KlauIhIjy3g0t8kfddA1nRf9XhCMc/FLo1EWJx0jW830bv9+lBiSnpJJhQaqzfQV m1cTCjan3FnZ1kf6OhC7Tvf7vGoK7ACWEkhyA9d3p3k+gO65aqrwH4aWb1c2P8n7JaAD 9e1Zhf7uEIGOXa03c1UUFE/6sWUp/H4rY7DG97gL4BvAtWYvMJrK6IJjcJSSBA37hUlu wv4hA/8u8ABmMq2Zk09LkvD5CNqywsGn2c1rqPop7exXbfkHUs3aE3y44WATve9KYEgA S8MA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=m4LgpEbv; dkim=neutral (no key) header.i=@linutronix.de header.s=2020e header.b="jg/s4nfR"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id j187-20020a638bc4000000b0054fd5ecd392si6019468pge.758.2023.06.16.12.18.26; Fri, 16 Jun 2023 12:18:41 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=m4LgpEbv; dkim=neutral (no key) header.i=@linutronix.de header.s=2020e header.b="jg/s4nfR"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229518AbjFPTRm (ORCPT + 99 others); Fri, 16 Jun 2023 15:17:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47974 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1345839AbjFPTQ6 (ORCPT ); Fri, 16 Jun 2023 15:16:58 -0400 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 89BCF35A7; Fri, 16 Jun 2023 12:16:57 -0700 (PDT) Date: Fri, 16 Jun 2023 19:16:55 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1686943015; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=M7XgB0OGOPsFYGZZ/z92GXf6OToxqzkZZ/QyKcnapfA=; b=m4LgpEbvAnD1kwsPyHzUSqpcpG7d9yQS9Waa71AMHD313rokVUXM5vqiH+ZfwDdsVVvpQl UXJ6EC+D6CIxdO/6IKt4FtyJDNrUdCn6O7bYkVsHJcsSWlgQhlrza6a2n7SbAjUvo5JAaR /dfDPtG+zYVmqL0DycDChQ5FxFDYc9Ui3AUbPlspN5NAyXZrg5czBQ6iUMgflXScccm5kO vGk+KNy3ob+3SufeLA2G4pTEGIUxP2bss7793mUqAhAEwpeXStBCL6WZvLJSVAchYgSYq5 goZePbwSEf2AOKFcHpQBLqrfnGMwKKKxp0k0z/1QyF9RF42hT+XZdfr0s/a+Dw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1686943015; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=M7XgB0OGOPsFYGZZ/z92GXf6OToxqzkZZ/QyKcnapfA=; b=jg/s4nfRE0XqdpVY47ZmhiSG8LdadL2/d0eAFuGYktZzrMNA9wkWJ8/Uqs5NyDawNwPPgS bZRk7lw5Huw7bIDQ== From: "tip-bot2 for Rick Edgecombe" Sender: tip-bot2@linutronix.de Reply-to: linux-kernel@vger.kernel.org To: linux-tip-commits@vger.kernel.org Subject: [tip: x86/shstk] x86/shstk: Handle signals for shadow stack Cc: "Yu-cheng Yu" , Rick Edgecombe , Dave Hansen , "Borislav Petkov (AMD)" , Kees Cook , "Mike Rapoport (IBM)" , Pengfei Xu , John Allen , x86@kernel.org, linux-kernel@vger.kernel.org MIME-Version: 1.0 Message-ID: <168694301534.404.9273402624964751657.tip-bot2@tip-bot2> Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1768888070408791423?= X-GMAIL-MSGID: =?utf-8?q?1768888070408791423?= The following commit has been merged into the x86/shstk branch of tip: Commit-ID: 6bf19cec9a198b8f6af939b5f7bd5d3e721c9e7e Gitweb: https://git.kernel.org/tip/6bf19cec9a198b8f6af939b5f7bd5d3e721c9e7e Author: Rick Edgecombe AuthorDate: Mon, 12 Jun 2023 17:10:57 -07:00 Committer: Dave Hansen CommitterDate: Thu, 15 Jun 2023 16:31:34 -07:00 x86/shstk: Handle signals for shadow stack When a signal is handled, the context is pushed to the stack before handling it. For shadow stacks, since the shadow stack only tracks return addresses, there isn't any state that needs to be pushed. However, there are still a few things that need to be done. These things are visible to userspace and which will be kernel ABI for shadow stacks. One is to make sure the restorer address is written to shadow stack, since the signal handler (if not changing ucontext) returns to the restorer, and the restorer calls sigreturn. So add the restorer on the shadow stack before handling the signal, so there is not a conflict when the signal handler returns to the restorer. The other thing to do is to place some type of checkable token on the thread's shadow stack before handling the signal and check it during sigreturn. This is an extra layer of protection to hamper attackers calling sigreturn manually as in SROP-like attacks. For this token the shadow stack data format defined earlier can be used. Have the data pushed be the previous SSP. In the future the sigreturn might want to return back to a different stack. Storing the SSP (instead of a restore offset or something) allows for future functionality that may want to restore to a different stack. So, when handling a signal push - the SSP pointing in the shadow stack data format - the restorer address below the restore token. In sigreturn, verify SSP is stored in the data format and pop the shadow stack. Co-developed-by: Yu-cheng Yu Signed-off-by: Yu-cheng Yu Signed-off-by: Rick Edgecombe Signed-off-by: Dave Hansen Reviewed-by: Borislav Petkov (AMD) Reviewed-by: Kees Cook Acked-by: Mike Rapoport (IBM) Tested-by: Pengfei Xu Tested-by: John Allen Tested-by: Kees Cook Link: https://lore.kernel.org/all/20230613001108.3040476-32-rick.p.edgecombe%40intel.com --- arch/x86/include/asm/shstk.h | 5 ++- arch/x86/kernel/shstk.c | 95 +++++++++++++++++++++++++++++++++++- arch/x86/kernel/signal.c | 1 +- arch/x86/kernel/signal_64.c | 6 ++- 4 files changed, 107 insertions(+) diff --git a/arch/x86/include/asm/shstk.h b/arch/x86/include/asm/shstk.h index d4a5c7b..ecb23a8 100644 --- a/arch/x86/include/asm/shstk.h +++ b/arch/x86/include/asm/shstk.h @@ -6,6 +6,7 @@ #include struct task_struct; +struct ksignal; #ifdef CONFIG_X86_USER_SHADOW_STACK struct thread_shstk { @@ -18,6 +19,8 @@ void reset_thread_features(void); unsigned long shstk_alloc_thread_stack(struct task_struct *p, unsigned long clone_flags, unsigned long stack_size); void shstk_free(struct task_struct *p); +int setup_signal_shadow_stack(struct ksignal *ksig); +int restore_signal_shadow_stack(void); #else static inline long shstk_prctl(struct task_struct *task, int option, unsigned long arg2) { return -EINVAL; } @@ -26,6 +29,8 @@ static inline unsigned long shstk_alloc_thread_stack(struct task_struct *p, unsigned long clone_flags, unsigned long stack_size) { return 0; } static inline void shstk_free(struct task_struct *p) {} +static inline int setup_signal_shadow_stack(struct ksignal *ksig) { return 0; } +static inline int restore_signal_shadow_stack(void) { return 0; } #endif /* CONFIG_X86_USER_SHADOW_STACK */ #endif /* __ASSEMBLY__ */ diff --git a/arch/x86/kernel/shstk.c b/arch/x86/kernel/shstk.c index e22928c..f02e8ea 100644 --- a/arch/x86/kernel/shstk.c +++ b/arch/x86/kernel/shstk.c @@ -232,6 +232,101 @@ static int get_shstk_data(unsigned long *data, unsigned long __user *addr) return 0; } +static int shstk_push_sigframe(unsigned long *ssp) +{ + unsigned long target_ssp = *ssp; + + /* Token must be aligned */ + if (!IS_ALIGNED(target_ssp, 8)) + return -EINVAL; + + *ssp -= SS_FRAME_SIZE; + if (put_shstk_data((void *__user)*ssp, target_ssp)) + return -EFAULT; + + return 0; +} + +static int shstk_pop_sigframe(unsigned long *ssp) +{ + unsigned long token_addr; + int err; + + err = get_shstk_data(&token_addr, (unsigned long __user *)*ssp); + if (unlikely(err)) + return err; + + /* Restore SSP aligned? */ + if (unlikely(!IS_ALIGNED(token_addr, 8))) + return -EINVAL; + + /* SSP in userspace? */ + if (unlikely(token_addr >= TASK_SIZE_MAX)) + return -EINVAL; + + *ssp = token_addr; + + return 0; +} + +int setup_signal_shadow_stack(struct ksignal *ksig) +{ + void __user *restorer = ksig->ka.sa.sa_restorer; + unsigned long ssp; + int err; + + if (!cpu_feature_enabled(X86_FEATURE_USER_SHSTK) || + !features_enabled(ARCH_SHSTK_SHSTK)) + return 0; + + if (!restorer) + return -EINVAL; + + ssp = get_user_shstk_addr(); + if (unlikely(!ssp)) + return -EINVAL; + + err = shstk_push_sigframe(&ssp); + if (unlikely(err)) + return err; + + /* Push restorer address */ + ssp -= SS_FRAME_SIZE; + err = write_user_shstk_64((u64 __user *)ssp, (u64)restorer); + if (unlikely(err)) + return -EFAULT; + + fpregs_lock_and_load(); + wrmsrl(MSR_IA32_PL3_SSP, ssp); + fpregs_unlock(); + + return 0; +} + +int restore_signal_shadow_stack(void) +{ + unsigned long ssp; + int err; + + if (!cpu_feature_enabled(X86_FEATURE_USER_SHSTK) || + !features_enabled(ARCH_SHSTK_SHSTK)) + return 0; + + ssp = get_user_shstk_addr(); + if (unlikely(!ssp)) + return -EINVAL; + + err = shstk_pop_sigframe(&ssp); + if (unlikely(err)) + return err; + + fpregs_lock_and_load(); + wrmsrl(MSR_IA32_PL3_SSP, ssp); + fpregs_unlock(); + + return 0; +} + void shstk_free(struct task_struct *tsk) { struct thread_shstk *shstk = &tsk->thread.shstk; diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 004cb30..356253e 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -40,6 +40,7 @@ #include #include #include +#include static inline int is_ia32_compat_frame(struct ksignal *ksig) { diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 0e808c7..cacf2ed 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -175,6 +175,9 @@ int x64_setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs) frame = get_sigframe(ksig, regs, sizeof(struct rt_sigframe), &fp); uc_flags = frame_uc_flags(regs); + if (setup_signal_shadow_stack(ksig)) + return -EFAULT; + if (!user_access_begin(frame, sizeof(*frame))) return -EFAULT; @@ -260,6 +263,9 @@ SYSCALL_DEFINE0(rt_sigreturn) if (!restore_sigcontext(regs, &frame->uc.uc_mcontext, uc_flags)) goto badframe; + if (restore_signal_shadow_stack()) + goto badframe; + if (restore_altstack(&frame->uc.uc_stack)) goto badframe;