linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ard Biesheuvel <ardb+git@google.com>
To: linux-kernel@vger.kernel.org
Cc: Ard Biesheuvel <ardb@kernel.org>,
	Kevin Loughlin <kevinloughlin@google.com>,
	 Tom Lendacky <thomas.lendacky@amd.com>,
	Dionna Glaze <dionnaglaze@google.com>,
	 Thomas Gleixner <tglx@linutronix.de>,
	Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
	 Dave Hansen <dave.hansen@linux.intel.com>,
	Andy Lutomirski <luto@kernel.org>,  Arnd Bergmann <arnd@arndb.de>,
	Nathan Chancellor <nathan@kernel.org>,
	 Nick Desaulniers <ndesaulniers@google.com>,
	Justin Stitt <justinstitt@google.com>,
	 Kees Cook <keescook@chromium.org>,
	Brian Gerst <brgerst@gmail.com>,
	linux-arch@vger.kernel.org,  llvm@lists.linux.dev
Subject: [PATCH v3 02/19] x86/boot: Move mem_encrypt= parsing to the decompressor
Date: Mon, 29 Jan 2024 19:05:05 +0100	[thread overview]
Message-ID: <20240129180502.4069817-23-ardb+git@google.com> (raw)
In-Reply-To: <20240129180502.4069817-21-ardb+git@google.com>

From: Ard Biesheuvel <ardb@kernel.org>

The early SME/SEV code parses the command line very early, in order to
decide whether or not memory encryption should be enabled, which needs
to occur even before the initial page tables are created.

This is problematic for a number of reasons:
- this early code runs from the 1:1 mapping provided by the decompressor
  or firmware, which uses a different translation than the one assumed by
  the linker, and so the code needs to be built in a special way;
- parsing external input while the entire kernel image is still mapped
  writable is a bad idea in general, and really does not belong in
  security minded code;
- the current code ignores the built-in command line entirely (although
  this appears to be the case for the entire decompressor)

Given that the decompressor/EFI stub is an intrinsic part of the x86
bootable kernel image, move the command line parsing there and out of
the core kernel. This removes the need to build lib/cmdline.o in a
special way, or to use RIP-relative LEA instructions in inline asm
blocks.

This involves a pair of new xloadflags in the setup header to indicate
that a) mem_encrypt= was provided, and b) whether it was set to on or
off. What this actually means in terms of default behavior when the
command line parameter is omitted is left up to the existing logic -
this permits the same flags to be reused if the need arises.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/x86/boot/compressed/misc.c         | 22 ++++++++++
 arch/x86/include/uapi/asm/bootparam.h   |  2 +
 arch/x86/lib/Makefile                   | 13 ------
 arch/x86/mm/mem_encrypt_identity.c      | 45 +++-----------------
 drivers/firmware/efi/libstub/x86-stub.c |  6 +++
 5 files changed, 37 insertions(+), 51 deletions(-)

diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index b99e08e6815b..d63a2dc7d0b1 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -357,6 +357,26 @@ unsigned long decompress_kernel(unsigned char *outbuf, unsigned long virt_addr,
 	return entry;
 }
 
+/*
+ * Set the memory encryption xloadflag based on the mem_encrypt= command line
+ * parameter, if provided. If not, the consumer of the flag decides what the
+ * default behavior should be.
+ */
+static void set_mem_encrypt_flag(struct setup_header *hdr)
+{
+	hdr->xloadflags &= ~(XLF_MEM_ENCRYPTION | XLF_MEM_ENCRYPTION_ENABLED);
+
+	if (IS_ENABLED(CONFIG_ARCH_HAS_MEM_ENCRYPT)) {
+		int on = cmdline_find_option_bool("mem_encrypt=on");
+		int off = cmdline_find_option_bool("mem_encrypt=off");
+
+		if (on || off)
+			hdr->xloadflags |= XLF_MEM_ENCRYPTION;
+		if (on > off)
+			hdr->xloadflags |= XLF_MEM_ENCRYPTION_ENABLED;
+	}
+}
+
 /*
  * The compressed kernel image (ZO), has been moved so that its position
  * is against the end of the buffer used to hold the uncompressed kernel
@@ -387,6 +407,8 @@ asmlinkage __visible void *extract_kernel(void *rmode, unsigned char *output)
 	/* Clear flags intended for solely in-kernel use. */
 	boot_params_ptr->hdr.loadflags &= ~KASLR_FLAG;
 
