Skip to content

Commit e16aeb0

Browse files
amitdanielkachhapwilldeacon
authored andcommitted
arm64: ptrauth: Introduce Armv8.3 pointer authentication enhancements
Some Armv8.3 Pointer Authentication enhancements have been introduced which are mandatory for Armv8.6 and optional for Armv8.3. These features are, * ARMv8.3-PAuth2 - An enhanced PAC generation logic is added which hardens finding the correct PAC value of the authenticated pointer. * ARMv8.3-FPAC - Fault is generated now when the ptrauth authentication instruction fails in authenticating the PAC present in the address. This is different from earlier case when such failures just adds an error code in the top byte and waits for subsequent load/store to abort. The ptrauth instructions which may cause this fault are autiasp, retaa etc. The above features are now represented by additional configurations for the Address Authentication cpufeature and a new ESR exception class. The userspace fault received in the kernel due to ARMv8.3-FPAC is treated as Illegal instruction and hence signal SIGILL is injected with ILL_ILLOPN as the signal code. Note that this is different from earlier ARMv8.3 ptrauth where signal SIGSEGV is issued due to Pointer authentication failures. The in-kernel PAC fault causes kernel to crash. Signed-off-by: Amit Daniel Kachhap <amit.kachhap@arm.com> Reviewed-by: Dave Martin <Dave.Martin@arm.com> Link: https://lore.kernel.org/r/20200914083656.21428-4-amit.kachhap@arm.com Signed-off-by: Will Deacon <will@kernel.org>
1 parent 4ef333b commit e16aeb0

5 files changed

Lines changed: 53 additions & 9 deletions

File tree

arch/arm64/include/asm/esr.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@
3535
#define ESR_ELx_EC_SYS64 (0x18)
3636
#define ESR_ELx_EC_SVE (0x19)
3737
#define ESR_ELx_EC_ERET (0x1a) /* EL2 only */
38-
/* Unallocated EC: 0x1b - 0x1E */
38+
/* Unallocated EC: 0x1B */
39+
#define ESR_ELx_EC_FPAC (0x1C) /* EL1 and above */
40+
/* Unallocated EC: 0x1D - 0x1E */
3941
#define ESR_ELx_EC_IMP_DEF (0x1f) /* EL3 only */
4042
#define ESR_ELx_EC_IABT_LOW (0x20)
4143
#define ESR_ELx_EC_IABT_CUR (0x21)

arch/arm64/include/asm/exception.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,5 @@ void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr);
4747
void do_cp15instr(unsigned int esr, struct pt_regs *regs);
4848
void do_el0_svc(struct pt_regs *regs);
4949
void do_el0_svc_compat(struct pt_regs *regs);
50+
void do_ptrauth_fault(struct pt_regs *regs, unsigned int esr);
5051
#endif /* __ASM_EXCEPTION_H */

arch/arm64/include/asm/sysreg.h

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -636,14 +636,22 @@
636636
#define ID_AA64ISAR1_APA_SHIFT 4
637637
#define ID_AA64ISAR1_DPB_SHIFT 0
638638

639-
#define ID_AA64ISAR1_APA_NI 0x0
640-
#define ID_AA64ISAR1_APA_ARCHITECTED 0x1
641-
#define ID_AA64ISAR1_API_NI 0x0
642-
#define ID_AA64ISAR1_API_IMP_DEF 0x1
643-
#define ID_AA64ISAR1_GPA_NI 0x0
644-
#define ID_AA64ISAR1_GPA_ARCHITECTED 0x1
645-
#define ID_AA64ISAR1_GPI_NI 0x0
646-
#define ID_AA64ISAR1_GPI_IMP_DEF 0x1
639+
#define ID_AA64ISAR1_APA_NI 0x0
640+
#define ID_AA64ISAR1_APA_ARCHITECTED 0x1
641+
#define ID_AA64ISAR1_APA_ARCH_EPAC 0x2
642+
#define ID_AA64ISAR1_APA_ARCH_EPAC2 0x3
643+
#define ID_AA64ISAR1_APA_ARCH_EPAC2_FPAC 0x4
644+
#define ID_AA64ISAR1_APA_ARCH_EPAC2_FPAC_CMB 0x5
645+
#define ID_AA64ISAR1_API_NI 0x0
646+
#define ID_AA64ISAR1_API_IMP_DEF 0x1
647+
#define ID_AA64ISAR1_API_IMP_DEF_EPAC 0x2
648+
#define ID_AA64ISAR1_API_IMP_DEF_EPAC2 0x3
649+
#define ID_AA64ISAR1_API_IMP_DEF_EPAC2_FPAC 0x4
650+
#define ID_AA64ISAR1_API_IMP_DEF_EPAC2_FPAC_CMB 0x5
651+
#define ID_AA64ISAR1_GPA_NI 0x0
652+
#define ID_AA64ISAR1_GPA_ARCHITECTED 0x1
653+
#define ID_AA64ISAR1_GPI_NI 0x0
654+
#define ID_AA64ISAR1_GPI_IMP_DEF 0x1
647655

