Thread (14 messages) 14 messages, 2 authors, 2020-10-13

Re: [PATCH] arm64: add prctl(PR_PAC_SET_ENABLED_KEYS)

flat view

From: Dave Martin <Dave.Martin@arm.com>
Date: 2020-08-24 14:57:05

On Wed, Aug 19, 2020 at 02:25:45PM -0700, Peter Collingbourne wrote:
On Wed, Aug 19, 2020 at 3:18 AM Dave Martin [off-list ref] wrote:
quoted
On Fri, Jul 31, 2020 at 06:11:52PM -0700, Peter Collingbourne wrote:
quoted
This prctl allows the user program to control which PAC keys are enabled
in a particular task. The main reason why this is useful is to enable a
userspace ABI that uses PAC to sign and authenticate function pointers
and other pointers exposed outside of the function, while still allowing
binaries conforming to the ABI to interoperate with legacy binaries that
do not sign or authenticate pointers.

The idea is that a dynamic loader or early startup code would issue
this prctl very early after establishing that a process may load legacy
binaries, but before executing any PAC instructions.
Apologies for the slow response on this, I'd had it on my list for a
while...
A couple more comments I accidentally left out of my last reply, below.
quoted
quoted
---
 .../arm64/pointer-authentication.rst          | 27 +++++++++++++++
 arch/arm64/include/asm/asm_pointer_auth.h     | 19 +++++++++++
 arch/arm64/include/asm/pointer_auth.h         | 10 ++++--
 arch/arm64/include/asm/processor.h            |  5 +++
 arch/arm64/kernel/asm-offsets.c               |  1 +
 arch/arm64/kernel/pointer_auth.c              | 34 +++++++++++++++++++
 include/uapi/linux/prctl.h                    |  3 ++
 kernel/sys.c                                  |  8 +++++
 8 files changed, 105 insertions(+), 2 deletions(-)
diff --git a/Documentation/arm64/pointer-authentication.rst b/Documentation/arm64/pointer-authentication.rst
index 30b2ab06526b..1f7e064deeb3 100644
--- a/Documentation/arm64/pointer-authentication.rst
+++ b/Documentation/arm64/pointer-authentication.rst
@@ -107,3 +107,30 @@ filter out the Pointer Authentication system key registers from
 KVM_GET/SET_REG_* ioctls and mask those features from cpufeature ID
 register. Any attempt to use the Pointer Authentication instructions will
 result in an UNDEFINED exception being injected into the guest.
+
+
+Enabling and disabling keys
+---------------------------
+
+The prctl PR_PAC_SET_ENABLED_KEYS allows the user program to control which
+PAC keys are enabled in a particular task. It takes two arguments, the
+first being a bitmask of PR_PAC_APIAKEY, PR_PAC_APIBKEY, PR_PAC_APDAKEY
+and PR_PAC_APDBKEY specifying which keys shall be affected by this prctl,
+and the second being a bitmask of the same bits specifying whether the key
+should be enabled or disabled. For example::
+
+  prctl(PR_PAC_SET_ENABLED_KEYS,
+        PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY | PR_PAC_APDBKEY,
+        PR_PAC_APIBKEY, 0, 0);
+
+disables all keys except the IB key.
+
+The main reason why this is useful is to enable a userspace ABI that uses PAC
+instructions to sign and authenticate function pointers and other pointers
+exposed outside of the function, while still allowing binaries conforming to
+the ABI to interoperate with legacy binaries that do not sign or authenticate
+pointers.
What actually breaks without this?

Since the keys are all enabled by default, the only purpose of this
prctl seems to be to disable keys.  I'm not sure what this is giving us.
Yes, the purpose is to disable keys. Let's consider the function
pointer signing userspace ABI use case. An example is Apple's arm64e
ABI, and I have a prototype branch of LLVM [0] that implements a
similar ABI in Linux userspace, based on Apple's implementation of
their ABI.

Here's an example of a function that returns a function pointer, and a
function that calls a function pointer of the same type:

static void f(void) {}

void *return_fp(void) {
  return f;
}

void call_fp(void (*p)(void)) {
  p();
}

If I compile this with my prototype compiler I get:

$ clang --target=aarch64-android   -fptrauth-calls  fptr.c -S -o - -O3
-march=armv8.3a
[...]
return_fp:                              // @return_fp
// %bb.0:                               // %entry
        adrp    x16, f
        add     x16, x16, :lo12:f
        mov     x17, #16277
        pacia   x16, x17
        mov     x0, x16
        ret
[...]
call_fp:                                // @call_fp
// %bb.0:                               // %entry
        mov     w1, #16277
        braa    x0, x1
[...]

In this code snippet the function pointer is signed with the IA key
and discriminator 16277 before being returned. When the function is
called, the pointer is first authenticated with the same key and
discriminator.

Now imagine that this code lives in a shared library used both by
programs that use the function pointer signing ABI and by legacy
binaries (i.e. programs that use the existing ABI), and we have a
legacy binary that calls return_fp. If the legacy binary then calls
the function pointer returned by return_fp, that code will not
authenticate the pointer before calling it, it will just use a br or
blr instruction to call it directly, which will lead to a crash if the
signature bits are set in the function pointer. In order to prevent
the crash, we need a way to cause the pacia instruction in return_fp
to become a no-op when running inside the process hosting the legacy
binary, so that the signature bits will remain clear and the br or blr
instruction in the legacy binary will successfully call the function
f. That can be done by disabling the IA key, which is exactly what
this prctl() lets us do.
Ack, I think there has been past discussion on this, but it's been
waiting for a usecase since it does impose a bit of extra overhead.

(I'd somehow assumes that you were actually wanting to get SIGILLs,
rather then compatibly executing some ptrauth insns as NOPs -- the
latter makes much more sense.)


Is this going to land for real, or is it just something people have
been experimenting with?

(I can guess the answer from the fact that you've proposed this patch
in the first place, but I have to ask...)

[...]

Cheers
---Dave

_______________________________________________
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