+	set_mem_encrypt_flag(&boot_params_ptr->hdr);
+
 	sanitize_boot_params(boot_params_ptr);
 
 	if (boot_params_ptr->screen_info.orig_video_mode == 7) {
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
index 01d19fc22346..316784e17d38 100644
--- a/arch/x86/include/uapi/asm/bootparam.h
+++ b/arch/x86/include/uapi/asm/bootparam.h
@@ -38,6 +38,8 @@
 #define XLF_EFI_KEXEC			(1<<4)
 #define XLF_5LEVEL			(1<<5)
 #define XLF_5LEVEL_ENABLED		(1<<6)
+#define XLF_MEM_ENCRYPTION		(1<<7)
+#define XLF_MEM_ENCRYPTION_ENABLED	(1<<8)
 
 #ifndef __ASSEMBLY__
 
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index ea3a28e7b613..f0dae4fb6d07 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -14,19 +14,6 @@ ifdef CONFIG_KCSAN
 CFLAGS_REMOVE_delay.o = $(CC_FLAGS_FTRACE)
 endif
 
-# Early boot use of cmdline; don't instrument it
-ifdef CONFIG_AMD_MEM_ENCRYPT
-KCOV_INSTRUMENT_cmdline.o := n
-KASAN_SANITIZE_cmdline.o  := n
-KCSAN_SANITIZE_cmdline.o  := n
-
-ifdef CONFIG_FUNCTION_TRACER
-CFLAGS_REMOVE_cmdline.o = -pg
-endif
-
-CFLAGS_cmdline.o := -fno-stack-protector -fno-jump-tables
-endif
-
 inat_tables_script = $(srctree)/arch/x86/tools/gen-insn-attr-x86.awk
 inat_tables_maps = $(srctree)/arch/x86/lib/x86-opcode-map.txt
 quiet_cmd_inat_tables = GEN     $@
diff --git a/arch/x86/mm/mem_encrypt_identity.c b/arch/x86/mm/mem_encrypt_identity.c
index 7f72472a34d6..06466f6d5966 100644
--- a/arch/x86/mm/mem_encrypt_identity.c
+++ b/arch/x86/mm/mem_encrypt_identity.c
@@ -43,7 +43,6 @@
 
 #include <asm/setup.h>
 #include <asm/sections.h>
-#include <asm/cmdline.h>
 #include <asm/coco.h>
 #include <asm/sev.h>
 
@@ -95,10 +94,6 @@ struct sme_populate_pgd_data {
  */
 static char sme_workarea[2 * PMD_SIZE] __section(".init.scratch");
 
-static char sme_cmdline_arg[] __initdata = "mem_encrypt";
-static char sme_cmdline_on[]  __initdata = "on";
-static char sme_cmdline_off[] __initdata = "off";
-
 static void __init sme_clear_pgd(struct sme_populate_pgd_data *ppd)
 {
 	unsigned long pgd_start, pgd_end, pgd_size;
@@ -504,11 +499,9 @@ void __init sme_encrypt_kernel(struct boot_params *bp)
 
 void __init sme_enable(struct boot_params *bp)
 {
-	const char *cmdline_ptr, *cmdline_arg, *cmdline_on, *cmdline_off;
 	unsigned int eax, ebx, ecx, edx;
 	unsigned long feature_mask;
 	unsigned long me_mask;
-	char buffer[16];
 	bool snp;
 	u64 msr;
 
@@ -570,42 +563,18 @@ void __init sme_enable(struct boot_params *bp)
 		msr = __rdmsr(MSR_AMD64_SYSCFG);
 		if (!(msr & MSR_AMD64_SYSCFG_MEM_ENCRYPT))
 			return;
+
+		if (bp->hdr.xloadflags & XLF_MEM_ENCRYPTION) {
+			if (bp->hdr.xloadflags & XLF_MEM_ENCRYPTION_ENABLED)
+				sme_me_mask = me_mask;
+		} else if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT)) {
+			sme_me_mask = me_mask;
+		}
 	} else {
 		/* SEV state cannot be controlled by a command line option */
 		sme_me_mask = me_mask;
-		goto out;
 	}
 
-	/*
-	 * Fixups have not been applied to phys_base yet and we're running
-	 * identity mapped, so we must obtain the address to the SME command
-	 * line argument data using rip-relative addressing.
-	 */
-	asm ("lea sme_cmdline_arg(%%rip), %0"
-	     : "=r" (cmdline_arg)
-	     : "p" (sme_cmdline_arg));
-	asm ("lea sme_cmdline_on(%%rip), %0"
-	     : "=r" (cmdline_on)
-	     : "p" (sme_cmdline_on));
-	asm ("lea sme_cmdline_off(%%rip), %0"
-	     : "=r" (cmdline_off)
-	     : "p" (sme_cmdline_off));
-
-	if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT))
-		sme_me_mask = me_mask;
-
-	cmdline_ptr = (const char *)((u64)bp->hdr.cmd_line_ptr |
-				     ((u64)bp->ext_cmd_line_ptr << 32));
-
-	if (cmdline_find_option(cmdline_ptr, cmdline_arg, buffer, sizeof(buffer)) < 0)
-		goto out;
-
-	if (!strncmp(buffer, cmdline_on, sizeof(buffer)))
-		sme_me_mask = me_mask;
-	else if (!strncmp(buffer, cmdline_off, sizeof(buffer)))
-		sme_me_mask = 0;
-
-out:
 	if (sme_me_mask) {
 		physical_mask &= ~sme_me_mask;
 		cc_vendor = CC_VENDOR_AMD;
diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
index 0d510c9a06a4..66e336cca0cc 100644
--- a/drivers/firmware/efi/libstub/x86-stub.c
+++ b/drivers/firmware/efi/libstub/x86-stub.c
@@ -879,6 +879,12 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
 		}
 	}
 
