mbox series

[00/11] ARMv8.3 pointer authentication userspace support

Message ID 1500480092-28480-1-git-send-email-mark.rutland@arm.com
Headers show
Series ARMv8.3 pointer authentication userspace support | expand

Message

Mark Rutland July 19, 2017, 4:01 p.m. UTC
This series adds support for the ARMv8.3 pointer authentication extension.

Since RFC [1]:
* Make the KVM context switch (semi-lazy)
* Rebase to v4.13-rc1
* Improve pointer authentication documentation
* Add hwcap documentation
* Various minor cleanups

I've pushed the series to the arm64/pointer-auth branch [2] of my linux tree.
I've also pushed out a necessary bootwrapper patch to the pointer-auth branch
[3] of my bootwrapper repo.


Extension Overview 
==================

The ARMv8.3 pointer authentication extension adds functionality to detect
modification of pointer values, mitigating certain classes of attack such as
stack smashing, and making return oriented programming attacks harder

The extension introduces the concept of a pointer authentication code (PAC),
which is stored in some upper bits of pointers. Each PAC is derived from the
original pointer, another 64-bit value (e.g. the stack pointer), and a secret
128-bit key.

New instructions are added which can be used to:

* Insert a PAC into a pointer
* Strip a PAC from a pointer
* Authenticate strip a PAC from a pointer

If authentication succeeds, the code is removed, yielding the original pointer.
If authentication fails, bits are set in the pointer such that it is guaranteed
to cause a fault if used.

These instructions can make use of four keys:

* APIAKey (A.K.A. Instruction A key)
* APIBKey (A.K.A. Instruction B key)
* APDAKey (A.K.A. Data A key)
* APDBKey (A.K.A. Data B Key)

A subset of these instruction encodings have been allocated from the HINT
space, and will operate as NOPs on any ARMv8 parts which do not feature the
extension (or if purposefully disabled by the kernel). Software using only this
subset of the instructions should function correctly on all ARMv8-A parts.

Additionally, instructions are added to authenticate small blocks of memory in
similar fashion, using APGAKey (A.K.A. Generic key).


This Series
===========

This series enables the use of instructions using APIAKey, which is initialised
and maintained per-process (shared by all threads). This series does not add
support for APIBKey, APDAKey, APDBKey, nor APGAKey. The series only supports
the use of an architected algorithm.

I've given this some basic testing with a homebrew test suite. More ideally,
we'd add some tests to the kernel source tree.

I've added some basic KVM support, but this doesn't cater for systems with
mismatched support. Looking forward, we'll need ID register emulation in KVM so
that we can hide features from guests to cater for such cases.


Open questions
==============

* Should keys be per-thread rather than per-process?

  My understanding is that glibc can't (currently) handle threads having
  different keys, but it might be that another libc would prefer per-thread
  keys. If desired, we could add a mechanism for a thread to re-initialize its
  keys without an exec*().

* Do we need a separate hwcap for XPAC* instructions?

  Library code performing stack unwinding may need to interoperate with other
  code which may or may not be using pointer authentication. It may be
  desirable to use XPAC* rather than attempting authentication and/or acquiring
  the PAC masks via ptrace.

  As we may expose APIBKey (potentially separately from APIAKey) in future,
  HWCAP_APIA cannot be used to determine when these instruction can/should be
  used.

* Should we expose a per-process data key now, to go with the insn key?

  I don't currently have a use-case for this.

* Should we expose generic authentication (i.e. APGAKey)?

  I don't currently have a use-case for this.

* Should the kernel remove PACs when unwinding user stacks?

  This is simple to do, but it's arguably placing a policy in the kernel as to
  what we expect user stacks to look like. Regardless, userspace will have to
  perform this when unwinding with DWARF.

Thanks,
Mark.

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2017-April/498941.html
[2] git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git arm64/pointer-auth
[3] git://git.kernel.org/pub/scm/linux/kernel/git/mark/boot-wrapper-aarch64.git pointer-auth

