mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 04:34:08 +08:00
arm64: head: move dynamic shadow call stack patching into early C runtime
Once we update the early kernel mapping code to only map the kernel once with the right permissions, we can no longer perform code patching via this mapping. So move this code to an earlier stage of the boot, right after applying the relocations. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Link: https://lore.kernel.org/r/20240214122845.2033971-54-ardb+git@google.com Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
This commit is contained in:
parent
dcfe969a64
commit
8a6e40e1f6
@ -72,8 +72,8 @@ static inline void dynamic_scs_init(void)
|
||||
static inline void dynamic_scs_init(void) {}
|
||||
#endif
|
||||
|
||||
int scs_patch(const u8 eh_frame[], int size);
|
||||
asmlinkage void scs_patch_vmlinux(void);
|
||||
int __pi_scs_patch(const u8 eh_frame[], int size);
|
||||
asmlinkage void __pi_scs_patch_vmlinux(void);
|
||||
|
||||
#endif /* __ASSEMBLY __ */
|
||||
|
||||
|
@ -71,14 +71,6 @@ obj-$(CONFIG_ARM64_PTR_AUTH) += pointer_auth.o
|
||||
obj-$(CONFIG_ARM64_MTE) += mte.o
|
||||
obj-y += vdso-wrap.o
|
||||
obj-$(CONFIG_COMPAT_VDSO) += vdso32-wrap.o
|
||||
obj-$(CONFIG_UNWIND_PATCH_PAC_INTO_SCS) += patch-scs.o
|
||||
|
||||
# We need to prevent the SCS patching code from patching itself. Using
|
||||
# -mbranch-protection=none here to avoid the patchable PAC opcodes from being
|
||||
# generated triggers an issue with full LTO on Clang, which stops emitting PAC
|
||||
# instructions altogether. So disable LTO as well for the compilation unit.
|
||||
CFLAGS_patch-scs.o += -mbranch-protection=none
|
||||
CFLAGS_REMOVE_patch-scs.o += $(CC_FLAGS_LTO)
|
||||
|
||||
# Force dependency (vdso*-wrap.S includes vdso.so through incbin)
|
||||
$(obj)/vdso-wrap.o: $(obj)/vdso/vdso.so
|
||||
|
@ -490,9 +490,6 @@ SYM_FUNC_START_LOCAL(__primary_switched)
|
||||
#endif
|
||||
#if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS)
|
||||
bl kasan_early_init
|
||||
#endif
|
||||
#ifdef CONFIG_UNWIND_PATCH_PAC_INTO_SCS
|
||||
bl scs_patch_vmlinux
|
||||
#endif
|
||||
mov x0, x20
|
||||
bl finalise_el2 // Prefer VHE if possible
|
||||
@ -794,6 +791,11 @@ SYM_FUNC_START_LOCAL(__primary_switch)
|
||||
#ifdef CONFIG_RELOCATABLE
|
||||
mov x0, x23
|
||||
bl __pi_relocate_kernel
|
||||
#endif
|
||||
#ifdef CONFIG_UNWIND_PATCH_PAC_INTO_SCS
|
||||
ldr x0, =__eh_frame_start
|
||||
ldr x1, =__eh_frame_end
|
||||
bl __pi_scs_patch_vmlinux
|
||||
#endif
|
||||
ldr x8, =__primary_switched
|
||||
adrp x0, KERNEL_START // __pa(KERNEL_START)
|
||||
|
@ -595,7 +595,7 @@ int module_finalize(const Elf_Ehdr *hdr,
|
||||
if (scs_is_dynamic()) {
|
||||
s = find_section(hdr, sechdrs, ".init.eh_frame");
|
||||
if (s)
|
||||
scs_patch((void *)s->sh_addr, s->sh_size);
|
||||
__pi_scs_patch((void *)s->sh_addr, s->sh_size);
|
||||
}
|
||||
|
||||
return module_init_ftrace_plt(hdr, sechdrs, me);
|
||||
|
@ -38,7 +38,9 @@ $(obj)/lib-%.pi.o: OBJCOPYFLAGS += --prefix-alloc-sections=.init
|
||||
$(obj)/lib-%.o: $(srctree)/lib/%.c FORCE
|
||||
$(call if_changed_rule,cc_o_c)
|
||||
|
||||
obj-y := idreg-override.pi.o lib-fdt.pi.o lib-fdt_ro.pi.o
|
||||
obj-$(CONFIG_RELOCATABLE) += relocate.pi.o
|
||||
obj-$(CONFIG_RANDOMIZE_BASE) += kaslr_early.pi.o
|
||||
extra-y := $(patsubst %.pi.o,%.o,$(obj-y))
|
||||
obj-y := idreg-override.pi.o \
|
||||
lib-fdt.pi.o lib-fdt_ro.pi.o
|
||||
obj-$(CONFIG_RELOCATABLE) += relocate.pi.o
|
||||
obj-$(CONFIG_RANDOMIZE_BASE) += kaslr_early.pi.o
|
||||
obj-$(CONFIG_UNWIND_PATCH_PAC_INTO_SCS) += patch-scs.pi.o
|
||||
extra-y := $(patsubst %.pi.o,%.o,$(obj-y))
|
||||
|
@ -4,14 +4,11 @@
|
||||
* Author: Ard Biesheuvel <ardb@google.com>
|
||||
*/
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/scs.h>
|
||||
|
||||
//
|
||||
@ -81,7 +78,11 @@ static void __always_inline scs_patch_loc(u64 loc)
|
||||
*/
|
||||
return;
|
||||
}
|
||||
dcache_clean_pou(loc, loc + sizeof(u32));
|
||||
if (IS_ENABLED(CONFIG_ARM64_WORKAROUND_CLEAN_CACHE))
|
||||
asm("dc civac, %0" :: "r"(loc));
|
||||
else
|
||||
asm(ALTERNATIVE("dc cvau, %0", "nop", ARM64_HAS_CACHE_IDC)
|
||||
:: "r"(loc));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -128,10 +129,10 @@ struct eh_frame {
|
||||
};
|
||||
};
|
||||
|
||||
static int noinstr scs_handle_fde_frame(const struct eh_frame *frame,
|
||||
bool fde_has_augmentation_data,
|
||||
int code_alignment_factor,
|
||||
bool dry_run)
|
||||
static int scs_handle_fde_frame(const struct eh_frame *frame,
|
||||
bool fde_has_augmentation_data,
|
||||
int code_alignment_factor,
|
||||
bool dry_run)
|
||||
{
|
||||
int size = frame->size - offsetof(struct eh_frame, opcodes) + 4;
|
||||
u64 loc = (u64)offset_to_ptr(&frame->initial_loc);
|
||||
@ -198,14 +199,13 @@ static int noinstr scs_handle_fde_frame(const struct eh_frame *frame,
|
||||
break;
|
||||
|
||||
default:
|
||||
pr_err("unhandled opcode: %02x in FDE frame %lx\n", opcode[-1], (uintptr_t)frame);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int noinstr scs_patch(const u8 eh_frame[], int size)
|
||||
int scs_patch(const u8 eh_frame[], int size)
|
||||
{
|
||||
const u8 *p = eh_frame;
|
||||
|
||||
@ -251,12 +251,12 @@ int noinstr scs_patch(const u8 eh_frame[], int size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
asmlinkage void __init scs_patch_vmlinux(void)
|
||||
asmlinkage void __init scs_patch_vmlinux(const u8 start[], const u8 end[])
|
||||
{
|
||||
if (!should_patch_pac_into_scs())
|
||||
return;
|
||||
|
||||
WARN_ON(scs_patch(__eh_frame_start, __eh_frame_end - __eh_frame_start));
|
||||
icache_inval_all_pou();
|
||||
scs_patch(start, end - start);
|
||||
asm("ic ialluis");
|
||||
isb();
|
||||
}
|
Loading…
Reference in New Issue
Block a user