mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-12-20 01:28:06 +01:00
x86/boot: Create a confined code area for startup code
In order to be able to have tight control over which code may execute from the early 1:1 mapping of memory, but still link vmlinux as a single executable, prefix all symbol references in startup code with __pi_, and invoke it from outside using the __pi_ prefix. Use objtool to check that no absolute symbol references are present in the startup code, as these cannot be used from code running from the 1:1 mapping. Note that this also requires disabling the latent-entropy GCC plugin, as the global symbol references that it injects would require explicit exports, and given that the startup code rarely executes more than once, it is not a useful source of entropy anyway. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Link: https://lore.kernel.org/20250828102202.1849035-43-ardb+git@google.com
This commit is contained in:
parent
749627c398
commit
7b38dec3c5
|
|
@ -4,6 +4,7 @@ KBUILD_AFLAGS += -D__DISABLE_EXPORTS
|
||||||
KBUILD_CFLAGS += -D__DISABLE_EXPORTS -mcmodel=small -fPIC \
|
KBUILD_CFLAGS += -D__DISABLE_EXPORTS -mcmodel=small -fPIC \
|
||||||
-Os -DDISABLE_BRANCH_PROFILING \
|
-Os -DDISABLE_BRANCH_PROFILING \
|
||||||
$(DISABLE_STACKLEAK_PLUGIN) \
|
$(DISABLE_STACKLEAK_PLUGIN) \
|
||||||
|
$(DISABLE_LATENT_ENTROPY_PLUGIN) \
|
||||||
-fno-stack-protector -D__NO_FORTIFY \
|
-fno-stack-protector -D__NO_FORTIFY \
|
||||||
-fno-jump-tables \
|
-fno-jump-tables \
|
||||||
-include $(srctree)/include/linux/hidden.h
|
-include $(srctree)/include/linux/hidden.h
|
||||||
|
|
@ -36,3 +37,16 @@ $(patsubst %.o,$(obj)/%.o,$(lib-y)): OBJECT_FILES_NON_STANDARD := y
|
||||||
#
|
#
|
||||||
$(pi-objs): objtool-enabled = 1
|
$(pi-objs): objtool-enabled = 1
|
||||||
$(pi-objs): objtool-args = $(if $(delay-objtool),,$(objtool-args-y)) --noabs
|
$(pi-objs): objtool-args = $(if $(delay-objtool),,$(objtool-args-y)) --noabs
|
||||||
|
|
||||||
|
#
|
||||||
|
# Confine the startup code by prefixing all symbols with __pi_ (for position
|
||||||
|
# independent). This ensures that startup code can only call other startup
|
||||||
|
# code, or code that has explicitly been made accessible to it via a symbol
|
||||||
|
# alias.
|
||||||
|
#
|
||||||
|
$(obj)/%.pi.o: OBJCOPYFLAGS := --prefix-symbols=__pi_
|
||||||
|
$(obj)/%.pi.o: $(obj)/%.o FORCE
|
||||||
|
$(call if_changed,objcopy)
|
||||||
|
|
||||||
|
targets += $(obj-y)
|
||||||
|
obj-y := $(patsubst %.o,%.pi.o,$(obj-y))
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@
|
||||||
#include <asm/setup_data.h>
|
#include <asm/setup_data.h>
|
||||||
|
|
||||||
#ifndef __BOOT_COMPRESSED
|
#ifndef __BOOT_COMPRESSED
|
||||||
#define error(v) pr_err(v)
|
|
||||||
#define has_cpuflag(f) boot_cpu_has(f)
|
#define has_cpuflag(f) boot_cpu_has(f)
|
||||||
#else
|
#else
|
||||||
#undef WARN
|
#undef WARN
|
||||||
|
|
|
||||||
|
|
@ -568,7 +568,6 @@ void __head sme_enable(struct boot_params *bp)
|
||||||
|
|
||||||
#ifdef CONFIG_MITIGATION_PAGE_TABLE_ISOLATION
|
#ifdef CONFIG_MITIGATION_PAGE_TABLE_ISOLATION
|
||||||
/* Local version for startup code, which never operates on user page tables */
|
/* Local version for startup code, which never operates on user page tables */
|
||||||
__weak
|
|
||||||
pgd_t __pti_set_user_pgtbl(pgd_t *pgdp, pgd_t pgd)
|
pgd_t __pti_set_user_pgtbl(pgd_t *pgdp, pgd_t pgd)
|
||||||
{
|
{
|
||||||
return pgd;
|
return pgd;
|
||||||
|
|
|
||||||
|
|
@ -272,7 +272,7 @@ static int svsm_perform_call_protocol(struct svsm_call *call)
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ret = ghcb ? svsm_perform_ghcb_protocol(ghcb, call)
|
ret = ghcb ? svsm_perform_ghcb_protocol(ghcb, call)
|
||||||
: svsm_perform_msr_protocol(call);
|
: __pi_svsm_perform_msr_protocol(call);
|
||||||
} while (ret == -EAGAIN);
|
} while (ret == -EAGAIN);
|
||||||
|
|
||||||
if (sev_cfg.ghcbs_initialized)
|
if (sev_cfg.ghcbs_initialized)
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ extern void i386_reserve_resources(void);
|
||||||
extern unsigned long __startup_64(unsigned long p2v_offset, struct boot_params *bp);
|
extern unsigned long __startup_64(unsigned long p2v_offset, struct boot_params *bp);
|
||||||
extern void startup_64_setup_gdt_idt(void);
|
extern void startup_64_setup_gdt_idt(void);
|
||||||
extern void startup_64_load_idt(void *vc_handler);
|
extern void startup_64_load_idt(void *vc_handler);
|
||||||
|
extern void __pi_startup_64_load_idt(void *vc_handler);
|
||||||
extern void early_setup_idt(void);
|
extern void early_setup_idt(void);
|
||||||
extern void __init do_early_exception(struct pt_regs *regs, int trapnr);
|
extern void __init do_early_exception(struct pt_regs *regs, int trapnr);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -551,6 +551,7 @@ struct cpuid_leaf {
|
||||||
};
|
};
|
||||||
|
|
||||||
int svsm_perform_msr_protocol(struct svsm_call *call);
|
int svsm_perform_msr_protocol(struct svsm_call *call);
|
||||||
|
int __pi_svsm_perform_msr_protocol(struct svsm_call *call);
|
||||||
int snp_cpuid(void (*cpuid_fn)(void *ctx, struct cpuid_leaf *leaf),
|
int snp_cpuid(void (*cpuid_fn)(void *ctx, struct cpuid_leaf *leaf),
|
||||||
void *ctx, struct cpuid_leaf *leaf);
|
void *ctx, struct cpuid_leaf *leaf);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -319,5 +319,5 @@ void early_setup_idt(void)
|
||||||
handler = vc_boot_ghcb;
|
handler = vc_boot_ghcb;
|
||||||
}
|
}
|
||||||
|
|
||||||
startup_64_load_idt(handler);
|
__pi_startup_64_load_idt(handler);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ SYM_CODE_START_NOALIGN(startup_64)
|
||||||
xorl %edx, %edx
|
xorl %edx, %edx
|
||||||
wrmsr
|
wrmsr
|
||||||
|
|
||||||
call startup_64_setup_gdt_idt
|
call __pi_startup_64_setup_gdt_idt
|
||||||
|
|
||||||
/* Now switch to __KERNEL_CS so IRET works reliably */
|
/* Now switch to __KERNEL_CS so IRET works reliably */
|
||||||
pushq $__KERNEL_CS
|
pushq $__KERNEL_CS
|
||||||
|
|
@ -91,7 +91,7 @@ SYM_CODE_START_NOALIGN(startup_64)
|
||||||
* subsequent code. Pass the boot_params pointer as the first argument.
|
* subsequent code. Pass the boot_params pointer as the first argument.
|
||||||
*/
|
*/
|
||||||
movq %r15, %rdi
|
movq %r15, %rdi
|
||||||
call sme_enable
|
call __pi_sme_enable
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Sanitize CPU configuration */
|
/* Sanitize CPU configuration */
|
||||||
|
|
@ -111,7 +111,7 @@ SYM_CODE_START_NOALIGN(startup_64)
|
||||||
* programmed into CR3.
|
* programmed into CR3.
|
||||||
*/
|
*/
|
||||||
movq %r15, %rsi
|
movq %r15, %rsi
|
||||||
call __startup_64
|
call __pi___startup_64
|
||||||
|
|
||||||
/* Form the CR3 value being sure to include the CR3 modifier */
|
/* Form the CR3 value being sure to include the CR3 modifier */
|
||||||
leaq early_top_pgt(%rip), %rcx
|
leaq early_top_pgt(%rip), %rcx
|
||||||
|
|
@ -562,7 +562,7 @@ SYM_CODE_START_NOALIGN(vc_no_ghcb)
|
||||||
/* Call C handler */
|
/* Call C handler */
|
||||||
movq %rsp, %rdi
|
movq %rsp, %rdi
|
||||||
movq ORIG_RAX(%rsp), %rsi
|
movq ORIG_RAX(%rsp), %rsi
|
||||||
call do_vc_no_ghcb
|
call __pi_do_vc_no_ghcb
|
||||||
|
|
||||||
/* Unwind pt_regs */
|
/* Unwind pt_regs */
|
||||||
POP_REGS
|
POP_REGS
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
.text
|
.text
|
||||||
.code64
|
.code64
|
||||||
SYM_FUNC_START(sme_encrypt_execute)
|
SYM_FUNC_START(__pi_sme_encrypt_execute)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Entry parameters:
|
* Entry parameters:
|
||||||
|
|
@ -69,9 +69,9 @@ SYM_FUNC_START(sme_encrypt_execute)
|
||||||
ANNOTATE_UNRET_SAFE
|
ANNOTATE_UNRET_SAFE
|
||||||
ret
|
ret
|
||||||
int3
|
int3
|
||||||
SYM_FUNC_END(sme_encrypt_execute)
|
SYM_FUNC_END(__pi_sme_encrypt_execute)
|
||||||
|
|
||||||
SYM_FUNC_START(__enc_copy)
|
SYM_FUNC_START_LOCAL(__enc_copy)
|
||||||
ANNOTATE_NOENDBR
|
ANNOTATE_NOENDBR
|
||||||
/*
|
/*
|
||||||
* Routine used to encrypt memory in place.
|
* Routine used to encrypt memory in place.
|
||||||
|
|
|
||||||
|
|
@ -3564,7 +3564,8 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
|
||||||
if (func && insn_func(insn) && func != insn_func(insn)->pfunc) {
|
if (func && insn_func(insn) && func != insn_func(insn)->pfunc) {
|
||||||
/* Ignore KCFI type preambles, which always fall through */
|
/* Ignore KCFI type preambles, which always fall through */
|
||||||
if (!strncmp(func->name, "__cfi_", 6) ||
|
if (!strncmp(func->name, "__cfi_", 6) ||
|
||||||
!strncmp(func->name, "__pfx_", 6))
|
!strncmp(func->name, "__pfx_", 6) ||
|
||||||
|
!strncmp(func->name, "__pi___pfx_", 11))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (file->ignore_unreachables)
|
if (file->ignore_unreachables)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user