All of lore.kernel.org
 help / color / mirror / Atom feed
From: Rick Edgecombe <rick.p.edgecombe@intel.com>
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 <mikelley@microsoft.com>,
	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	[thread overview]
Message-ID: <20231017202505.340906-3-rick.p.edgecombe@intel.com> (raw)
In-Reply-To: <20231017202505.340906-1-rick.p.edgecombe@intel.com>

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=>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 <rick.p.edgecombe@intel.com>
---
 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 numpages)
 				    __pgprot(_PAGE_GLOBAL), 0);
 }
 
+static bool kernel_vaddr_encryped(unsigned long addr, bool enc)
+{
+	unsigned int level;
+	pte_t *pte;
+
+	pte = lookup_address(addr, &level);
+	if (!pte)
+		return false;
+
+	if (enc)
+		return pte_val(*pte) == cc_mkenc(pte_val(*pte));
+
+	return pte_val(*pte) == 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 addr, int numpages, bool enc)
 {
 	pgprot_t empty = __pgprot(0);
 	struct cpa_data cpa;
-	int ret;
+	int ret, numpages_in_state = 0;
 
 	/* 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 addr, int numpages, bool enc)
 	cpa.mask_clr = enc ? pgprot_decrypted(empty) : pgprot_encrypted(empty);
 	cpa.pgd = init_mm.pgd;
 
+	/*
+	 * 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 = 0; i < numpages; i++) {
+		if (kernel_vaddr_encryped(addr + (PAGE_SIZE * i), enc))
+			numpages_in_state++;
+	}
+	spin_unlock(&pgd_lock);
+	if (numpages_in_state == numpages)
+		return 0;
+	else if (numpages_in_state)
+		return 1;
+
 	/* Must avoid aliasing mappings in the highmem code */
 	kmap_flush_unused();
 	vm_unmap_aliases();
-- 
2.34.1


  parent reply	other threads:[~2023-10-17 20:25 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-17 20:24 [PATCH 00/10] Handle set_memory_XXcrypted() errors Rick Edgecombe
2023-10-17 20:24 ` [PATCH 01/10] mm: Add helper for freeing decrypted memory Rick Edgecombe
2023-10-17 20:24 ` Rick Edgecombe [this message]
2023-10-18  8:44   ` [PATCH 02/10] x86/mm/cpa: Reject incorrect encryption change requests Ingo Molnar
2023-10-18 15:53     ` Edgecombe, Rick P
2023-10-17 20:24 ` [PATCH 03/10] kvmclock: Use free_decrypted_pages() Rick Edgecombe
2023-10-18  5:20   ` Kuppuswamy Sathyanarayanan
2023-10-18 15:57     ` Edgecombe, Rick P
2023-10-17 20:24 ` [PATCH 04/10] swiotlb: " Rick Edgecombe
2023-10-18  4:43   ` Christoph Hellwig
2023-10-18 15:55     ` Edgecombe, Rick P
2023-10-31 10:43   ` Petr Tesařík
2023-10-31 15:54     ` Edgecombe, Rick P
2023-10-31 17:13       ` Petr Tesařík
2023-10-31 17:29         ` Edgecombe, Rick P
2023-11-01  6:27           ` Petr Tesařík
2023-11-01 14:40             ` Edgecombe, Rick P
2023-10-17 20:25 ` [PATCH 05/10] ptp: " Rick Edgecombe
2023-10-17 20:25 ` [PATCH 06/10] dma: " Rick Edgecombe
2023-10-18  6:24   ` Christoph Hellwig
2023-10-18 17:09     ` Edgecombe, Rick P
2023-10-18 17:42   ` Robin Murphy
2023-10-23 16:46     ` Edgecombe, Rick P
2023-10-23 17:22       ` Robin Murphy
2023-10-23 17:27         ` Edgecombe, Rick P
2023-10-17 20:25 ` [RFC 07/10] hv: " Rick Edgecombe
2023-10-17 20:25 ` [RFC 08/10] hv: Track decrypted status in vmbus_gpadl Rick Edgecombe
2023-10-17 20:25 ` [RFC 09/10] hv_nstvsc: Don't free decrypted memory Rick Edgecombe
2023-10-17 20:25 ` [RFC 10/10] uio_hv_generic: " Rick Edgecombe
2023-10-19 17:05 ` [PATCH 00/10] Handle set_memory_XXcrypted() errors Michael Kelley (LINUX)
2023-10-19 19:13   ` Dave Hansen
2023-10-23 16:47     ` Michael Kelley (LINUX)
2023-10-23 16:57       ` Dave Hansen
2023-10-23 17:01       ` Edgecombe, Rick P

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20231017202505.340906-3-rick.p.edgecombe@intel.com \
    --to=rick.p.edgecombe@intel.com \
    --cc=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=decui@microsoft.com \
    --cc=elena.reshetova@intel.com \
    --cc=hpa@zytor.com \
    --cc=isaku.yamahata@intel.com \
    --cc=kirill.shutemov@linux.intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=mikelley@microsoft.com \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=sathyanarayanan.kuppuswamy@linux.intel.com \
    --cc=seanjc@google.com \
    --cc=tglx@linutronix.de \
    --cc=thomas.lendacky@amd.com \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.