+	if (IS_ENABLED(CONFIG_ARCH_HAS_MEM_ENCRYPT) && efi_mem_encrypt) {
+		hdr->xloadflags |= XLF_MEM_ENCRYPTION;
+		if (efi_mem_encrypt > 0)
+			hdr->xloadflags |= XLF_MEM_ENCRYPTION_ENABLED;
+	}
+
 	status = efi_decompress_kernel(&kernel_entry);
 	if (status != EFI_SUCCESS) {
 		efi_err("Failed to decompress kernel\n");
-- 
2.43.0.429.g432eaa2c6b-goog


  parent reply	other threads:[~2024-01-29 18:05 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-29 18:05 [PATCH v3 00/19] x86: Confine early 1:1 mapped startup code Ard Biesheuvel
2024-01-29 18:05 ` [PATCH v3 01/19] efi/libstub: Add generic support for parsing mem_encrypt= Ard Biesheuvel
2024-01-31  7:31   ` Borislav Petkov
2024-02-01 16:23     ` Kevin Loughlin
2024-02-01 16:28       ` Ard Biesheuvel
2024-01-29 18:05 ` Ard Biesheuvel [this message]
2024-01-31  8:35   ` [PATCH v3 02/19] x86/boot: Move mem_encrypt= parsing to the decompressor Borislav Petkov
2024-01-31  9:12     ` Ard Biesheuvel
2024-01-31  9:29       ` Borislav Petkov
2024-01-31  9:59         ` Ard Biesheuvel
2024-02-01 14:17         ` Tom Lendacky
2024-02-01 16:15           ` Ard Biesheuvel
2024-02-02 16:35             ` [PATCH] x86/Kconfig: Remove CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT Borislav Petkov
2024-02-02 16:47               ` Ard Biesheuvel
2024-02-03 10:50               ` [tip: x86/sev] " tip-bot2 for Borislav Petkov (AMD)
2024-01-29 18:05 ` [PATCH v3 03/19] x86/startup_64: Drop long return to initial_code pointer Ard Biesheuvel
2024-01-31 13:44   ` Borislav Petkov
2024-01-31 13:57     ` Ard Biesheuvel
2024-01-31 14:07       ` Ard Biesheuvel
2024-01-31 16:29         ` Borislav Petkov
2024-01-31 18:14   ` [tip: x86/boot] " tip-bot2 for Ard Biesheuvel
2024-01-29 18:05 ` [PATCH v3 04/19] x86/startup_64: Simplify calculation of initial page table address Ard Biesheuvel
2024-02-05 10:40   ` Borislav Petkov
2024-01-29 18:05 ` [PATCH v3 05/19] x86/startup_64: Simplify CR4 handling in startup code Ard Biesheuvel
2024-02-06 18:21   ` Borislav Petkov
2024-02-07 10:38     ` Ard Biesheuvel
2024-01-29 18:05 ` [PATCH v3 06/19] x86/startup_64: Drop global variables keeping track of LA57 state Ard Biesheuvel
2024-02-07 13:29   ` Borislav Petkov
2024-02-09 13:55     ` Ard Biesheuvel
2024-02-10 10:40       ` Borislav Petkov
2024-02-11 22:36         ` Ard Biesheuvel
2024-01-29 18:05 ` [PATCH v3 07/19] x86/startup_64: Simplify virtual switch on primary boot Ard Biesheuvel
2024-02-07 14:50   ` Borislav Petkov
2024-01-29 18:05 ` [PATCH v3 08/19] x86/head64: Replace pointer fixups with PIE codegen Ard Biesheuvel
2024-02-12 10:29   ` Borislav Petkov
2024-02-12 11:52     ` Ard Biesheuvel
2024-02-12 14:18       ` Borislav Petkov
2024-01-29 18:05 ` [PATCH v3 09/19] x86/head64: Simplify GDT/IDT initialization code Ard Biesheuvel
2024-02-12 14:37   ` Borislav Petkov
2024-02-12 15:23     ` Ard Biesheuvel
2024-01-29 18:05 ` [PATCH v3 10/19] asm-generic: Add special .pi.text section for position independent code Ard Biesheuvel
2024-01-29 18:05 ` [PATCH v3 11/19] x86: Move return_thunk to __pitext section Ard Biesheuvel
2024-01-29 18:05 ` [PATCH v3 12/19] x86/head64: Move early startup code into __pitext Ard Biesheuvel
2024-01-29 18:05 ` [PATCH v3 13/19] modpost: Warn about calls from __pitext into other text sections Ard Biesheuvel
2024-01-29 18:05 ` [PATCH v3 14/19] x86/coco: Make cc_set_mask() static inline Ard Biesheuvel
2024-01-30 23:16   ` Kevin Loughlin
2024-01-30 23:36     ` Ard Biesheuvel
2024-01-29 18:05 ` [PATCH v3 15/19] x86/sev: Make all code reachable from 1:1 mapping __pitext Ard Biesheuvel
2024-01-29 18:05 ` [PATCH v3 16/19] x86/sev: Avoid WARN() in early code Ard Biesheuvel
2024-01-29 18:05 ` [PATCH v3 17/19] x86/sev: Use PIC codegen for early SEV startup code Ard Biesheuvel
2024-01-29 18:05 ` [PATCH v3 18/19] x86/sev: Drop inline asm LEA instructions for RIP-relative references Ard Biesheuvel
2024-01-29 18:05 ` [PATCH v3 19/19] x86/startup_64: Don't bother setting up GS before the kernel is mapped Ard Biesheuvel

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=20240129180502.4069817-23-ardb+git@google.com \
    --to=ardb+git@google.com \
    --cc=ardb@kernel.org \
    --cc=arnd@arndb.de \
    --cc=bp@alien8.de \
    --cc=brgerst@gmail.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=dionnaglaze@google.com \
    --cc=justinstitt@google.com \
    --cc=keescook@chromium.org \
    --cc=kevinloughlin@google.com \
    --cc=linux-arch@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=llvm@lists.linux.dev \
    --cc=luto@kernel.org \
    --cc=mingo@redhat.com \
    --cc=nathan@kernel.org \
    --cc=ndesaulniers@google.com \
    --cc=tglx@linutronix.de \
    --cc=thomas.lendacky@amd.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).