[PATCH 1/4] BACKPORT: arm64: Add CNTVCT_EL0 trap handler
Marc Zyngier [Wed, 20 Dec 2017 03:24:17 +0000 (19:24 -0800)]
Since people seem to make a point in breaking the userspace visible
counter, we have no choice but to trap the access. Add the required
handler.

Bug 2031796
CVE-2017-13218

Acked-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
(cherry picked from commit 6126ce0588eb5a0752d5c8b5796a7fca324fd887)
Change-Id: I4204b5e1db899849ca16e6b26fe234339815f864
Signed-off-by: Rohit Khanna <rokhanna@nvidia.com>
Signed-off-by: Gagan Grover <ggrover@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1621712
(cherry picked from commit fe7b634c82d1c21f7c83caecf8bd23cbdf56d389)
Reviewed-on: https://git-master.nvidia.com/r/1648567
Reviewed-by: Jeetesh Burman <jburman@nvidia.com>
Tested-by: Jeetesh Burman <jburman@nvidia.com>
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
GVS: Gerrit_Virtual_Submit

arch/arm64/include/asm/esr.h
arch/arm64/kernel/entry.S
arch/arm64/kernel/traps.c

index 7883412..422ec15 100644 (file)
 #define ESR_EL1_EC_BKPT32      (0x38)
 #define ESR_EL1_EC_BRK64       (0x3C)
 
+/* ISS field definitions for System instruction traps */
+#define ESR_ELx_SYS64_ISS_RES0_SHIFT   22
+#define ESR_ELx_SYS64_ISS_RES0_MASK    (UL(0x7) << ESR_ELx_SYS64_ISS_RES0_SHIFT)
+#define ESR_ELx_SYS64_ISS_DIR_MASK     0x1
+#define ESR_ELx_SYS64_ISS_DIR_READ     0x1
+#define ESR_ELx_SYS64_ISS_DIR_WRITE    0x0
+
+#define ESR_ELx_SYS64_ISS_RT_SHIFT     5
+#define ESR_ELx_SYS64_ISS_RT_MASK      (UL(0x1f) << ESR_ELx_SYS64_ISS_RT_SHIFT)
+#define ESR_ELx_SYS64_ISS_CRM_SHIFT    1
+#define ESR_ELx_SYS64_ISS_CRM_MASK     (UL(0xf) << ESR_ELx_SYS64_ISS_CRM_SHIFT)
+#define ESR_ELx_SYS64_ISS_CRN_SHIFT    10
+#define ESR_ELx_SYS64_ISS_CRN_MASK     (UL(0xf) << ESR_ELx_SYS64_ISS_CRN_SHIFT)
+#define ESR_ELx_SYS64_ISS_OP1_SHIFT    14
+#define ESR_ELx_SYS64_ISS_OP1_MASK     (UL(0x7) << ESR_ELx_SYS64_ISS_OP1_SHIFT)
+#define ESR_ELx_SYS64_ISS_OP2_SHIFT    17
+#define ESR_ELx_SYS64_ISS_OP2_MASK     (UL(0x7) << ESR_ELx_SYS64_ISS_OP2_SHIFT)
+#define ESR_ELx_SYS64_ISS_OP0_SHIFT    20
+#define ESR_ELx_SYS64_ISS_OP0_MASK     (UL(0x3) << ESR_ELx_SYS64_ISS_OP0_SHIFT)
+#define ESR_ELx_SYS64_ISS_SYS_MASK     (ESR_ELx_SYS64_ISS_OP0_MASK | \
+                                        ESR_ELx_SYS64_ISS_OP1_MASK | \
+                                        ESR_ELx_SYS64_ISS_OP2_MASK | \
+                                        ESR_ELx_SYS64_ISS_CRN_MASK | \
+                                        ESR_ELx_SYS64_ISS_CRM_MASK)
+#define ESR_ELx_SYS64_ISS_SYS_VAL(op0, op1, op2, crn, crm) \
+                                       (((op0) << ESR_ELx_SYS64_ISS_OP0_SHIFT) | \
+                                        ((op1) << ESR_ELx_SYS64_ISS_OP1_SHIFT) | \
+                                        ((op2) << ESR_ELx_SYS64_ISS_OP2_SHIFT) | \
+                                        ((crn) << ESR_ELx_SYS64_ISS_CRN_SHIFT) | \
+                                        ((crm) << ESR_ELx_SYS64_ISS_CRM_SHIFT))
+
+#define ESR_ELx_SYS64_ISS_SYS_OP_MASK  (ESR_ELx_SYS64_ISS_SYS_MASK | \
+                                        ESR_ELx_SYS64_ISS_DIR_MASK)
+
+#define ESR_ELx_SYS64_ISS_SYS_CNTVCT   (ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 2, 14, 0) | \
+                                        ESR_ELx_SYS64_ISS_DIR_READ)
+
 #endif /* __ASM_ESR_H */
index 13cb2fc..53bb667 100644 (file)
@@ -383,7 +383,7 @@ el0_sync:
        adr     x26, el0_fpsimd_exc
        cmp     x24, #ESR_EL1_EC_FP_EXC64       // FP/ASIMD exception
        b.eq    el0_sync_tramp
-       adr     x26, el0_undef
+       adr     x26, el0_sys
        cmp     x24, #ESR_EL1_EC_SYS64          // configurable trap
        b.eq    el0_sync_tramp
        adr     x26, el0_sp_pc
@@ -533,6 +533,15 @@ el0_undef:
        // enable interrupts before calling the main handler
        enable_irq
        b       do_undefinstr
+el0_sys:
+       /*
+        * System instructions, for trapped cache maintenance instructions
+        */
+       enable_dbg
+       enable_irq
+       mov     x0, x25
+       mov     x1, sp
+       b       do_sysinstr
 el0_dbg:
        /*
         * Debug exception handling
index 9786cca..c227247 100644 (file)
 #include <linux/sched.h>
 #include <linux/syscalls.h>
 
+#include <asm/arch_timer.h>
 #include <asm/atomic.h>
 #include <asm/debug-monitors.h>
+#include <asm/esr.h>
 #include <asm/traps.h>
 #include <asm/stacktrace.h>
 #include <asm/exception.h>
@@ -325,6 +327,25 @@ die_sig:
        arm64_notify_die("Oops - undefined instruction", regs, &info, 0);
 }
 
+static void cntvct_read_handler(unsigned int esr, struct pt_regs *regs)
+{
+       int rt = (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT;
+
+       if (rt != 31)
+               regs->regs[rt] = arch_counter_get_cntvct();
+       regs->pc += 4;
+}
+
+asmlinkage void __exception do_sysinstr(unsigned int esr, struct pt_regs *regs)
+{
+       if ((esr & ESR_ELx_SYS64_ISS_SYS_OP_MASK) == ESR_ELx_SYS64_ISS_SYS_CNTVCT) {
+               cntvct_read_handler(esr, regs);
+               return;
+       }
+
+       do_undefinstr(regs);
+}
+
 long compat_arm_syscall(struct pt_regs *regs);
 
 asmlinkage long do_ni_syscall(struct pt_regs *regs)