Mark Rutland (11):
  arm64: docs: describe ELF hwcaps
  asm-generic: mm_hooks: allow hooks to be overridden individually
  arm64: add pointer authentication register bits
  arm64/cpufeature: add ARMv8.3 id_aa64isar1 bits
  arm64/cpufeature: detect pointer authentication
  arm64: Don't trap host pointer auth use to EL2
  arm64: add basic pointer authentication support
  arm64: expose user PAC bit positions via ptrace
  arm64/kvm: preserve host HCR_EL2 value
  arm64/kvm: context-switch ptrauth registers
  arm64: docs: document pointer authentication

 Documentation/arm64/booting.txt                |   8 ++
 Documentation/arm64/elf_hwcaps.txt             | 138 +++++++++++++++++++++++++
 Documentation/arm64/pointer-authentication.txt |  85 +++++++++++++++
 arch/arm64/Kconfig                             |  23 +++++
 arch/arm64/include/asm/cpucaps.h               |   4 +-
 arch/arm64/include/asm/esr.h                   |   3 +-
 arch/arm64/include/asm/kvm_arm.h               |   3 +-
 arch/arm64/include/asm/kvm_host.h              |  28 ++++-
 arch/arm64/include/asm/kvm_hyp.h               |   7 ++
 arch/arm64/include/asm/mmu.h                   |   5 +
 arch/arm64/include/asm/mmu_context.h           |  25 ++++-
 arch/arm64/include/asm/pointer_auth.h          |  97 +++++++++++++++++
 arch/arm64/include/asm/sysreg.h                |  30 ++++++
 arch/arm64/include/uapi/asm/hwcap.h            |   1 +
 arch/arm64/include/uapi/asm/ptrace.h           |   5 +
 arch/arm64/kernel/cpufeature.c                 |  39 ++++++-
 arch/arm64/kernel/cpuinfo.c                    |   1 +
 arch/arm64/kernel/head.S                       |  19 +++-
 arch/arm64/kernel/ptrace.c                     |  39 +++++++
 arch/arm64/kvm/handle_exit.c                   |  21 ++++
 arch/arm64/kvm/hyp/Makefile                    |   1 +
 arch/arm64/kvm/hyp/ptrauth-sr.c                |  91 ++++++++++++++++
 arch/arm64/kvm/hyp/switch.c                    |   9 +-
 arch/arm64/kvm/hyp/tlb.c                       |   6 +-
 arch/arm64/kvm/sys_regs.c                      |  32 ++++++
 include/asm-generic/mm_hooks.h                 |  11 ++
 include/uapi/linux/elf.h                       |   1 +
 27 files changed, 719 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/arm64/elf_hwcaps.txt
 create mode 100644 Documentation/arm64/pointer-authentication.txt
 create mode 100644 arch/arm64/include/asm/pointer_auth.h
 create mode 100644 arch/arm64/kvm/hyp/ptrauth-sr.c

-- 
1.9.1

Comments

Dave Martin July 21, 2017, 5:05 p.m. UTC | #1
On Wed, Jul 19, 2017 at 05:01:21PM +0100, Mark Rutland wrote:
> This series adds support for the ARMv8.3 pointer authentication extension.

> 

> Since RFC [1]:

> * Make the KVM context switch (semi-lazy)

> * Rebase to v4.13-rc1

> * Improve pointer authentication documentation

> * Add hwcap documentation

> * Various minor cleanups

> 

> I've pushed the series to the arm64/pointer-auth branch [2] of my linux tree.

> I've also pushed out a necessary bootwrapper patch to the pointer-auth branch

> [3] of my bootwrapper repo.


[...]

> Open questions

> ==============

> 

> * Should keys be per-thread rather than per-process?

> 

>   My understanding is that glibc can't (currently) handle threads having

>   different keys, but it might be that another libc would prefer per-thread


Can you elaborate?

It's not valid to do a function return from one thread to another.

>   keys. If desired, we could add a mechanism for a thread to re-initialize its

