From 60f737636c2be52fe1af2f1a3a2f66acacdc6a30 Mon Sep 17 00:00:00 2001 From: Julien Grall Date: Mon, 14 Apr 2014 19:01:20 +0100 Subject: [PATCH] xen/arm: Inject an undefined instruction when the coproc/sysreg is not handled Currently Xen panics if it's unable to handle a coprocessor/sysreg instruction. Replace this behavior by inject an undefined instruction to the faulty guest and log if Xen is in debug mode. This is CVE-2014-2915 / XSA-93. Signed-off-by: Julien Grall Acked-by: Ian Campbell --- xen/arch/arm/traps.c | 61 +++++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c index a7edc4e199..92b7910e8a 100644 --- a/xen/arch/arm/traps.c +++ b/xen/arch/arm/traps.c @@ -1351,10 +1351,16 @@ static void do_cp15_32(struct cpu_user_regs *regs, *r = v->arch.actlr; break; default: - printk("%s p15, %d, r%d, cr%d, cr%d, %d @ 0x%"PRIregister"\n", - cp32.read ? "mrc" : "mcr", - cp32.op1, cp32.reg, cp32.crn, cp32.crm, cp32.op2, regs->pc); - panic("unhandled 32-bit CP15 access %#x", hsr.bits & HSR_CP32_REGS_MASK); +#ifndef NDEBUG + gdprintk(XENLOG_ERR, + "%s p15, %d, r%d, cr%d, cr%d, %d @ 0x%"PRIregister"\n", + cp32.read ? "mrc" : "mcr", + cp32.op1, cp32.reg, cp32.crn, cp32.crm, cp32.op2, regs->pc); + gdprintk(XENLOG_ERR, "unhandled 32-bit CP15 access %#x", + hsr.bits & HSR_CP32_REGS_MASK); +#endif + inject_undef32_exception(regs); + return; } advance_pc(regs, hsr); } @@ -1362,8 +1368,6 @@ static void do_cp15_32(struct cpu_user_regs *regs, static void do_cp15_64(struct cpu_user_regs *regs, union hsr hsr) { - struct hsr_cp64 cp64 = hsr.cp64; - if ( !check_conditional_instr(regs, hsr) ) { advance_pc(regs, hsr); @@ -1381,10 +1385,20 @@ static void do_cp15_64(struct cpu_user_regs *regs, } break; default: - printk("%s p15, %d, r%d, r%d, cr%d @ 0x%"PRIregister"\n", - cp64.read ? "mrrc" : "mcrr", - cp64.op1, cp64.reg1, cp64.reg2, cp64.crm, regs->pc); - panic("unhandled 64-bit CP15 access %#x", hsr.bits & HSR_CP64_REGS_MASK); + { +#ifndef NDEBUG + struct hsr_cp64 cp64 = hsr.cp64; + + gdprintk(XENLOG_ERR, + "%s p15, %d, r%d, r%d, cr%d @ 0x%"PRIregister"\n", + cp64.read ? "mrrc" : "mcrr", + cp64.op1, cp64.reg1, cp64.reg2, cp64.crm, regs->pc); + gdprintk(XENLOG_ERR, "unhandled 64-bit CP15 access %#x", + hsr.bits & HSR_CP64_REGS_MASK); +#endif + inject_undef32_exception(regs); + return; + } } advance_pc(regs, hsr); } @@ -1393,7 +1407,6 @@ static void do_cp15_64(struct cpu_user_regs *regs, static void do_sysreg(struct cpu_user_regs *regs, union hsr hsr) { - struct hsr_sysreg sysreg = hsr.sysreg; switch ( hsr.bits & HSR_SYSREG_REGS_MASK ) { @@ -1407,15 +1420,23 @@ static void do_sysreg(struct cpu_user_regs *regs, } break; default: - printk("%s %d, %d, c%d, c%d, %d %s x%d @ 0x%"PRIregister"\n", - sysreg.read ? "mrs" : "msr", - sysreg.op0, sysreg.op1, - sysreg.crn, sysreg.crm, - sysreg.op2, - sysreg.read ? "=>" : "<=", - sysreg.reg, regs->pc); - panic("unhandled 64-bit sysreg access %#x", - hsr.bits & HSR_SYSREG_REGS_MASK); + { + struct hsr_sysreg sysreg = hsr.sysreg; +#ifndef NDEBUG + + gdprintk(XENLOG_ERR, + "%s %d, %d, c%d, c%d, %d %s x%d @ 0x%"PRIregister"\n", + sysreg.read ? "mrs" : "msr", + sysreg.op0, sysreg.op1, + sysreg.crn, sysreg.crm, + sysreg.op2, + sysreg.read ? "=>" : "<=", + sysreg.reg, regs->pc); + gdprintk(XENLOG_ERR, "unhandled 64-bit sysreg access %#x", + hsr.bits & HSR_SYSREG_REGS_MASK); +#endif + inject_undef64_exception(regs, sysreg.len); + } } regs->pc += 4; -- 2.39.5