Thread (16 messages) 16 messages, 4 authors, 2021-10-14

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
  endif
  
diff --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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help