>   keys without an exec*().


Switching from per-process to per-thread keys would be an ABI break
unless it's opt-in.

> * Do we need a separate hwcap for XPAC* instructions?

> 

>   Library code performing stack unwinding may need to interoperate with other

>   code which may or may not be using pointer authentication. It may be

>   desirable to use XPAC* rather than attempting authentication and/or acquiring

>   the PAC masks via ptrace.

> 

>   As we may expose APIBKey (potentially separately from APIAKey) in future,

>   HWCAP_APIA cannot be used to determine when these instruction can/should be

>   used.


Can the availability of XPAC* be determined from the feature regs, or
is that insufficient?

This is a little different from the keys, which the kernel must
provision / allow to be set in order for them to be useful.

> * Should we expose a per-process data key now, to go with the insn key?

> 

>   I don't currently have a use-case for this.

> 

> * Should we expose generic authentication (i.e. APGAKey)?

> 

>   I don't currently have a use-case for this.


I guess there's no ABI impact for adding these later, so maybe it's not
urgent if nobody shouts.

> * Should the kernel remove PACs when unwinding user stacks?

> 

>   This is simple to do, but it's arguably placing a policy in the kernel as to

>   what we expect user stacks to look like. Regardless, userspace will have to

>   perform this when unwinding with DWARF.


Not sure.  This is arguably not more gross than related things the
kernel already does, and may be inefficient for userspace to do e.g.,
when capturing perf backtraces.  Still gross though.

Side question: do you know whether there will be DWARF / ELF annotations
for this?  Since ptr auth is a compile-time option, it is plausible that
an attribute could be added to indicate that an image uses it.

Cheers
---Dave
Yao Qi July 24, 2017, 11:52 a.m. UTC | #2
On 19/07/17 17:01, Mark Rutland wrote:
> * Should the kernel remove PACs when unwinding user stacks?

>

>   This is simple to do, but it's arguably placing a policy in the kernel as to

>   what we expect user stacks to look like. Regardless, userspace will have to

>   perform this when unwinding with DWARF.


I am not sure what do you mean.  Do you mean stripping a PAC from a
pointer during unwinding, so that user space can unwind the program
without being aware of PAC?  Can kernel remove PAC from all instruction
pointers?  Note that user space debugger may try to unwind in coredump,
so if the contents dumped into coredump including PAC bits, debuggers
still have to be aware of PAC (unless kernel can remove all PAC bits
during coredump too).

IMO, kernel needs to tell the truth to reflect the process/task state
to the user space, and leave the user space to consume.
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.
Yao Qi July 25, 2017, 11:32 a.m. UTC | #3
On 19/07/17 17:01, Mark Rutland wrote:
> If authentication fails, bits are set in the pointer such that it is guaranteed

> to cause a fault if used.


How does user space know the fault is caused by authentication fail?
When GDB is debugging a program, and it failed in pointer
authentication, I assume GDB only knows that the program receives signal
SIGSEGV, but how does GDB or user know why does the program get SIGSEGV?
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.
Mark Rutland July 25, 2017, 12:06 p.m. UTC | #4
On Fri, Jul 21, 2017 at 06:05:09PM +0100, Dave Martin wrote:
> On Wed, Jul 19, 2017 at 05:01:21PM +0100, Mark Rutland wrote:

> > This series adds support for the ARMv8.3 pointer authentication extension.


> > Open questions

> > ==============

> > 

> > * Should keys be per-thread rather than per-process?

> > 

> >   My understanding is that glibc can't (currently) handle threads having

> >   different keys, but it might be that another libc would prefer per-thread

> 

> Can you elaborate?

> 

> It's not valid to do a function return from one thread to another.


Regardless of whether it's valid per the C spec or POSIX, some people
use {set,get}context and {set,long}jmp in this manner (IIRC, QEMU does
this), and my understanding is that similar tricks are in use in the
bowels of glibc.

Otherwise, my preference would be to have per-thread keys from day one.

