From patchwork Mon Feb 27 22:29:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Edgecombe, Rick P" X-Patchwork-Id: 13154249 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id B1D08C83005 for ; Mon, 27 Feb 2023 22:32:00 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id D3CFE6B008A; Mon, 27 Feb 2023 17:31:47 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id A41A06B0096; Mon, 27 Feb 2023 17:31:47 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 69A3B6B0093; Mon, 27 Feb 2023 17:31:47 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0014.hostedemail.com [216.40.44.14]) by kanga.kvack.org (Postfix) with ESMTP id 275F56B008A for ; Mon, 27 Feb 2023 17:31:47 -0500 (EST) Received: from smtpin15.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id 09FD51A05A5 for ; Mon, 27 Feb 2023 22:31:47 +0000 (UTC) X-FDA: 80514520254.15.D691236 Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by imf24.hostedemail.com (Postfix) with ESMTP id 08E2A180009 for ; Mon, 27 Feb 2023 22:31:44 +0000 (UTC) Authentication-Results: imf24.hostedemail.com; dkim=pass header.d=intel.com header.s=Intel header.b=RhOrvd+M; dmarc=pass (policy=none) header.from=intel.com; spf=pass (imf24.hostedemail.com: domain of rick.p.edgecombe@intel.com designates 192.55.52.136 as permitted sender) smtp.mailfrom=rick.p.edgecombe@intel.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1677537105; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references:dkim-signature; bh=5N0lFCbFu8gwpBsmCT1OeqTBC2+wwCTV8SigqvCE8fg=; b=0qKZWl/i0Gd48ANjZDXhFskK+dSaN9BWVXjJWc+Q9h4NR3mcI02LOHyKQvTA94ycgFGOjd 81H/iAppktyOm73AN9thMg7RTcAYs+UefFxVg0y94JIxal/ubG2c93PZyY7Pt5PjsoVVs7 XNKUUiNdiG2ABeYCxlEAuSjQDUwCHFg= ARC-Authentication-Results: i=1; imf24.hostedemail.com; dkim=pass header.d=intel.com header.s=Intel header.b=RhOrvd+M; dmarc=pass (policy=none) header.from=intel.com; spf=pass (imf24.hostedemail.com: domain of rick.p.edgecombe@intel.com designates 192.55.52.136 as permitted sender) smtp.mailfrom=rick.p.edgecombe@intel.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1677537105; a=rsa-sha256; cv=none; b=TQI6bQH9HSMtJlpu/QB7YWve2F0xkTTIW0TsEIqZkGWU9ajc3g9bdRgR5BOfhfwjHwZKLm saGOgXOSTL8OBqik4UvfD6QAy6G0KtOtKPJNvhH11yiT4YP8WCvopzbglAlWtuH/py0o2f LQxndwLafqPcFJels7tm5n22uW/xyYw= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1677537105; x=1709073105; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=Pl+T1+xmSBSUgFqJaHPWJP+BmegywDM6GYKzVKSMXoQ=; b=RhOrvd+MjCj46UIbdgPZrlU22DVQXSsU7b2FM6A7cxk1nLipVM56ZbdM AqO+nUCr0cgh/9q0V4vNNnHMJXRfydVZc0pV9t6u5mVUzcpIAzRjQMwdG UesWZs6T8XK/4W/Fxt0C8kd9eVYqX/CEde4a5qk+kjBwMn7pbOzdy4RO9 mlD8SwXe0k/GNUz52u3G2+cK3dEs1sNNT3X0XQrsX68cqIoVDNnQRR4/i OfX80XlVfYcxyksZPqDjbBpJzSMdccDe6EZBBdAya3IRDNE4FQm//I/N3 Wr6cOBN7HV/27TSBc/UIETMkJznvNhFgNCwPzpQ0CEohpLWgG6mc/f0t1 g==; X-IronPort-AV: E=McAfee;i="6500,9779,10634"; a="313657391" X-IronPort-AV: E=Sophos;i="5.98,220,1673942400"; d="scan'208";a="313657391" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Feb 2023 14:31:23 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10634"; a="848024576" X-IronPort-AV: E=Sophos;i="5.98,220,1673942400"; d="scan'208";a="848024576" Received: from leonqu-mobl1.amr.corp.intel.com (HELO rpedgeco-desk.amr.corp.intel.com) ([10.209.72.19]) by orsmga005-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Feb 2023 14:31:18 -0800 From: Rick Edgecombe To: x86@kernel.org, "H . Peter Anvin" , Thomas Gleixner , Ingo Molnar , linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-mm@kvack.org, linux-arch@vger.kernel.org, linux-api@vger.kernel.org, Arnd Bergmann , Andy Lutomirski , Balbir Singh , Borislav Petkov , Cyrill Gorcunov , Dave Hansen , Eugene Syromiatnikov , Florian Weimer , "H . J . Lu" , Jann Horn , Jonathan Corbet , Kees Cook , Mike Kravetz , Nadav Amit , Oleg Nesterov , Pavel Machek , Peter Zijlstra , Randy Dunlap , Weijiang Yang , "Kirill A . Shutemov" , John Allen , kcc@google.com, eranian@google.com, rppt@kernel.org, jamorris@linux.microsoft.com, dethoma@microsoft.com, akpm@linux-foundation.org, Andrew.Cooper3@citrix.com, christina.schimpe@intel.com, david@redhat.com, debug@rivosinc.com Cc: rick.p.edgecombe@intel.com, Yu-cheng Yu Subject: [PATCH v7 15/41] x86/mm: Update ptep/pmdp_set_wrprotect() for _PAGE_SAVED_DIRTY Date: Mon, 27 Feb 2023 14:29:31 -0800 Message-Id: <20230227222957.24501-16-rick.p.edgecombe@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230227222957.24501-1-rick.p.edgecombe@intel.com> References: <20230227222957.24501-1-rick.p.edgecombe@intel.com> X-Rspamd-Queue-Id: 08E2A180009 X-Rspamd-Server: rspam09 X-Rspam-User: X-Stat-Signature: qjq8bzwap5z6m3pdkgi6or9au1qufrq9 X-HE-Tag: 1677537104-818712 X-HE-Meta: U2FsdGVkX1/pnCdx1qcUQcLLFV+Nch0rLI2/0/iyy1MRJwEn4MU5lr1nJ0clGngnwIbNTEt8FZpiPHsKluJM1D2WZv0ftXKFYaLenbxzp4bJ+GzNRHGq/xD2gGtYfs2Ys43bpCmU4gjhpxaNim+VA/s6uuMKRcGaNuPK7Akf6AcdSg5BfSytxVUQvbIs4UdjGj4fggeBodGc7egCm5xYpV9bR+N8IQiw7pAScFfBqzGx30JEbe5L1YXaf9sES68FxJceN/FoRcWvY54mEkuVd3EX8MKykipOE0JDML7Kn1eNkqocUS/WvPWfxuh2wO/IQVPzRFHISVzayc8kJY1lCo0NihA9inlIOMxBQVdIO2nW5LZW7mevLHyx773lTME+1tzOe46ROGNHRdqRJmjaarx9oasXc6wSq1yqMNlT0ZI7GzggvRTqMQnL0rPvVUb4WrlNN2mCbzyqmzB3Mnudh0gUrdGpcT533CjdmRkf+ibzP6haY6YW1ywS7jJKHA/7K7CWe8qQXJZ6an8PkJ9hHeSzAO8IAnaRqGRz9mxcCQWes3HeieDUhjVtZCkmjlisOg041iYprHTZbOUtbuhl0fGdisrROJZ+L8P1WKGZjvH5UrLqSxXhJUAxlS9zblBa6ennFtYhWPfdH9UXpewokKOWVJRg1yyZLnWbX4SXbCR1as7OuJW1ELQ/bTmpaAh9F/IfJZ8Z0zcjFXghXMEfFf1yV8gBN9jRof87CuU6QkOpcQV3ghQruiMxwe0aBykAamOV4GvINFPb4QWGStBB7WD++yemtB4Utjuh6zZKi1qN11VlU41y2bdXKoPwdNmA2FebZd0kpL2PdDVemncfFQ8KrI9vGFbO4N2ZJHKK8ncC7YrV3nS1cOdPFsskKOWQUXOAJY3WnD2LrzNH2RTcXrAvGd+BnTDgCIg20O8CWaZ9BY4p5EIVOWUEzHT8Zq3Qc8Z3uBQrXbnRjrsWScR Y5ZYi8ZR 6k5eFH6UJiXEbC4+NQmfgv/PTw07Dmj7ItEXNxIo6+N+XB1ekCyZoSBmDXqMHPS+GYaAhRq5T+oT4BSDn4SrOC+DJ7up9QfsRnq6B3ydMToTfsVGboKVIZhru3eKGOsJ+n4HRZzxVbuSfCF5G1H52iHhMd4rjYG4XfefSuY585yQfuUcrRpwZP4Zacf8JGdjscubo5I7hQ2p6GrOzH6VTul77O9ZFGau4L5AjK/XDpMHKPAEGxk8NbtU08HUAVRmt0UGyl4raCcmqoaT9Ma3cD7S6qFUAKn4v7R7JEOiKuUsvFVKfRT5xub+mCUYMzsmVpZ8m8ve3D0bRd/zDKcaK58wVFFqc7Iv/3r+nxWxjOEsttMDpIbWL7l3h4G2wLCCFpXS5bXzyLMjj8rs= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: From: Yu-cheng Yu When shadow stack is in use, Write=0,Dirty=1 PTE are preserved for shadow stack. Copy-on-write PTEs then have Write=0,SavedDirty=1. When a PTE goes from Write=1,Dirty=1 to Write=0,SavedDirty=1, it could become a transient shadow stack PTE in two cases: 1. Some processors can start a write but end up seeing a Write=0 PTE by the time they get to the Dirty bit, creating a transient shadow stack PTE. However, this will not occur on processors supporting shadow stack, and a TLB flush is not necessary. 2. When _PAGE_DIRTY is replaced with _PAGE_SAVED_DIRTY non-atomically, a transient shadow stack PTE can be created as a result. Thus, prevent that with cmpxchg. In the case of pmdp_set_wrprotect(), for nopmd configs the ->pmd operated on does not exist and the logic would need to be different. Although the extra functionality will normally be optimized out when user shadow stacks are not configured, also exclude it in the preprocessor stage so that it will still compile. User shadow stack is not supported there by Linux anyway. Leave the cpu_feature_enabled() check so that the functionality also gets disabled based on runtime detection of the feature. Similarly, compile it out in ptep_set_wrprotect() due to a clang warning on i386. Like above, the code path should get optimized out on i386 since shadow stack is not supported on 32 bit kernels, but this makes the compiler happy. Dave Hansen, Jann Horn, Andy Lutomirski, and Peter Zijlstra provided many insights to the issue. Jann Horn provided the cmpxchg solution. Tested-by: Pengfei Xu Tested-by: John Allen Tested-by: Kees Cook Acked-by: Mike Rapoport (IBM) Reviewed-by: Kees Cook Signed-off-by: Yu-cheng Yu Co-developed-by: Rick Edgecombe Signed-off-by: Rick Edgecombe --- v6: - Fix comment and log to update for _PAGE_COW being replaced with _PAGE_SAVED_DIRTY. v5: - Commit log verbiage and formatting (Boris) - Remove capitalization on shadow stack (Boris) - Fix i386 warning on recent clang v3: - Remove unnecessary #ifdef (Dave Hansen) v2: - Compile out some code due to clang build error - Clarify commit log (dhansen) - Normalize PTE bit descriptions between patches (dhansen) - Update comment with text from (dhansen) --- arch/x86/include/asm/pgtable.h | 35 ++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 7360783f2140..349fcab0405a 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -1192,6 +1192,23 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { +#ifdef CONFIG_X86_USER_SHADOW_STACK + /* + * Avoid accidentally creating shadow stack PTEs + * (Write=0,Dirty=1). Use cmpxchg() to prevent races with + * the hardware setting Dirty=1. + */ + if (cpu_feature_enabled(X86_FEATURE_USER_SHSTK)) { + pte_t old_pte, new_pte; + + old_pte = READ_ONCE(*ptep); + do { + new_pte = pte_wrprotect(old_pte); + } while (!try_cmpxchg(&ptep->pte, &old_pte.pte, new_pte.pte)); + + return; + } +#endif clear_bit(_PAGE_BIT_RW, (unsigned long *)&ptep->pte); } @@ -1244,6 +1261,24 @@ static inline pud_t pudp_huge_get_and_clear(struct mm_struct *mm, static inline void pmdp_set_wrprotect(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp) { +#ifdef CONFIG_X86_USER_SHADOW_STACK + /* + * Avoid accidentally creating shadow stack PTEs + * (Write=0,Dirty=1). Use cmpxchg() to prevent races with + * the hardware setting Dirty=1. + */ + if (cpu_feature_enabled(X86_FEATURE_USER_SHSTK)) { + pmd_t old_pmd, new_pmd; + + old_pmd = READ_ONCE(*pmdp); + do { + new_pmd = pmd_wrprotect(old_pmd); + } while (!try_cmpxchg(&pmdp->pmd, &old_pmd.pmd, new_pmd.pmd)); + + return; + } +#endif + clear_bit(_PAGE_BIT_RW, (unsigned long *)pmdp); }