| 1 | =======================================
|
| 2 | Pointer authentication in AArch64 Linux
|
| 3 | =======================================
|
| 4 |
|
| 5 | Author: Mark Rutland <[email protected]>
|
| 6 |
|
| 7 | Date: 2017-07-19
|
| 8 |
|
| 9 | This document briefly describes the provision of pointer authentication
|
| 10 | functionality in AArch64 Linux.
|
| 11 |
|
| 12 |
|
| 13 | Architecture overview
|
| 14 | ---------------------
|
| 15 |
|
| 16 | The ARMv8.3 Pointer Authentication extension adds primitives that can be
|
| 17 | used to mitigate certain classes of attack where an attacker can corrupt
|
| 18 | the contents of some memory (e.g. the stack).
|
| 19 |
|
| 20 | The extension uses a Pointer Authentication Code (PAC) to determine
|
| 21 | whether pointers have been modified unexpectedly. A PAC is derived from
|
| 22 | a pointer, another value (such as the stack pointer), and a secret key
|
| 23 | held in system registers.
|
| 24 |
|
| 25 | The extension adds instructions to insert a valid PAC into a pointer,
|
| 26 | and to verify/remove the PAC from a pointer. The PAC occupies a number
|
| 27 | of high-order bits of the pointer, which varies dependent on the
|
| 28 | configured virtual address size and whether pointer tagging is in use.
|
| 29 |
|
| 30 | A subset of these instructions have been allocated from the HINT
|
| 31 | encoding space. In the absence of the extension (or when disabled),
|
| 32 | these instructions behave as NOPs. Applications and libraries using
|
| 33 | these instructions operate correctly regardless of the presence of the
|
| 34 | extension.
|
| 35 |
|
| 36 | The extension provides five separate keys to generate PACs - two for
|
| 37 | instruction addresses (APIAKey, APIBKey), two for data addresses
|
| 38 | (APDAKey, APDBKey), and one for generic authentication (APGAKey).
|
| 39 |
|
| 40 |
|
| 41 | Basic support
|
| 42 | -------------
|
| 43 |
|
| 44 | When CONFIG_ARM64_PTR_AUTH is selected, and relevant HW support is
|
| 45 | present, the kernel will assign random key values to each process at
|
| 46 | exec*() time. The keys are shared by all threads within the process, and
|
| 47 | are preserved across fork().
|
| 48 |
|
| 49 | Presence of address authentication functionality is advertised via
|
| 50 | HWCAP_PACA, and generic authentication functionality via HWCAP_PACG.
|
| 51 |
|
| 52 | The number of bits that the PAC occupies in a pointer is 55 minus the
|
| 53 | virtual address size configured by the kernel. For example, with a
|
| 54 | virtual address size of 48, the PAC is 7 bits wide.
|
| 55 |
|
| 56 | When ARM64_PTR_AUTH_KERNEL is selected, the kernel will be compiled
|
| 57 | with HINT space pointer authentication instructions protecting
|
| 58 | function returns. Kernels built with this option will work on hardware
|
| 59 | with or without pointer authentication support.
|
| 60 |
|
| 61 | In addition to exec(), keys can also be reinitialized to random values
|
| 62 | using the PR_PAC_RESET_KEYS prctl. A bitmask of PR_PAC_APIAKEY,
|
| 63 | PR_PAC_APIBKEY, PR_PAC_APDAKEY, PR_PAC_APDBKEY and PR_PAC_APGAKEY
|
| 64 | specifies which keys are to be reinitialized; specifying 0 means "all
|
| 65 | keys".
|
| 66 |
|
| 67 |
|
| 68 | Debugging
|
| 69 | ---------
|
| 70 |
|
| 71 | When CONFIG_ARM64_PTR_AUTH is selected, and HW support for address
|
| 72 | authentication is present, the kernel will expose the position of TTBR0
|
| 73 | PAC bits in the NT_ARM_PAC_MASK regset (struct user_pac_mask), which
|
| 74 | userspace can acquire via PTRACE_GETREGSET.
|
| 75 |
|
| 76 | The regset is exposed only when HWCAP_PACA is set. Separate masks are
|
| 77 | exposed for data pointers and instruction pointers, as the set of PAC
|
| 78 | bits can vary between the two. Note that the masks apply to TTBR0
|
| 79 | addresses, and are not valid to apply to TTBR1 addresses (e.g. kernel
|
| 80 | pointers).
|
| 81 |
|
| 82 | Additionally, when CONFIG_CHECKPOINT_RESTORE is also set, the kernel
|
| 83 | will expose the NT_ARM_PACA_KEYS and NT_ARM_PACG_KEYS regsets (struct
|
| 84 | user_pac_address_keys and struct user_pac_generic_keys). These can be
|
| 85 | used to get and set the keys for a thread.
|
| 86 |
|
| 87 |
|
| 88 | Virtualization
|
| 89 | --------------
|
| 90 |
|
| 91 | Pointer authentication is enabled in KVM guest when each virtual cpu is
|
| 92 | initialised by passing flags KVM_ARM_VCPU_PTRAUTH_[ADDRESS/GENERIC] and
|
| 93 | requesting these two separate cpu features to be enabled. The current KVM
|
| 94 | guest implementation works by enabling both features together, so both
|
| 95 | these userspace flags are checked before enabling pointer authentication.
|
| 96 | The separate userspace flag will allow to have no userspace ABI changes
|
| 97 | if support is added in the future to allow these two features to be
|
| 98 | enabled independently of one another.
|
| 99 |
|
| 100 | As Arm Architecture specifies that Pointer Authentication feature is
|
| 101 | implemented along with the VHE feature so KVM arm64 ptrauth code relies
|
| 102 | on VHE mode to be present.
|
| 103 |
|
| 104 | Additionally, when these vcpu feature flags are not set then KVM will
|
| 105 | filter out the Pointer Authentication system key registers from
|
| 106 | KVM_GET/SET_REG_* ioctls and mask those features from cpufeature ID
|
| 107 | register. Any attempt to use the Pointer Authentication instructions will
|
| 108 | result in an UNDEFINED exception being injected into the guest.
|
| 109 |
|
| 110 |
|
| 111 | Enabling and disabling keys
|
| 112 | ---------------------------
|
| 113 |
|
| 114 | The prctl PR_PAC_SET_ENABLED_KEYS allows the user program to control which
|
| 115 | PAC keys are enabled in a particular task. It takes two arguments, the
|
| 116 | first being a bitmask of PR_PAC_APIAKEY, PR_PAC_APIBKEY, PR_PAC_APDAKEY
|
| 117 | and PR_PAC_APDBKEY specifying which keys shall be affected by this prctl,
|
| 118 | and the second being a bitmask of the same bits specifying whether the key
|
| 119 | should be enabled or disabled. For example::
|
| 120 |
|
| 121 | prctl(PR_PAC_SET_ENABLED_KEYS,
|
| 122 | PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY | PR_PAC_APDBKEY,
|
| 123 | PR_PAC_APIBKEY, 0, 0);
|
| 124 |
|
| 125 | disables all keys except the IB key.
|
| 126 |
|
| 127 | The main reason why this is useful is to enable a userspace ABI that uses PAC
|
| 128 | instructions to sign and authenticate function pointers and other pointers
|
| 129 | exposed outside of the function, while still allowing binaries conforming to
|
| 130 | the ABI to interoperate with legacy binaries that do not sign or authenticate
|
| 131 | pointers.
|
| 132 |
|
| 133 | The idea is that a dynamic loader or early startup code would issue this
|
| 134 | prctl very early after establishing that a process may load legacy binaries,
|
| 135 | but before executing any PAC instructions.
|
| 136 |
|
| 137 | For compatibility with previous kernel versions, processes start up with IA,
|
| 138 | IB, DA and DB enabled, and are reset to this state on exec(). Processes created
|
| 139 | via fork() and clone() inherit the key enabled state from the calling process.
|
| 140 |
|
| 141 | It is recommended to avoid disabling the IA key, as this has higher performance
|
| 142 | overhead than disabling any of the other keys.
|