linux/arch/arm64/include/asm/pointer_auth.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2#ifndef __ASM_POINTER_AUTH_H
   3#define __ASM_POINTER_AUTH_H
   4
   5#include <linux/bitops.h>
   6#include <linux/prctl.h>
   7#include <linux/random.h>
   8
   9#include <asm/cpufeature.h>
  10#include <asm/memory.h>
  11#include <asm/sysreg.h>
  12
  13#ifdef CONFIG_ARM64_PTR_AUTH
  14/*
  15 * Each key is a 128-bit quantity which is split across a pair of 64-bit
  16 * registers (Lo and Hi).
  17 */
  18struct ptrauth_key {
  19        unsigned long lo, hi;
  20};
  21
  22/*
  23 * We give each process its own keys, which are shared by all threads. The keys
  24 * are inherited upon fork(), and reinitialised upon exec*().
  25 */
  26struct ptrauth_keys_user {
  27        struct ptrauth_key apia;
  28        struct ptrauth_key apib;
  29        struct ptrauth_key apda;
  30        struct ptrauth_key apdb;
  31        struct ptrauth_key apga;
  32};
  33
  34#define __ptrauth_key_install_nosync(k, v)                      \
  35do {                                                            \
  36        struct ptrauth_key __pki_v = (v);                       \
  37        write_sysreg_s(__pki_v.lo, SYS_ ## k ## KEYLO_EL1);     \
  38        write_sysreg_s(__pki_v.hi, SYS_ ## k ## KEYHI_EL1);     \
  39} while (0)
  40
  41#ifdef CONFIG_ARM64_PTR_AUTH_KERNEL
  42
  43struct ptrauth_keys_kernel {
  44        struct ptrauth_key apia;
  45};
  46
  47static __always_inline void ptrauth_keys_init_kernel(struct ptrauth_keys_kernel *keys)
  48{
  49        if (system_supports_address_auth())
  50                get_random_bytes(&keys->apia, sizeof(keys->apia));
  51}
  52
  53static __always_inline void ptrauth_keys_switch_kernel(struct ptrauth_keys_kernel *keys)
  54{
  55        if (!system_supports_address_auth())
  56                return;
  57
  58        __ptrauth_key_install_nosync(APIA, keys->apia);
  59        isb();
  60}
  61
  62#endif /* CONFIG_ARM64_PTR_AUTH_KERNEL */
  63
  64static inline void ptrauth_keys_install_user(struct ptrauth_keys_user *keys)
  65{
  66        if (system_supports_address_auth()) {
  67                __ptrauth_key_install_nosync(APIB, keys->apib);
  68                __ptrauth_key_install_nosync(APDA, keys->apda);
  69                __ptrauth_key_install_nosync(APDB, keys->apdb);
  70        }
  71
  72        if (system_supports_generic_auth())
  73                __ptrauth_key_install_nosync(APGA, keys->apga);
  74}
  75
  76static inline void ptrauth_keys_init_user(struct ptrauth_keys_user *keys)
  77{
  78        if (system_supports_address_auth()) {
  79                get_random_bytes(&keys->apia, sizeof(keys->apia));
  80                get_random_bytes(&keys->apib, sizeof(keys->apib));
  81                get_random_bytes(&keys->apda, sizeof(keys->apda));
  82                get_random_bytes(&keys->apdb, sizeof(keys->apdb));
  83        }
  84
  85        if (system_supports_generic_auth())
  86                get_random_bytes(&keys->apga, sizeof(keys->apga));
  87
  88        ptrauth_keys_install_user(keys);
  89}
  90
  91extern int ptrauth_prctl_reset_keys(struct task_struct *tsk, unsigned long arg);
  92
  93extern int ptrauth_set_enabled_keys(struct task_struct *tsk, unsigned long keys,
  94                                    unsigned long enabled);
  95extern int ptrauth_get_enabled_keys(struct task_struct *tsk);
  96
  97static inline unsigned long ptrauth_strip_insn_pac(unsigned long ptr)
  98{
  99        return ptrauth_clear_pac(ptr);
 100}
 101
 102static __always_inline void ptrauth_enable(void)
 103{
 104        if (!system_supports_address_auth())
 105                return;
 106        sysreg_clear_set(sctlr_el1, 0, (SCTLR_ELx_ENIA | SCTLR_ELx_ENIB |
 107                                        SCTLR_ELx_ENDA | SCTLR_ELx_ENDB));
 108        isb();
 109}
 110
 111#define ptrauth_suspend_exit()                                                 \
 112        ptrauth_keys_install_user(&current->thread.keys_user)
 113
 114#define ptrauth_thread_init_user()                                             \
 115        do {                                                                   \
 116                ptrauth_keys_init_user(&current->thread.keys_user);            \
 117                                                                               \
 118                /* enable all keys */                                          \
 119                if (system_supports_address_auth())                            \
 120                        set_task_sctlr_el1(current->thread.sctlr_user |        \
 121                                           SCTLR_ELx_ENIA | SCTLR_ELx_ENIB |   \
 122                                           SCTLR_ELx_ENDA | SCTLR_ELx_ENDB);   \
 123        } while (0)
 124
 125#define ptrauth_thread_switch_user(tsk)                                        \
 126        ptrauth_keys_install_user(&(tsk)->thread.keys_user)
 127
 128#else /* CONFIG_ARM64_PTR_AUTH */
 129#define ptrauth_enable()
 130#define ptrauth_prctl_reset_keys(tsk, arg)      (-EINVAL)
 131#define ptrauth_set_enabled_keys(tsk, keys, enabled)    (-EINVAL)
 132#define ptrauth_get_enabled_keys(tsk)   (-EINVAL)
 133#define ptrauth_strip_insn_pac(lr)      (lr)
 134#define ptrauth_suspend_exit()
 135#define ptrauth_thread_init_user()
 136#define ptrauth_thread_switch_user(tsk)
 137#endif /* CONFIG_ARM64_PTR_AUTH */
 138
 139#ifdef CONFIG_ARM64_PTR_AUTH_KERNEL
 140#define ptrauth_thread_init_kernel(tsk)                                 \
 141        ptrauth_keys_init_kernel(&(tsk)->thread.keys_kernel)
 142#define ptrauth_thread_switch_kernel(tsk)                               \
 143        ptrauth_keys_switch_kernel(&(tsk)->thread.keys_kernel)
 144#else
 145#define ptrauth_thread_init_kernel(tsk)
 146#define ptrauth_thread_switch_kernel(tsk)
 147#endif /* CONFIG_ARM64_PTR_AUTH_KERNEL */
 148
 149#define PR_PAC_ENABLED_KEYS_MASK                                               \
 150        (PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY | PR_PAC_APDBKEY)
 151
 152#endif /* __ASM_POINTER_AUTH_H */
 153