cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pointer_auth.h (4651B)


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