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: 109312 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp1563355vqr; Fri, 16 Jun 2023 12:18:43 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ5o/UI4j7w9YbJo1Znf5Ll3mfX1QUb8LHVhWD51Npvct8IfjnGldo7+9Of9LbYkwgLkfXAb X-Received: by 2002:a92:ce49:0:b0:340:b4b2:5fb8 with SMTP id a9-20020a92ce49000000b00340b4b25fb8mr218394ilr.10.1686943123100; Fri, 16 Jun 2023 12:18:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1686943123; cv=none; d=google.com; s=arc-20160816; b=SgjFjHEeXq8GsOJ6ryjOPpk1JNp4QlfQkCXr059roTBUwvfT4QV2eZVuaP2QyPg1ip 4vtbHfzMZPr9dWDE/oYmgyvmVRcs9ZAKir6UFcJmEz/YSqQ2ukhvPeFPNjDXmbGQW7s+ SlHiA0tRwED/bGdyaxbi2LcfraG0Z/mqu7/T8rnNQ7qPtvKfYxQSt+cCqUHfVdwLLG17 NUhRhfvwVccHcDbT/6VpsGRCFSTP3GdLatB9jK7dGGKxGyUEcjWL21y8ursAQ9WJP1wy 8iNMKbs3NpuOczvAvSKCryo3gz2Jv4EMflQ++RfU9XU5coWRfDS+MdRIppqmDn245WpI FLCA== 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=UmtZngEwGEglvAjwA1iZWOHFlGGQMSgXWHHhk2pwUQI=; b=mKV6oew+zIDIeQdXQbk2dUuSdY9M0S0VwioWcOh82l8M+CiFv16wQu3yKUOyi6ZlCQ tK3BDvJijep1fvmb8ryTHT8m1FiDlsblK3YLuofOi9yFG4XBCAkMgqNiOf6ThxOxJ1y9 FS/Pc0uFNufda0rkZ5/osICAP+bhEM9hIlOud4y+tE+HHrbNf80iy3WFG3PoYbFqzZp4 ip3RdQ8klmmi0Da5vUdQKH83ZHY2MBZNIAWBcIkYRkkNiYy8T1W5+ukvD6Tc8iaRvPYi vrIbqg2dv7AbAQQq9SUOTKXC+MmDjPqkyGR7XAyw/UHtdgGTYiDJMDbNqRskPR8LGbRx hpVQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=xRQrYTKJ; dkim=neutral (no key) header.i=@linutronix.de header.s=2020e header.b=HY+ew+Zj; 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 g9-20020a636b09000000b005537e4e7d59si1438081pgc.84.2023.06.16.12.18.28; Fri, 16 Jun 2023 12:18:43 -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=xRQrYTKJ; dkim=neutral (no key) header.i=@linutronix.de header.s=2020e header.b=HY+ew+Zj; 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 S1345804AbjFPTRp (ORCPT + 99 others); Fri, 16 Jun 2023 15:17:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47984 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230265AbjFPTQ7 (ORCPT ); Fri, 16 Jun 2023 15:16:59 -0400 Received: from galois.linutronix.de (Galois.linutronix.de [IPv6:2a0a:51c0:0:12e:550::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A5C6E35AD; 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=1686943016; 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=UmtZngEwGEglvAjwA1iZWOHFlGGQMSgXWHHhk2pwUQI=; b=xRQrYTKJQJ9BECIYsswb/M/tkHhl6sEroqSRxV7t8wtj9WrzEQkN0zwatBdHS7ergIpXZX zridPXwcp7Afk3Hk73gXVo38WF4oQsg47Mw5IDDtmJnfEUT6fOI9edP+Z8WZJ+RKf100jJ jURlIijjepod8YM97Ajbw89ozYB/sMj3fUuMWV9dULtiPhYFmJZj3X0V6xJZ4BUAp7kjJF sHi2a0+rztGu8I1m8HavXjmt8VRILkUQuhyAFjZ3o12BiyS5anKpvX/ydSlAYqBbbr/b76 7h4OrcAMJcdn+YU+vRbkWEXEVxU9J7WcRr6Vkr6t8zuNGfASkxOedPhjM2fn5Q== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1686943016; 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=UmtZngEwGEglvAjwA1iZWOHFlGGQMSgXWHHhk2pwUQI=; b=HY+ew+ZjmZrm04VhuWzfvMt5hLnOYsox2eYD3/S+BX3AS8pBxP/woLHsgl4bELA41kfR8C iDRCjmt8gNcahwAg== 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: Introduce routines modifying shstk 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: <168694301574.404.8311948853813705393.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?1768888072233671668?= X-GMAIL-MSGID: =?utf-8?q?1768888072233671668?= The following commit has been merged into the x86/shstk branch of tip: Commit-ID: 10b9f8c4a81cb827c555868bc06abc257fdfedf0 Gitweb: https://git.kernel.org/tip/10b9f8c4a81cb827c555868bc06abc257fdfedf0 Author: Rick Edgecombe AuthorDate: Mon, 12 Jun 2023 17:10:56 -07:00 Committer: Dave Hansen CommitterDate: Thu, 15 Jun 2023 16:31:34 -07:00 x86/shstk: Introduce routines modifying shstk Shadow stacks are normally written to via CALL/RET or specific CET instructions like RSTORSSP/SAVEPREVSSP. However, sometimes the kernel will need to write to the shadow stack directly using the ring-0 only WRUSS instruction. A shadow stack restore token marks a restore point of the shadow stack, and the address in a token must point directly above the token, which is within the same shadow stack. This is distinctively different from other pointers on the shadow stack, since those pointers point to executable code area. Introduce token setup and verify routines. Also introduce WRUSS, which is a kernel-mode instruction but writes directly to user shadow stack. In future patches that enable shadow stack to work with signals, the kernel will need something to denote the point in the stack where sigreturn may be called. This will prevent attackers calling sigreturn at arbitrary places in the stack, in order to help prevent SROP attacks. To do this, something that can only be written by the kernel needs to be placed on the shadow stack. This can be accomplished by setting bit 63 in the frame written to the shadow stack. Userspace return addresses can't have this bit set as it is in the kernel range. It also can't be a valid restore token. 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-31-rick.p.edgecombe%40intel.com --- arch/x86/include/asm/special_insns.h | 13 +++++- arch/x86/kernel/shstk.c | 75 +++++++++++++++++++++++++++- 2 files changed, 88 insertions(+) diff --git a/arch/x86/include/asm/special_insns.h b/arch/x86/include/asm/special_insns.h index de48d13..d6cd934 100644 --- a/arch/x86/include/asm/special_insns.h +++ b/arch/x86/include/asm/special_insns.h @@ -202,6 +202,19 @@ static inline void clwb(volatile void *__p) : [pax] "a" (p)); } +#ifdef CONFIG_X86_USER_SHADOW_STACK +static inline int write_user_shstk_64(u64 __user *addr, u64 val) +{ + asm_volatile_goto("1: wrussq %[val], (%[addr])\n" + _ASM_EXTABLE(1b, %l[fail]) + :: [addr] "r" (addr), [val] "r" (val) + :: fail); + return 0; +fail: + return -EFAULT; +} +#endif /* CONFIG_X86_USER_SHADOW_STACK */ + #define nop() asm volatile ("nop") static inline void serialize(void) diff --git a/arch/x86/kernel/shstk.c b/arch/x86/kernel/shstk.c index bd9cdc3..e22928c 100644 --- a/arch/x86/kernel/shstk.c +++ b/arch/x86/kernel/shstk.c @@ -25,6 +25,8 @@ #include #include +#define SS_FRAME_SIZE 8 + static bool features_enabled(unsigned long features) { return current->thread.features & features; @@ -40,6 +42,35 @@ static void features_clr(unsigned long features) current->thread.features &= ~features; } +/* + * Create a restore token on the shadow stack. A token is always 8-byte + * and aligned to 8. + */ +static int create_rstor_token(unsigned long ssp, unsigned long *token_addr) +{ + unsigned long addr; + + /* Token must be aligned */ + if (!IS_ALIGNED(ssp, 8)) + return -EINVAL; + + addr = ssp - SS_FRAME_SIZE; + + /* + * SSP is aligned, so reserved bits and mode bit are a zero, just mark + * the token 64-bit. + */ + ssp |= BIT(0); + + if (write_user_shstk_64((u64 __user *)addr, (u64)ssp)) + return -EFAULT; + + if (token_addr) + *token_addr = addr; + + return 0; +} + static unsigned long alloc_shstk(unsigned long size) { int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_ABOVE4G; @@ -157,6 +188,50 @@ unsigned long shstk_alloc_thread_stack(struct task_struct *tsk, unsigned long cl return addr + size; } +static unsigned long get_user_shstk_addr(void) +{ + unsigned long long ssp; + + fpregs_lock_and_load(); + + rdmsrl(MSR_IA32_PL3_SSP, ssp); + + fpregs_unlock(); + + return ssp; +} + +#define SHSTK_DATA_BIT BIT(63) + +static int put_shstk_data(u64 __user *addr, u64 data) +{ + if (WARN_ON_ONCE(data & SHSTK_DATA_BIT)) + return -EINVAL; + + /* + * Mark the high bit so that the sigframe can't be processed as a + * return address. + */ + if (write_user_shstk_64(addr, data | SHSTK_DATA_BIT)) + return -EFAULT; + return 0; +} + +static int get_shstk_data(unsigned long *data, unsigned long __user *addr) +{ + unsigned long ldata; + + if (unlikely(get_user(ldata, addr))) + return -EFAULT; + + if (!(ldata & SHSTK_DATA_BIT)) + return -EINVAL; + + *data = ldata & ~SHSTK_DATA_BIT; + + return 0; +} + void shstk_free(struct task_struct *tsk) { struct thread_shstk *shstk = &tsk->thread.shstk;