Skip to content

Commit cd0d9d9

Browse files
ardbiesheuvelbp3tk0v
authored andcommitted
x86/boot: Move mem_encrypt= parsing to the decompressor
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 new xloadflag in the setup header to indicate that mem_encrypt=on appeared on the kernel command line. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Tested-by: Tom Lendacky <thomas.lendacky@amd.com> Link: https://lore.kernel.org/r/20240227151907.387873-17-ardb+git@google.com
1 parent 7205f06 commit cd0d9d9

File tree

5 files changed

+22
-42
lines changed

5 files changed

+22
-42
lines changed

arch/x86/boot/compressed/misc.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,19 @@ unsigned long decompress_kernel(unsigned char *outbuf, unsigned long virt_addr,
371371
return entry;
372372
}
373373

374+
/*
375+
* Set the memory encryption xloadflag based on the mem_encrypt= command line
376+
* parameter, if provided.
377+
*/
378+
static void parse_mem_encrypt(struct setup_header *hdr)
379+
{
380+
int on = cmdline_find_option_bool("mem_encrypt=on");
381+
int off = cmdline_find_option_bool("mem_encrypt=off");
382+
383+
if (on > off)
384+
hdr->xloadflags |= XLF_MEM_ENCRYPTION;
385+
}
386+
374387
/*
375388
* The compressed kernel image (ZO), has been moved so that its position
376389
* is against the end of the buffer used to hold the uncompressed kernel
@@ -401,6 +414,8 @@ asmlinkage __visible void *extract_kernel(void *rmode, unsigned char *output)
401414
/* Clear flags intended for solely in-kernel use. */
402415
boot_params_ptr->hdr.loadflags &= ~KASLR_FLAG;
403416

417+
parse_mem_encrypt(&boot_params_ptr->hdr);
418+
404419
sanitize_boot_params(boot_params_ptr);
405420

406421
if (boot_params_ptr->screen_info.orig_video_mode == 7) {

arch/x86/include/uapi/asm/bootparam.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#define XLF_EFI_KEXEC (1<<4)
3939
#define XLF_5LEVEL (1<<5)
4040
#define XLF_5LEVEL_ENABLED (1<<6)
41+
#define XLF_MEM_ENCRYPTION (1<<7)
4142

4243
#ifndef __ASSEMBLY__
4344

arch/x86/lib/Makefile

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,6 @@ ifdef CONFIG_KCSAN
1414
CFLAGS_REMOVE_delay.o = $(CC_FLAGS_FTRACE)
1515
endif
1616

17-
# Early boot use of cmdline; don't instrument it
18-
ifdef CONFIG_AMD_MEM_ENCRYPT
19-
KCOV_INSTRUMENT_cmdline.o := n
20-
KASAN_SANITIZE_cmdline.o := n
21-
KCSAN_SANITIZE_cmdline.o := n
22-
23-
ifdef CONFIG_FUNCTION_TRACER
24-
CFLAGS_REMOVE_cmdline.o = -pg
25-
endif
26-
27-
CFLAGS_cmdline.o := -fno-stack-protector -fno-jump-tables
28-
endif
29-
3017
inat_tables_script = $(srctree)/arch/x86/tools/gen-insn-attr-x86.awk
3118
inat_tables_maps = $(srctree)/arch/x86/lib/x86-opcode-map.txt
3219
quiet_cmd_inat_tables = GEN $@

arch/x86/mm/mem_encrypt_identity.c

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343

4444
#include <asm/setup.h>
4545
#include <asm/sections.h>
46-
#include <asm/cmdline.h>
4746
#include <asm/coco.h>
4847
#include <asm/sev.h>
4948

@@ -95,9 +94,6 @@ struct sme_populate_pgd_data {
9594
*/
9695
static char sme_workarea[2 * PMD_SIZE] __section(".init.scratch");
9796

98-
static char sme_cmdline_arg[] __initdata = "mem_encrypt";
99-
static char sme_cmdline_on[] __initdata = "on";
100-
10197
static void __init sme_clear_pgd(struct sme_populate_pgd_data *ppd)
10298
{
10399
unsigned long pgd_start, pgd_end, pgd_size;
@@ -504,11 +500,9 @@ void __init sme_encrypt_kernel(struct boot_params *bp)
504500

505501
void __init sme_enable(struct boot_params *bp)
506502
{
507-
const char *cmdline_ptr, *cmdline_arg, *cmdline_on;
508503
unsigned int eax, ebx, ecx, edx;
509504
unsigned long feature_mask;
510505
unsigned long me_mask;
511-
char buffer[16];
512506
bool snp;
513507
u64 msr;
514508

@@ -551,6 +545,9 @@ void __init sme_enable(struct boot_params *bp)
551545

552546
/* Check if memory encryption is enabled */
553547
if (feature_mask == AMD_SME_BIT) {
548+
if (!(bp->hdr.xloadflags & XLF_MEM_ENCRYPTION))
549+
return;
550+
554551
/*
555552
* No SME if Hypervisor bit is set. This check is here to
556553
* prevent a guest from trying to enable SME. For running as a
@@ -570,31 +567,8 @@ void __init sme_enable(struct boot_params *bp)
570567
msr = __rdmsr(MSR_AMD64_SYSCFG);
571568
if (!(msr & MSR_AMD64_SYSCFG_MEM_ENCRYPT))
572569
return;
573-
} else {
574-
/* SEV state cannot be controlled by a command line option */
575-
goto out;
576570
}
577571

578-
/*
579-
* Fixups have not been applied to phys_base yet and we're running
580-
* identity mapped, so we must obtain the address to the SME command
581-
* line argument data using rip-relative addressing.
582-
*/
583-
asm ("lea sme_cmdline_arg(%%rip), %0"
584-
: "=r" (cmdline_arg)
585-
: "p" (sme_cmdline_arg));
586-
asm ("lea sme_cmdline_on(%%rip), %0"
587-
: "=r" (cmdline_on)
588-
: "p" (sme_cmdline_on));
589-
590-
cmdline_ptr = (const char *)((u64)bp->hdr.cmd_line_ptr |
591-
((u64)bp->ext_cmd_line_ptr << 32));
592-
593-
if (cmdline_find_option(cmdline_ptr, cmdline_arg, buffer, sizeof(buffer)) < 0 ||
594-
strncmp(buffer, cmdline_on, sizeof(buffer)))
595-
return;
596-
597-
out:
598572
RIP_REL_REF(sme_me_mask) = me_mask;
599573
physical_mask &= ~me_mask;
600574
cc_vendor = CC_VENDOR_AMD;

drivers/firmware/efi/libstub/x86-stub.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,9 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
884884
}
885885
}
886886

887+
if (efi_mem_encrypt > 0)
888+
hdr->xloadflags |= XLF_MEM_ENCRYPTION;
889+
887890
status = efi_decompress_kernel(&kernel_entry);
888891
if (status != EFI_SUCCESS) {
889892
efi_err("Failed to decompress kernel\n");

0 commit comments

Comments
 (0)