> >   keys. If desired, we could add a mechanism for a thread to re-initialize its

> >   keys without an exec*().

> 

> Switching from per-process to per-thread keys would be an ABI break

> unless it's opt-in.


Indeed, which is why I suggested an opt-in mechanism.

> > * Do we need a separate hwcap for XPAC* instructions?

> > 

> >   Library code performing stack unwinding may need to interoperate with other

> >   code which may or may not be using pointer authentication. It may be

> >   desirable to use XPAC* rather than attempting authentication and/or acquiring

> >   the PAC masks via ptrace.

> > 

> >   As we may expose APIBKey (potentially separately from APIAKey) in future,

> >   HWCAP_APIA cannot be used to determine when these instruction can/should be

> >   used.

> 

> Can the availability of XPAC* be determined from the feature regs, or

> is that insufficient?


I'd forgotten to fix up the id reg emulation to enable this, but this
should be sufficient when wired up.

The painful part is that there are several fields which can imply XPAC*
are present, so userspace has to remember to check all of those fields.

[...]

> > * Should the kernel remove PACs when unwinding user stacks?

> > 

> >   This is simple to do, but it's arguably placing a policy in the kernel as to

> >   what we expect user stacks to look like. Regardless, userspace will have to

> >   perform this when unwinding with DWARF.

> 

> Not sure.  This is arguably not more gross than related things the

> kernel already does, and may be inefficient for userspace to do e.g.,

> when capturing perf backtraces.  Still gross though.

> 

> Side question: do you know whether there will be DWARF / ELF annotations

> for this?  Since ptr auth is a compile-time option, it is plausible that

> an attribute could be added to indicate that an image uses it.


Jiong, Yao, can you answer this?

I think that there's DWARF metadata for unwinding, but I'm not sure
there's an ELF annotation on an image.

Note that you may link with libraries which may or may not use pointer
auth, so a single process can have a mixture of code using pointer auth,
and code which does not.

Thanks,
Mark.
Jiong Wang July 25, 2017, 2 p.m. UTC | #5
> > * Should the kernel remove PACs when unwinding user stacks?

> >

> >   This is simple to do, but it's arguably placing a policy in the kernel as to

> >   what we expect user stacks to look like. Regardless, userspace will have to

> >   perform this when unwinding with DWARF.

>>

>> Not sure.  This is arguably not more gross than related things the

>> kernel already does, and may be inefficient for userspace to do e.g.,

>> when capturing perf backtraces.  Still gross though.

>>

>> Side question: do you know whether there will be DWARF / ELF annotations

>> for this?  Since ptr auth is a compile-time option, it is plausible that

>> an attribute could be added to indicate that an image uses it.


> Jiong, Yao, can you answer this?

>

> I think that there's DWARF metadata for unwinding, but I'm not sure

> there's an ELF annotation on an image.

>

> Note that you may link with libraries which may or may not use pointer

> auth, so a single process can have a mixture of code using pointer auth,

> and code which does not.


Yes, there is new DWARF frame information for pointer authentication to describe
the signing status at instruction level.  There is no ELF annotation on an image.

As the use cases of pointer authentication extension in GCC are about return
address signing.  The DWARF extension is mostly around describing signed LR so
the unwinder could have a way to figure out the original value of it to continue
unwinding.

In general, whenever return address, i.e. LR register, is mangled or restored by
hardware instruction, compiler (or assembly writer) is expected to generate a
DW_CFA_AARCH64_negate_ra_state CFA instruction.

For DWARF unwinder, during unwinding, whenever a DW_CFA_AARCH64_negate_ra_state
is hit, the unwinder toggle the LR signing status and kept it in bit zero (lsb)
of a new DWARF register AARCH64_DWARF_PAUTH_RA_STATE whose value must be honored
later when unwinding the value of LR. If the lsb of AARCH64_DWARF_PAUTH_RA_STATE
is set, it means the return address is mangled, then the unwinder needs to
restore LR by either masking off the signature (userspace unwinders need ptrace
interface to get this) or executing signature strip instruction (can only be
done by native unwinder) or executing authentication instruction (can only be
done by native unwinder).

