Re: [RFC PATCH 9/9] arm64: implement dynamic shadow call stack for GCC
From: Dan Li <hidden>
Date: 2021-10-13 22:38:02
Also in:
linux-hardening
On 10/13/21 11:22 PM, Ard Biesheuvel wrote:
quoted hunk ↗ jump to hunk
Implement support for the shadow call stack on GCC, and in a dynamic manner, by parsing the unwind tables at init time to locate all occurrences of PACIASP/AUTIASP, and replacing them with the shadow call stack push and pop instructions, respectively. This is useful because the overhead of the shadow call stack is difficult to justify on hardware that implements pointer authentication (PAC), and given that the PAC instructions are executed as NOPs on hardware that doesn't, we can just replace them. This patch only implements this for the core kernel, but the logic can be reused for modules without much trouble. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> --- Makefile | 4 +- arch/Kconfig | 4 +- arch/arm64/Kconfig | 8 +- arch/arm64/kernel/Makefile | 2 + arch/arm64/kernel/head.S | 3 + arch/arm64/kernel/patch-scs.c | 223 ++++++++++++++++++++ 6 files changed, 239 insertions(+), 5 deletions(-)diff --git a/Makefile b/Makefile index 7cfe4ff36f44..2d94fed93d9d 100644 --- a/Makefile +++ b/Makefile@@ -933,8 +933,8 @@ LDFLAGS_vmlinux += --gc-sections endif ifdef CONFIG_SHADOW_CALL_STACK -CC_FLAGS_SCS := -fsanitize=shadow-call-stack -KBUILD_CFLAGS += $(CC_FLAGS_SCS) +CC_FLAGS_SCS-$(CONFIG_CC_IS_CLANG) := -fsanitize=shadow-call-stack +KBUILD_CFLAGS += $(CC_FLAGS_SCS-y) export CC_FLAGS_SCS endifdiff --git a/arch/arm64/kernel/patch-scs.c b/arch/arm64/kernel/patch-scs.c new file mode 100644 index 000000000000..878a40060550 --- /dev/null +++ b/arch/arm64/kernel/patch-scs.c +static int scs_patch_loc(u64 loc) +{ + u32 insn = le32_to_cpup((void *)loc); + + /* + * Sometimes, the unwind data appears to be out of sync, and associates + * the DW_CFA_negate_ra_state directive with the ret instruction + * following the autiasp, rather than the autiasp itself. + */ + if (insn == 0xd65f03c0) { // ret + loc -= 4; + insn = le32_to_cpup((void *)loc); + } + + switch (insn) { + case 0xd503233f: // paciasp + *(u32 *)loc = cpu_to_le32(0xf800865e); + break; + case 0xd50323bf: // autiasp + *(u32 *)loc = cpu_to_le32(0xf85f8e5e); + break; + default: + // ignore + break; + } + return 0; +}
Hi Ard, According to my understanding (may be wrong), here may need to filter out '-march=armv8.3-a'. When it is specified, gcc will use 'retaa' instead of 'autiasp' as a pac check. _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel