From 11d3d2f77d8293fe14638e74cbf52d1241b60e78 Mon Sep 17 00:00:00 2001 From: Bill Roberts Date: Mon, 8 Sep 2025 11:31:22 -0500 Subject: [PATCH] cmd/internal/obj/arm64: add support for PAC instructions Add support for the Pointer Authentication Code instructions required for the ELF ABI when enabling PAC aware binaries. This allows for assembly writers to add PAC instructions where needed to support this ABI. Follow up work is to enable the compiler to emit these instructions in the appropriate places. The TL;DR for the Linux ABI is that the prologue of a function that pushes the link register (LR) to the stack, signs the LR with a key managed by the operating system and hardware using a PAC instruction, like "paciasp". The function epilog, when restoring the LR from the stack will verify the signature, using an instruction like "autiasp". This helps prevents attackers from modifying the return address on the stack, a common technique for ROP attacks. Details on PAC can be found here: - https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/enabling-pac-and-bti-on-aarch64 - https://developer.arm.com/documentation/109576/0100/Pointer-Authentication-Code The ABI details can be found here: - https://github.com/ARM-software/abi-aa/blob/main/aaelf64/aaelf64.rst Change-Id: I4516ed1294d19f9ff9d278833d542821b6642aa9 Reviewed-on: https://go-review.googlesource.com/c/go/+/676675 Reviewed-by: Cherry Mui Reviewed-by: Joel Sing LUCI-TryBot-Result: Go LUCI Reviewed-by: Dmitri Shuralyov --- src/cmd/asm/internal/asm/testdata/arm64.s | 8 ++++++ .../asm/internal/asm/testdata/arm64error.s | 6 +++++ src/cmd/internal/obj/arm64/a.out.go | 6 +++++ src/cmd/internal/obj/arm64/anames.go | 6 +++++ src/cmd/internal/obj/arm64/asm7.go | 25 +++++++++++++++++++ 5 files changed, 51 insertions(+) diff --git a/src/cmd/asm/internal/asm/testdata/arm64.s b/src/cmd/asm/internal/asm/testdata/arm64.s index 236f1a6697..109a3d8316 100644 --- a/src/cmd/asm/internal/asm/testdata/arm64.s +++ b/src/cmd/asm/internal/asm/testdata/arm64.s @@ -1894,4 +1894,12 @@ next: BTI J // 9f2403d5 BTI JC // df2403d5 +// Pointer Authentication Codes (PAC) + PACIASP // 3f2303d5 + AUTIASP // bf2303d5 + PACIBSP // 7f2303d5 + AUTIBSP // ff2303d5 + AUTIA1716 // 9f2103d5 + AUTIB1716 // df2103d5 + END diff --git a/src/cmd/asm/internal/asm/testdata/arm64error.s b/src/cmd/asm/internal/asm/testdata/arm64error.s index 55890ce3e6..ce88e3ca54 100644 --- a/src/cmd/asm/internal/asm/testdata/arm64error.s +++ b/src/cmd/asm/internal/asm/testdata/arm64error.s @@ -422,4 +422,10 @@ TEXT errors(SB),$0 SHA1H V1.B16, V2.B16 // ERROR "invalid operands" BTI // ERROR "missing operand" BTI PLDL1KEEP // ERROR "illegal argument" + PACIASP C // ERROR "illegal combination" + AUTIASP R2 // ERROR "illegal combination" + PACIBSP R0 // ERROR "illegal combination" + AUTIBSP C // ERROR "illegal combination" + AUTIA1716 $45 // ERROR "illegal combination" + AUTIB1716 R0 // ERROR "illegal combination" RET diff --git a/src/cmd/internal/obj/arm64/a.out.go b/src/cmd/internal/obj/arm64/a.out.go index 710dd64b30..814dba2c10 100644 --- a/src/cmd/internal/obj/arm64/a.out.go +++ b/src/cmd/internal/obj/arm64/a.out.go @@ -1020,6 +1020,12 @@ const ( AWORD AYIELD ABTI + APACIASP + AAUTIASP + APACIBSP + AAUTIBSP + AAUTIA1716 + AAUTIB1716 ALAST AB = obj.AJMP ABL = obj.ACALL diff --git a/src/cmd/internal/obj/arm64/anames.go b/src/cmd/internal/obj/arm64/anames.go index 379f53bab3..497429d998 100644 --- a/src/cmd/internal/obj/arm64/anames.go +++ b/src/cmd/internal/obj/arm64/anames.go @@ -537,5 +537,11 @@ var Anames = []string{ "WORD", "YIELD", "BTI", + "PACIASP", + "AUTIASP", + "PACIBSP", + "AUTIBSP", + "AUTIA1716", + "AUTIB1716", "LAST", } diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go index 172c2256d7..cfb70cf08a 100644 --- a/src/cmd/internal/obj/arm64/asm7.go +++ b/src/cmd/internal/obj/arm64/asm7.go @@ -3017,6 +3017,13 @@ func buildop(ctxt *obj.Link) { oprangeset(ANOOP, t) oprangeset(ADRPS, t) + oprangeset(APACIASP, t) + oprangeset(AAUTIASP, t) + oprangeset(APACIBSP, t) + oprangeset(AAUTIBSP, t) + oprangeset(AAUTIA1716, t) + oprangeset(AAUTIB1716, t) + case ACBZ: oprangeset(ACBZW, t) oprangeset(ACBNZ, t) @@ -7016,6 +7023,24 @@ func (c *ctxt7) op0(p *obj.Prog, a obj.As) uint32 { case ASEVL: return SYSHINT(5) + + case APACIASP: + return SYSHINT(25) + + case AAUTIASP: + return SYSHINT(29) + + case APACIBSP: + return SYSHINT(27) + + case AAUTIBSP: + return SYSHINT(31) + + case AAUTIA1716: + return SYSHINT(12) + + case AAUTIB1716: + return SYSHINT(14) } c.ctxt.Diag("%v: bad op0 %v", p, a) -- 2.52.0