Please see the following links for more details:
  https://gcc.gnu.org/ml/gcc-patches/2017-01/msg00376.html
  https://gcc.gnu.org/ml/gcc-patches/2016-11/msg03010.html


Regards,
Jiong

IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.
Li Kun July 25, 2017, 2:12 p.m. UTC | #6
Hi Mark,

Could you please give us some information about the impact to 
performance to help us evaluating

the influence to the system?

Thanks a lot.


Best Regards


在 2017/7/20 0:01, Mark Rutland 写道:
> This series adds support for the ARMv8.3 pointer authentication extension.

>

> Since RFC [1]:

> * Make the KVM context switch (semi-lazy)

> * Rebase to v4.13-rc1

> * Improve pointer authentication documentation

> * Add hwcap documentation

> * Various minor cleanups

>

> I've pushed the series to the arm64/pointer-auth branch [2] of my linux tree.

> I've also pushed out a necessary bootwrapper patch to the pointer-auth branch

> [3] of my bootwrapper repo.

>

>

> Extension Overview

> ==================

>

> The ARMv8.3 pointer authentication extension adds functionality to detect

> modification of pointer values, mitigating certain classes of attack such as

> stack smashing, and making return oriented programming attacks harder

>

> The extension introduces the concept of a pointer authentication code (PAC),

> which is stored in some upper bits of pointers. Each PAC is derived from the

> original pointer, another 64-bit value (e.g. the stack pointer), and a secret

> 128-bit key.

>

> New instructions are added which can be used to:

>

> * Insert a PAC into a pointer

> * Strip a PAC from a pointer

> * Authenticate strip a PAC from a pointer

>

> If authentication succeeds, the code is removed, yielding the original pointer.

> If authentication fails, bits are set in the pointer such that it is guaranteed

> to cause a fault if used.

>

> These instructions can make use of four keys:

>

> * APIAKey (A.K.A. Instruction A key)

> * APIBKey (A.K.A. Instruction B key)

> * APDAKey (A.K.A. Data A key)

> * APDBKey (A.K.A. Data B Key)

>

> A subset of these instruction encodings have been allocated from the HINT

> space, and will operate as NOPs on any ARMv8 parts which do not feature the

> extension (or if purposefully disabled by the kernel). Software using only this

> subset of the instructions should function correctly on all ARMv8-A parts.

>

> Additionally, instructions are added to authenticate small blocks of memory in

> similar fashion, using APGAKey (A.K.A. Generic key).

>

>

> This Series

> ===========

>

> This series enables the use of instructions using APIAKey, which is initialised

> and maintained per-process (shared by all threads). This series does not add

> support for APIBKey, APDAKey, APDBKey, nor APGAKey. The series only supports

> the use of an architected algorithm.

>

> I've given this some basic testing with a homebrew test suite. More ideally,

> we'd add some tests to the kernel source tree.

>

> I've added some basic KVM support, but this doesn't cater for systems with

> mismatched support. Looking forward, we'll need ID register emulation in KVM so

> that we can hide features from guests to cater for such cases.

>

>

> Open questions

> ==============

>

> * Should keys be per-thread rather than per-process?

>

>    My understanding is that glibc can't (currently) handle threads having

>    different keys, but it might be that another libc would prefer per-thread

>    keys. If desired, we could add a mechanism for a thread to re-initialize its

>    keys without an exec*().

>

> * Do we need a separate hwcap for XPAC* instructions?

>

>    Library code performing stack unwinding may need to interoperate with other

>    code which may or may not be using pointer authentication. It may be

>    desirable to use XPAC* rather than attempting authentication and/or acquiring

>    the PAC masks via ptrace.

>

>    As we may expose APIBKey (potentially separately from APIAKey) in future,

>    HWCAP_APIA cannot be used to determine when these instruction can/should be

