From nobody Fri Jan 2 01:45:46 2026 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0022BCDB474 for ; Tue, 17 Oct 2023 20:25:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344443AbjJQUZi (ORCPT ); Tue, 17 Oct 2023 16:25:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55518 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234861AbjJQUZb (ORCPT ); Tue, 17 Oct 2023 16:25:31 -0400 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.7]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 86A61BA; Tue, 17 Oct 2023 13:25:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1697574330; x=1729110330; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=gcF+O4qhVSDzWKyOPqIfGB0MPXeZPkkPdOYMfsrWVF0=; b=OYVqzXze13qHqoLPgXrwAY1F5UxX6jgrbXAmmnmxbiLJ497jgzMcTWai qdfXq9pVmhPDreyTj+WhdVcVJbiNHTjkWvtY4A42/tsaxBTH3dWVjAyLJ QOjIy5W2LYnxzuRil79sygRtMcYlD35iD5q3QnbirkaXZOIY8Fbg7KRpR Jyjo8LefcxdAvOK6Vf2/e61NIEgGUaiwgNoDxdgRpbyfigYnKkWYlCdeS LQnAKXfH5Cv6BGjiMZU1iKfnAJ9EtAEyB2n3c1mLV5NyKFOn867eZ8bSo ka3u0mYopThZlRF0EUZoWqoNxDMIJISGlbLVgdu6N0ZlMYgFR0HxlaXZx g==; X-IronPort-AV: E=McAfee;i="6600,9927,10866"; a="7429498" X-IronPort-AV: E=Sophos;i="6.03,233,1694761200"; d="scan'208";a="7429498" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmvoesa101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Oct 2023 13:25:30 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10866"; a="900040438" X-IronPort-AV: E=Sophos;i="6.03,233,1694761200"; d="scan'208";a="900040438" Received: from rtdinh-mobl1.amr.corp.intel.com (HELO rpedgeco-desk4.intel.com) ([10.212.150.155]) by fmsmga001-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Oct 2023 13:23:27 -0700 From: Rick Edgecombe To: x86@kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, hpa@zytor.com, luto@kernel.org, peterz@infradead.org, kirill.shutemov@linux.intel.com, elena.reshetova@intel.com, isaku.yamahata@intel.com, seanjc@google.com, Michael Kelley , thomas.lendacky@amd.com, decui@microsoft.com, sathyanarayanan.kuppuswamy@linux.intel.com, linux-mm@kvack.org, linux-kernel@vger.kernel.org, linux-s390@vger.kernel.org Cc: rick.p.edgecombe@intel.com Subject: [PATCH 02/10] x86/mm/cpa: Reject incorrect encryption change requests Date: Tue, 17 Oct 2023 13:24:57 -0700 Message-Id: <20231017202505.340906-3-rick.p.edgecombe@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231017202505.340906-1-rick.p.edgecombe@intel.com> References: <20231017202505.340906-1-rick.p.edgecombe@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Kernel memory is "encrypted" by default. Some callers may "decrypt" it in order to share it with things outside the kernel like a device or an untrusted VMM. There is nothing to stop set_memory_encrypted() from being passed memory that is already "encrypted" (aka. "private" on TDX). In fact, some callers do this because ... $REASONS. Unfortunately, part of the TDX decrypted=3D>encrypted transition is truly one way*. It can't handle being asked to encrypt an already encrypted page Allow __set_memory_enc_pgtable() to detect already-encrypted memory before it hits the TDX code. * The one way part is "page acceptance" [commit log written by Dave Hansen] Signed-off-by: Rick Edgecombe --- arch/x86/mm/pat/set_memory.c | 41 +++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c index bda9f129835e..1238b0db3e33 100644 --- a/arch/x86/mm/pat/set_memory.c +++ b/arch/x86/mm/pat/set_memory.c @@ -2122,6 +2122,21 @@ int set_memory_global(unsigned long addr, int numpag= es) __pgprot(_PAGE_GLOBAL), 0); } =20 +static bool kernel_vaddr_encryped(unsigned long addr, bool enc) +{ + unsigned int level; + pte_t *pte; + + pte =3D lookup_address(addr, &level); + if (!pte) + return false; + + if (enc) + return pte_val(*pte) =3D=3D cc_mkenc(pte_val(*pte)); + + return pte_val(*pte) =3D=3D cc_mkdec(pte_val(*pte)); +} + /* * __set_memory_enc_pgtable() is used for the hypervisors that get * informed about "encryption" status via page tables. @@ -2130,7 +2145,7 @@ static int __set_memory_enc_pgtable(unsigned long add= r, int numpages, bool enc) { pgprot_t empty =3D __pgprot(0); struct cpa_data cpa; - int ret; + int ret, numpages_in_state =3D 0; =20 /* Should not be working on unaligned addresses */ if (WARN_ONCE(addr & ~PAGE_MASK, "misaligned address: %#lx\n", addr)) @@ -2143,6 +2158,30 @@ static int __set_memory_enc_pgtable(unsigned long ad= dr, int numpages, bool enc) cpa.mask_clr =3D enc ? pgprot_decrypted(empty) : pgprot_encrypted(empty); cpa.pgd =3D init_mm.pgd; =20 + /* + * If any page is already in the right state, bail with an error + * because the code doesn't handled it. This is likely because + * something has gone wrong and isn't worth optimizing for. + * + * If all the memory pages are already in the desired state return + * success. + * + * kernel_vaddr_encryped() does not synchronize against huge page + * splits so take pgd_lock. A caller doing strange things could + * get a new PMD mid level PTE confused with a huge PMD entry. Just + * lock to tie up loose ends. + */ + spin_lock(&pgd_lock); + for (int i =3D 0; i < numpages; i++) { + if (kernel_vaddr_encryped(addr + (PAGE_SIZE * i), enc)) + numpages_in_state++; + } + spin_unlock(&pgd_lock); + if (numpages_in_state =3D=3D numpages) + return 0; + else if (numpages_in_state) + return 1; + /* Must avoid aliasing mappings in the highmem code */ kmap_flush_unused(); vm_unmap_aliases(); --=20 2.34.1