648656
/* id_aa64pfr0 */
649657
#define ID_AA64PFR0_CSV3_SHIFT 60

arch/arm64/kernel/entry-common.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,13 @@ static void notrace el1_dbg(struct pt_regs *regs, unsigned long esr)
6666
}
6767
NOKPROBE_SYMBOL(el1_dbg);
6868

69+
static void notrace el1_fpac(struct pt_regs *regs, unsigned long esr)
70+
{
71+
local_daif_inherit(regs);
72+
do_ptrauth_fault(regs, esr);
73+
}
74+
NOKPROBE_SYMBOL(el1_fpac);
75+
6976
asmlinkage void notrace el1_sync_handler(struct pt_regs *regs)
7077
{
7178
unsigned long esr = read_sysreg(esr_el1);
@@ -92,6 +99,9 @@ asmlinkage void notrace el1_sync_handler(struct pt_regs *regs)
9299
case ESR_ELx_EC_BRK64:
93100
el1_dbg(regs, esr);
94101
break;
102+
case ESR_ELx_EC_FPAC:
103+
el1_fpac(regs, esr);
104+
break;
95105
default:
96106
el1_inv(regs, esr);
97107
}
@@ -227,6 +237,14 @@ static void notrace el0_svc(struct pt_regs *regs)
227237
}
228238
NOKPROBE_SYMBOL(el0_svc);
229239

240+
static void notrace el0_fpac(struct pt_regs *regs, unsigned long esr)
241+
{
242+
user_exit_irqoff();
243+
local_daif_restore(DAIF_PROCCTX);
244+
do_ptrauth_fault(regs, esr);
245+
}
246+
NOKPROBE_SYMBOL(el0_fpac);
247+
230248
asmlinkage void notrace el0_sync_handler(struct pt_regs *regs)
231249
{
232250
unsigned long esr = read_sysreg(esr_el1);
@@ -272,6 +290,9 @@ asmlinkage void notrace el0_sync_handler(struct pt_regs *regs)
272290
case ESR_ELx_EC_BRK64:
273291
el0_dbg(regs, esr);
274292
break;
293+
case ESR_ELx_EC_FPAC:
294+
el0_fpac(regs, esr);
295+
break;
275296
default:
276297
el0_inv(regs, esr);
277298
}

arch/arm64/kernel/traps.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,17 @@ void do_bti(struct pt_regs *regs)
479479
}
480480
NOKPROBE_SYMBOL(do_bti);
481481

482+
void do_ptrauth_fault(struct pt_regs *regs, unsigned int esr)
483+
{
484+
/*
485+
* Unexpected FPAC exception or pointer authentication failure in
486+
* the kernel: kill the task before it does any more harm.
487+
*/
488+
BUG_ON(!user_mode(regs));
489+
force_signal_inject(SIGILL, ILL_ILLOPN, regs->pc, esr);
490+
}
491+
NOKPROBE_SYMBOL(do_ptrauth_fault);
492+
482493
#define __user_cache_maint(insn, address, res) \
483494
if (address >= user_addr_max()) { \
484495
res = -EFAULT; \
@@ -775,6 +786,7 @@ static const char *esr_class_str[] = {
775786
[ESR_ELx_EC_SYS64] = "MSR/MRS (AArch64)",
776787
[ESR_ELx_EC_SVE] = "SVE",
777788
[ESR_ELx_EC_ERET] = "ERET/ERETAA/ERETAB",
789+
[ESR_ELx_EC_FPAC] = "FPAC",
778790
[ESR_ELx_EC_IMP_DEF] = "EL3 IMP DEF",
779791
[ESR_ELx_EC_IABT_LOW] = "IABT (lower EL)",
780792
[ESR_ELx_EC_IABT_CUR] = "IABT (current EL)",

0 commit comments

Comments
 (0)