>    used.

>

> * Should we expose a per-process data key now, to go with the insn key?

>

>    I don't currently have a use-case for this.

>

> * Should we expose generic authentication (i.e. APGAKey)?

>

>    I don't currently have a use-case for this.

>

> * Should the kernel remove PACs when unwinding user stacks?

>

>    This is simple to do, but it's arguably placing a policy in the kernel as to

>    what we expect user stacks to look like. Regardless, userspace will have to

>    perform this when unwinding with DWARF.

>

> Thanks,

> Mark.

>

> [1] http://lists.infradead.org/pipermail/linux-arm-kernel/2017-April/498941.html

> [2] git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git arm64/pointer-auth

> [3] git://git.kernel.org/pub/scm/linux/kernel/git/mark/boot-wrapper-aarch64.git pointer-auth

>

> Mark Rutland (11):

>    arm64: docs: describe ELF hwcaps

>    asm-generic: mm_hooks: allow hooks to be overridden individually

>    arm64: add pointer authentication register bits

>    arm64/cpufeature: add ARMv8.3 id_aa64isar1 bits

>    arm64/cpufeature: detect pointer authentication

>    arm64: Don't trap host pointer auth use to EL2

>    arm64: add basic pointer authentication support

>    arm64: expose user PAC bit positions via ptrace

>    arm64/kvm: preserve host HCR_EL2 value

>    arm64/kvm: context-switch ptrauth registers

>    arm64: docs: document pointer authentication

>

>   Documentation/arm64/booting.txt                |   8 ++

>   Documentation/arm64/elf_hwcaps.txt             | 138 +++++++++++++++++++++++++

>   Documentation/arm64/pointer-authentication.txt |  85 +++++++++++++++

>   arch/arm64/Kconfig                             |  23 +++++

>   arch/arm64/include/asm/cpucaps.h               |   4 +-

>   arch/arm64/include/asm/esr.h                   |   3 +-

>   arch/arm64/include/asm/kvm_arm.h               |   3 +-

>   arch/arm64/include/asm/kvm_host.h              |  28 ++++-

>   arch/arm64/include/asm/kvm_hyp.h               |   7 ++

>   arch/arm64/include/asm/mmu.h                   |   5 +

>   arch/arm64/include/asm/mmu_context.h           |  25 ++++-

>   arch/arm64/include/asm/pointer_auth.h          |  97 +++++++++++++++++

>   arch/arm64/include/asm/sysreg.h                |  30 ++++++

>   arch/arm64/include/uapi/asm/hwcap.h            |   1 +

>   arch/arm64/include/uapi/asm/ptrace.h           |   5 +

>   arch/arm64/kernel/cpufeature.c                 |  39 ++++++-

>   arch/arm64/kernel/cpuinfo.c                    |   1 +

>   arch/arm64/kernel/head.S                       |  19 +++-

>   arch/arm64/kernel/ptrace.c                     |  39 +++++++

>   arch/arm64/kvm/handle_exit.c                   |  21 ++++

>   arch/arm64/kvm/hyp/Makefile                    |   1 +

>   arch/arm64/kvm/hyp/ptrauth-sr.c                |  91 ++++++++++++++++

>   arch/arm64/kvm/hyp/switch.c                    |   9 +-

>   arch/arm64/kvm/hyp/tlb.c                       |   6 +-

>   arch/arm64/kvm/sys_regs.c                      |  32 ++++++

>   include/asm-generic/mm_hooks.h                 |  11 ++

>   include/uapi/linux/elf.h                       |   1 +

>   27 files changed, 719 insertions(+), 13 deletions(-)

>   create mode 100644 Documentation/arm64/elf_hwcaps.txt

>   create mode 100644 Documentation/arm64/pointer-authentication.txt

>   create mode 100644 arch/arm64/include/asm/pointer_auth.h

>   create mode 100644 arch/arm64/kvm/hyp/ptrauth-sr.c

>


