aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZhichao Huang <zhichao.huang@linaro.org>2017-05-11 08:46:11 -0400
committerChristoffer Dall <cdall@linaro.org>2017-05-15 08:29:19 -0400
commit661e6b02b5aa82db31897f36e96324b77450fd7a (patch)
tree188465d531beaca405cb976c8d123381d2835be7
parent6c0d706b563af732adb094c5bf807437e8963e84 (diff)
KVM: arm: plug potential guest hardware debug leakage
Hardware debugging in guests is not intercepted currently, it means that a malicious guest can bring down the entire machine by writing to the debug registers. This patch enable trapping of all debug registers, preventing the guests to access the debug registers. This includes access to the debug mode(DBGDSCR) in the guest world all the time which could otherwise mess with the host state. Reads return 0 and writes are ignored (RAZ_WI). The result is the guest cannot detect any working hardware based debug support. As debug exceptions are still routed to the guest normal debug using software based breakpoints still works. To support debugging using hardware registers we need to implement a debug register aware world switch as well as special trapping for registers that may affect the host state. Cc: stable@vger.kernel.org Signed-off-by: Zhichao Huang <zhichao.huang@linaro.org> Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Christoffer Dall <cdall@linaro.org> Signed-off-by: Christoffer Dall <cdall@linaro.org>
-rw-r--r--arch/arm/include/asm/kvm_coproc.h3
-rw-r--r--arch/arm/kvm/coproc.c77
-rw-r--r--arch/arm/kvm/handle_exit.c4
-rw-r--r--arch/arm/kvm/hyp/switch.c4
4 files changed, 66 insertions, 22 deletions
diff --git a/arch/arm/include/asm/kvm_coproc.h b/arch/arm/include/asm/kvm_coproc.h
index 4917c2f7e459..e74ab0fbab79 100644
--- a/arch/arm/include/asm/kvm_coproc.h
+++ b/arch/arm/include/asm/kvm_coproc.h
@@ -31,7 +31,8 @@ void kvm_register_target_coproc_table(struct kvm_coproc_target_table *table);
31int kvm_handle_cp10_id(struct kvm_vcpu *vcpu, struct kvm_run *run); 31int kvm_handle_cp10_id(struct kvm_vcpu *vcpu, struct kvm_run *run);
32int kvm_handle_cp_0_13_access(struct kvm_vcpu *vcpu, struct kvm_run *run); 32int kvm_handle_cp_0_13_access(struct kvm_vcpu *vcpu, struct kvm_run *run);
33int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run); 33int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run);
34int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run); 34int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run);
35int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run);
35int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run); 36int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run);
36int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run); 37int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run);
37 38
diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c
index ac8d36da4d08..1403ffb1916b 100644
--- a/arch/arm/kvm/coproc.c
+++ b/arch/arm/kvm/coproc.c
@@ -112,12 +112,6 @@ int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run)
112 return 1; 112 return 1;
113} 113}
114 114
115int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run)
116{
117 kvm_inject_undefined(vcpu);
118 return 1;
119}
120
121static void reset_mpidr(struct kvm_vcpu *vcpu, const struct coproc_reg *r) 115static void reset_mpidr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
122{ 116{
123 /* 117 /*
@@ -533,12 +527,7 @@ static int emulate_cp15(struct kvm_vcpu *vcpu,
533 return 1; 527 return 1;
534} 528}
535 529
536/** 530static struct coproc_params decode_64bit_hsr(struct kvm_vcpu *vcpu)
537 * kvm_handle_cp15_64 -- handles a mrrc/mcrr trap on a guest CP15 access
538 * @vcpu: The VCPU pointer
539 * @run: The kvm_run struct
540 */
541int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
542{ 531{
543 struct coproc_params params; 532 struct coproc_params params;
544 533
@@ -552,9 +541,38 @@ int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
552 params.Rt2 = (kvm_vcpu_get_hsr(vcpu) >> 10) & 0xf; 541 params.Rt2 = (kvm_vcpu_get_hsr(vcpu) >> 10) & 0xf;
553 params.CRm = 0; 542 params.CRm = 0;
554 543
544 return params;
545}
546
547/**
548 * kvm_handle_cp15_64 -- handles a mrrc/mcrr trap on a guest CP15 access
549 * @vcpu: The VCPU pointer
550 * @run: The kvm_run struct
551 */
552int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
553{
554 struct coproc_params params = decode_64bit_hsr(vcpu);
555
555 return emulate_cp15(vcpu, &params); 556 return emulate_cp15(vcpu, &params);
556} 557}
557 558
559/**
560 * kvm_handle_cp14_64 -- handles a mrrc/mcrr trap on a guest CP14 access
561 * @vcpu: The VCPU pointer
562 * @run: The kvm_run struct
563 */
564int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
565{
566 struct coproc_params params = decode_64bit_hsr(vcpu);
567
568 /* raz_wi cp14 */
569 pm_fake(vcpu, &params, NULL);
570
571 /* handled */
572 kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
573 return 1;
574}
575
558static void reset_coproc_regs(struct kvm_vcpu *vcpu, 576static void reset_coproc_regs(struct kvm_vcpu *vcpu,
559 const struct coproc_reg *table, size_t num) 577 const struct coproc_reg *table, size_t num)
560{ 578{
@@ -565,12 +583,7 @@ static void reset_coproc_regs(struct kvm_vcpu *vcpu,
565 table[i].reset(vcpu, &table[i]); 583 table[i].reset(vcpu, &table[i]);
566} 584}
567 585
568/** 586static struct coproc_params decode_32bit_hsr(struct kvm_vcpu *vcpu)
569 * kvm_handle_cp15_32 -- handles a mrc/mcr trap on a guest CP15 access
570 * @vcpu: The VCPU pointer
571 * @run: The kvm_run struct
572 */
573int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
574{ 587{
575 struct coproc_params params; 588 struct coproc_params params;
576 589
@@ -584,9 +597,37 @@ int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
584 params.Op2 = (kvm_vcpu_get_hsr(vcpu) >> 17) & 0x7; 597 params.Op2 = (kvm_vcpu_get_hsr(vcpu) >> 17) & 0x7;
585 params.Rt2 = 0; 598 params.Rt2 = 0;
586 599
600 return params;
601}
602
603/**
604 * kvm_handle_cp15_32 -- handles a mrc/mcr trap on a guest CP15 access
605 * @vcpu: The VCPU pointer
606 * @run: The kvm_run struct
607 */
608int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
609{
610 struct coproc_params params = decode_32bit_hsr(vcpu);
587 return emulate_cp15(vcpu, &params); 611 return emulate_cp15(vcpu, &params);
588} 612}
589 613
614/**
615 * kvm_handle_cp14_32 -- handles a mrc/mcr trap on a guest CP14 access
616 * @vcpu: The VCPU pointer
617 * @run: The kvm_run struct
618 */
619int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
620{
621 struct coproc_params params = decode_32bit_hsr(vcpu);
622
623 /* raz_wi cp14 */
624 pm_fake(vcpu, &params, NULL);
625
626 /* handled */
627 kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
628 return 1;
629}
630
590/****************************************************************************** 631/******************************************************************************
591 * Userspace API 632 * Userspace API
592 *****************************************************************************/ 633 *****************************************************************************/
diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
index 5fd7968cdae9..f86a9aaef462 100644
--- a/arch/arm/kvm/handle_exit.c
+++ b/arch/arm/kvm/handle_exit.c
@@ -95,9 +95,9 @@ static exit_handle_fn arm_exit_handlers[] = {
95 [HSR_EC_WFI] = kvm_handle_wfx, 95 [HSR_EC_WFI] = kvm_handle_wfx,
96 [HSR_EC_CP15_32] = kvm_handle_cp15_32, 96 [HSR_EC_CP15_32] = kvm_handle_cp15_32,
97 [HSR_EC_CP15_64] = kvm_handle_cp15_64, 97 [HSR_EC_CP15_64] = kvm_handle_cp15_64,
98 [HSR_EC_CP14_MR] = kvm_handle_cp14_access, 98 [HSR_EC_CP14_MR] = kvm_handle_cp14_32,
99 [HSR_EC_CP14_LS] = kvm_handle_cp14_load_store, 99 [HSR_EC_CP14_LS] = kvm_handle_cp14_load_store,
100 [HSR_EC_CP14_64] = kvm_handle_cp14_access, 100 [HSR_EC_CP14_64] = kvm_handle_cp14_64,
101 [HSR_EC_CP_0_13] = kvm_handle_cp_0_13_access, 101 [HSR_EC_CP_0_13] = kvm_handle_cp_0_13_access,
102 [HSR_EC_CP10_ID] = kvm_handle_cp10_id, 102 [HSR_EC_CP10_ID] = kvm_handle_cp10_id,
103 [HSR_EC_HVC] = handle_hvc, 103 [HSR_EC_HVC] = handle_hvc,
diff --git a/arch/arm/kvm/hyp/switch.c b/arch/arm/kvm/hyp/switch.c
index 92678b7bd046..624a510d31df 100644
--- a/arch/arm/kvm/hyp/switch.c
+++ b/arch/arm/kvm/hyp/switch.c
@@ -48,7 +48,9 @@ static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu, u32 *fpexc_host)
48 write_sysreg(HSTR_T(15), HSTR); 48 write_sysreg(HSTR_T(15), HSTR);
49 write_sysreg(HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11), HCPTR); 49 write_sysreg(HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11), HCPTR);
50 val = read_sysreg(HDCR); 50 val = read_sysreg(HDCR);
51 write_sysreg(val | HDCR_TPM | HDCR_TPMCR, HDCR); 51 val |= HDCR_TPM | HDCR_TPMCR; /* trap performance monitors */
52 val |= HDCR_TDRA | HDCR_TDOSA | HDCR_TDA; /* trap debug regs */
53 write_sysreg(val, HDCR);
52} 54}
53 55
54static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu) 56static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu)