From: christoffer.dall@linaro.org (Christoffer Dall)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v3 01/11] KVM: arm: plug guest debug exploit
Date: Wed, 1 Jul 2015 11:00:00 +0200 [thread overview]
Message-ID: <20150701090000.GD11332@cbox> (raw)
In-Reply-To: <0DE86164-5740-4894-A41C-DBCD930196AC@linaro.org>
On Wed, Jul 01, 2015 at 03:04:00PM +0800, zichao wrote:
>
>
> On June 29, 2015 11:49:53 PM GMT+08:00, Christoffer Dall <christoffer.dall@linaro.org> wrote:
> >On Mon, Jun 22, 2015 at 06:41:24PM +0800, Zhichao Huang wrote:
> >> 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 patch also disable the debug mode(DBGDSCR) in the guest world
> >all
> >> the time, preventing the guests to mess with the host state.
> >>
> >> However, it is a precursor for later patches which will need to do
> >> more to world switch debug states while necessary.
> >>
> >> Cc: <stable@vger.kernel.org>
> >> Signed-off-by: Zhichao Huang <zhichao.huang@linaro.org>
> >> ---
> >> arch/arm/include/asm/kvm_coproc.h | 3 +-
> >> arch/arm/kvm/coproc.c | 60
> >+++++++++++++++++++++++++++++++++++----
> >> arch/arm/kvm/handle_exit.c | 4 +--
> >> arch/arm/kvm/interrupts_head.S | 13 ++++++++-
> >> 4 files changed, 70 insertions(+), 10 deletions(-)
> >>
> >> diff --git a/arch/arm/include/asm/kvm_coproc.h
> >b/arch/arm/include/asm/kvm_coproc.h
> >> index 4917c2f..e74ab0f 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);
> >> int kvm_handle_cp10_id(struct kvm_vcpu *vcpu, struct kvm_run *run);
> >> int kvm_handle_cp_0_13_access(struct kvm_vcpu *vcpu, struct kvm_run
> >*run);
> >> int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run
> >*run);
> >> -int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run
> >*run);
> >> +int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run);
> >> +int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run);
> >> int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run);
> >> int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run);
> >>
> >> diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c
> >> index f3d88dc..2e12760 100644
> >> --- a/arch/arm/kvm/coproc.c
> >> +++ b/arch/arm/kvm/coproc.c
> >> @@ -91,12 +91,6 @@ int kvm_handle_cp14_load_store(struct kvm_vcpu
> >*vcpu, struct kvm_run *run)
> >> return 1;
> >> }
> >>
> >> -int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run
> >*run)
> >> -{
> >> - kvm_inject_undefined(vcpu);
> >> - return 1;
> >> -}
> >> -
> >> static void reset_mpidr(struct kvm_vcpu *vcpu, const struct
> >coproc_reg *r)
> >> {
> >> /*
> >> @@ -519,6 +513,60 @@ int kvm_handle_cp15_32(struct kvm_vcpu *vcpu,
> >struct kvm_run *run)
> >> return emulate_cp15(vcpu, ¶ms);
> >> }
> >>
> >> +/**
> >> + * kvm_handle_cp14_64 -- handles a mrrc/mcrr trap on a guest CP14
> >access
> >> + * @vcpu: The VCPU pointer
> >> + * @run: The kvm_run struct
> >> + */
> >> +int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
> >> +{
> >> + struct coproc_params params;
> >> +
> >> + params.CRn = (kvm_vcpu_get_hsr(vcpu) >> 1) & 0xf;
> >> + params.Rt1 = (kvm_vcpu_get_hsr(vcpu) >> 5) & 0xf;
> >> + params.is_write = ((kvm_vcpu_get_hsr(vcpu) & 1) == 0);
> >> + params.is_64bit = true;
> >> +
> >> + params.Op1 = (kvm_vcpu_get_hsr(vcpu) >> 16) & 0xf;
> >> + params.Op2 = 0;
> >> + params.Rt2 = (kvm_vcpu_get_hsr(vcpu) >> 10) & 0xf;
> >> + params.CRm = 0;
> >
> >this is a complete duplicate of kvm_handle_cp15_64, can you share this
> >code somehow?
> >
>
> This patch just want to plug the exploit in the simplest way, and I shared the cp14/cp15 handlers in later patches [PATCH v3 04/11].
>
> Should I take the patch [04/11] ahead of current patch [01/11] ?
>
It would be good if the patch that we can cc stable and which fixes the
issue is self-contained. If it's impossible to do that while sharing
the handlers (I don't see why, but I didn't write the code) then ok, but
otherwise just add that bit of code into this patch I would say.
> >> +
> >> + /* raz_wi */
> >> + (void)pm_fake(vcpu, ¶ms, NULL);
> >> +
> >> + /* handled */
> >> + kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
> >> + return 1;
> >> +}
> >> +
> >> +/**
> >> + * kvm_handle_cp14_32 -- handles a mrc/mcr trap on a guest CP14
> >access
> >> + * @vcpu: The VCPU pointer
> >> + * @run: The kvm_run struct
> >> + */
> >> +int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
> >> +{
> >> + struct coproc_params params;
> >> +
> >> + params.CRm = (kvm_vcpu_get_hsr(vcpu) >> 1) & 0xf;
> >> + params.Rt1 = (kvm_vcpu_get_hsr(vcpu) >> 5) & 0xf;
> >> + params.is_write = ((kvm_vcpu_get_hsr(vcpu) & 1) == 0);
> >> + params.is_64bit = false;
> >> +
> >> + params.CRn = (kvm_vcpu_get_hsr(vcpu) >> 10) & 0xf;
> >> + params.Op1 = (kvm_vcpu_get_hsr(vcpu) >> 14) & 0x7;
> >> + params.Op2 = (kvm_vcpu_get_hsr(vcpu) >> 17) & 0x7;
> >> + params.Rt2 = 0;
> >
> >this is a complete duplicate of kvm_handle_cp15_32, can you share this
> >code somehow?
> >
> >> +
> >> + /* raz_wi */
> >> + (void)pm_fake(vcpu, ¶ms, NULL);
> >> +
> >> + /* handled */
> >> + kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
> >> + return 1;
> >> +}
> >> +
> >>
> >/******************************************************************************
> >> * Userspace API
> >>
> >*****************************************************************************/
> >> diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
> >> index 95f12b2..357ad1b 100644
> >> --- a/arch/arm/kvm/handle_exit.c
> >> +++ b/arch/arm/kvm/handle_exit.c
> >> @@ -104,9 +104,9 @@ static exit_handle_fn arm_exit_handlers[] = {
> >> [HSR_EC_WFI] = kvm_handle_wfx,
> >> [HSR_EC_CP15_32] = kvm_handle_cp15_32,
> >> [HSR_EC_CP15_64] = kvm_handle_cp15_64,
> >> - [HSR_EC_CP14_MR] = kvm_handle_cp14_access,
> >> + [HSR_EC_CP14_MR] = kvm_handle_cp14_32,
> >> [HSR_EC_CP14_LS] = kvm_handle_cp14_load_store,
> >> - [HSR_EC_CP14_64] = kvm_handle_cp14_access,
> >> + [HSR_EC_CP14_64] = kvm_handle_cp14_64,
> >> [HSR_EC_CP_0_13] = kvm_handle_cp_0_13_access,
> >> [HSR_EC_CP10_ID] = kvm_handle_cp10_id,
> >> [HSR_EC_SVC_HYP] = handle_svc_hyp,
> >> diff --git a/arch/arm/kvm/interrupts_head.S
> >b/arch/arm/kvm/interrupts_head.S
> >> index 35e4a3a..f85c447 100644
> >> --- a/arch/arm/kvm/interrupts_head.S
> >> +++ b/arch/arm/kvm/interrupts_head.S
> >> @@ -97,6 +97,10 @@ vcpu .req r0 @ vcpu pointer always in r0
> >> mrs r8, LR_fiq
> >> mrs r9, SPSR_fiq
> >> push {r2-r9}
> >> +
> >> + /* DBGDSCR reg */
> >> + mrc p14, 0, r2, c0, c1, 0
> >> + push {r2}
> >
> >this feels like it should belong in read_cp15_state and not the gp regs
> >portion ?
> >
>
> Happy to move it. But moving the cp14 regs to read/write_cp15_state still seems no very appropriate. Should I move it to __kvm_vcpu_return and __kvm_vcpu_run?
you should probably rename read_cp15_state to read_coproc_state then.
>
> Another reason might be that, I want to disable debug mode (DBGDSCR) as early as possible.
>
Why? The world-switch code is atomic in that sense is it not?
> >
> >> .endm
> >>
> >> .macro pop_host_regs_mode mode
> >> @@ -111,6 +115,9 @@ vcpu .req r0 @ vcpu pointer always in r0
> >> * Clobbers all registers, in all modes, except r0 and r1.
> >> */
> >> .macro restore_host_regs
> >> + pop {r2}
> >> + mcr p14, 0, r2, c0, c2, 2
> >> +
> >
> >Why are we reading the DBGDSCRint and writing the DBGDSCRext ?
>
> Because the DBGDSCRint is read-only, and I borrowed the operation from kernel.
>
> arch/arm/kernel/hw_breakpoint.c:
> ARM_DBG_READ(c0, c1, 0, dscr)
> ARM_DBG_WRITE(c0, c2, 2, dscr)
> >
> >> pop {r2-r9}
> >> msr r8_fiq, r2
> >> msr r9_fiq, r3
> >> @@ -159,6 +166,10 @@ vcpu .req r0 @ vcpu pointer always in r0
> >> * Clobbers *all* registers.
> >> */
> >> .macro restore_guest_regs
> >> + /* reset DBGDSCR to disable debug mode */
> >> + mov r2, #0
> >> + mcr p14, 0, r2, c0, c2, 2
> >
> >Is it valid to write 0 in all all fields of this register?
>
> I'm afraid of it too, although it tests ok. Does Will have any suggestions?
> >
> >I thought Will expressed concern about accessing this register? Why is
> >it safe in this context and not before? It seems from the spec that
> >this can still raise an undefined exception if an external debugger
> >lowers the software debug enable signal.
> >
> >> +
> >> restore_guest_regs_mode svc, #VCPU_SVC_REGS
> >> restore_guest_regs_mode abt, #VCPU_ABT_REGS
> >> restore_guest_regs_mode und, #VCPU_UND_REGS
> >> @@ -607,7 +618,7 @@ ARM_BE8(rev r6, r6 )
> >> * (hardware reset value is 0) */
> >> .macro set_hdcr operation
> >> mrc p15, 4, r2, c1, c1, 1
> >> - ldr r3, =(HDCR_TPM|HDCR_TPMCR)
> >> + ldr r3, =(HDCR_TPM|HDCR_TPMCR|HDCR_TDRA|HDCR_TDOSA|HDCR_TDA)
> >> .if \operation == vmentry
> >> orr r2, r2, r3 @ Trap some perfmon accesses
> >> .else
> >> --
> >> 1.7.12.4
> >>
> >
> >Thanks,
> >-Christoffer
>
> --
> zhichao.huang
next prev parent reply other threads:[~2015-07-01 9:00 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-06-22 10:41 [PATCH v3 00/11] KVM: arm: debug infrastructure support Zhichao Huang
2015-06-22 10:41 ` [PATCH v3 01/11] KVM: arm: plug guest debug exploit Zhichao Huang
2015-06-29 15:49 ` Christoffer Dall
2015-07-01 7:04 ` zichao
2015-07-01 9:00 ` Christoffer Dall [this message]
2015-06-22 10:41 ` [PATCH v3 02/11] KVM: arm: rename pm_fake handler to trap_raz_wi Zhichao Huang
2015-06-30 13:20 ` Christoffer Dall
2015-06-22 10:41 ` [PATCH v3 03/11] KVM: arm: enable to use the ARM_DSCR_MDBGEN macro from KVM assembly code Zhichao Huang
2015-06-30 13:20 ` Christoffer Dall
2015-06-22 10:41 ` [PATCH v3 04/11] KVM: arm: common infrastructure for handling AArch32 CP14/CP15 Zhichao Huang
2015-06-29 19:43 ` Christoffer Dall
2015-07-01 7:09 ` zichao
2015-07-01 9:00 ` Christoffer Dall
2015-06-22 10:41 ` [PATCH v3 05/11] KVM: arm: check ordering of all system register tables Zhichao Huang
2015-06-30 13:20 ` Christoffer Dall
2015-06-22 10:41 ` [PATCH v3 06/11] KVM: arm: add trap handlers for 32-bit debug registers Zhichao Huang
2015-06-29 21:16 ` Christoffer Dall
2015-07-01 7:14 ` zichao
2015-06-22 10:41 ` [PATCH v3 07/11] KVM: arm: add trap handlers for 64-bit " Zhichao Huang
2015-06-30 13:20 ` Christoffer Dall
2015-07-01 7:43 ` Zhichao Huang
2015-06-22 10:41 ` [PATCH v3 08/11] KVM: arm: implement dirty bit mechanism for " Zhichao Huang
2015-06-30 9:20 ` Christoffer Dall
2015-07-03 9:54 ` Zhichao Huang
2015-07-03 11:56 ` Christoffer Dall
2015-07-07 10:06 ` Zhichao Huang
2015-07-07 10:24 ` Will Deacon
2015-07-08 10:50 ` Zhichao Huang
2015-07-08 17:08 ` Will Deacon
2015-07-09 12:54 ` Zhichao Huang
2015-07-09 11:50 ` Christoffer Dall
2015-07-13 12:12 ` zichao
2015-06-22 10:41 ` [PATCH v3 09/11] KVM: arm: implement lazy world switch " Zhichao Huang
2015-06-30 13:15 ` Christoffer Dall
2015-07-03 10:06 ` Zhichao Huang
2015-07-03 21:05 ` Christoffer Dall
2015-06-22 10:41 ` [PATCH v3 10/11] KVM: arm: add a trace event for cp14 traps Zhichao Huang
2015-06-30 13:20 ` Christoffer Dall
2015-06-22 10:41 ` [PATCH v3 11/11] KVM: arm: enable trapping of all debug registers Zhichao Huang
2015-06-30 13:19 ` Christoffer Dall
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150701090000.GD11332@cbox \
--to=christoffer.dall@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).