-- 
Best Regards
Li Kun
Mark Rutland July 25, 2017, 3:12 p.m. UTC | #7
On Tue, Jul 25, 2017 at 10:12:24PM +0800, Li Kun wrote:
> Hi Mark,


Hi,

> Could you please give us some information about the impact to

> performance to help us evaluating the influence to the system?


I'm afraid I don't have any performance details to share, as this series
has been developed and tested using models, and the performance impact
of pointer authentication will be very much dependent on the
microarchitecture.

I have assumed that this shouldn't regress performance on systems
without pointer authentication functionality, but I haven't yet
attempted to verify that.

From this series, I'd expect the largest cost to be the semi-lazy KVM
context-switch, for guests which are continuously using pointer
authentication.

Thanks,
Mark.
Mark Rutland July 25, 2017, 4:01 p.m. UTC | #8
Hi,

On Tue, Jul 25, 2017 at 12:32:10PM +0100, Yao Qi wrote:
> On 19/07/17 17:01, Mark Rutland wrote:

> > If authentication fails, bits are set in the pointer such that it is

> > guaranteed to cause a fault if used.

> 

> How does user space know the fault is caused by authentication fail?


Strictly speaking, it does not, and neither does the kernel.

In general, it cannot know whether this is the case, as an
authentication failure does not result in an immediate exception.

> When GDB is debugging a program, and it failed in pointer

> authentication, I assume GDB only knows that the program receives signal

> SIGSEGV, but how does GDB or user know why does the program get SIGSEGV?


I think in practice, the user has to determine this for themselves. I do
not believe that it is possible to reliably determine whether a given
fault was caused by an authentication failure.

For example, consider an authentication failure in a function epilogue:

	ldp	x29, x30, [sp], #FRAME_SIZE
	autiasp
	ret

When AUTIASP fails to authenticate the x30 value, it ensures that x30 is
a faulting value, by forcing some of the high bits to particular values,
but that's all. A user can set those bits in the same way.

The RET loads the LR value into the PC, which subsequently triggers an
instruction abort for the PC value (i.e. we branch to the bogus address
*then* take a fault at that address).

At that point, we have no information to determine what the CPU was
executing before it branched to the bogus address. So we cannot know how
the address was generated, and therefore cannot know if it was an
authentication failure.

For data pointers, you could generate bogus pointers with a large
out-of-bounds array index, whereby the bogus pointer looked like the
result of a pointer authentication failure.

Thanks,
Mark.
Mark Rutland Aug. 11, 2017, 11:29 a.m. UTC | #9
On Tue, Jul 25, 2017 at 01:06:43PM +0100, Mark Rutland wrote:
> On Fri, Jul 21, 2017 at 06:05:09PM +0100, Dave Martin wrote:

> > On Wed, Jul 19, 2017 at 05:01:21PM +0100, Mark Rutland wrote:

> > > This series adds support for the ARMv8.3 pointer authentication extension.

> 

> > > Open questions

> > > ==============

> > > 

> > > * Should keys be per-thread rather than per-process?

> > > 

> > >   My understanding is that glibc can't (currently) handle threads having

> > >   different keys, but it might be that another libc would prefer per-thread

> > 

> > Can you elaborate?

> > 

> > It's not valid to do a function return from one thread to another.

> 

> Regardless of whether it's valid per the C spec or POSIX, some people

> use {set,get}context and {set,long}jmp in this manner (IIRC, QEMU does

> this), and my understanding is that similar tricks are in use in the

> bowels of glibc.

> 

> Otherwise, my preference would be to have per-thread keys from day one.


Having considered comments I've received elsewhere, I've reversed my
position here. I think per-process keys are the more
sensible default since:

* This will allow us to protect function pointers in shared
  datastructures such as vtables.

* Tasks have their own stacks, and values leaked from one stack cannot
  be used to spoof return addresses on another.

* If an attacker can take control of one thread, they've already gained
  code execution and/or primitives that can be used to attack the
  process by other means.

Thanks,
Mark.