From: Sean Christopherson <seanjc@google.com>
To: Michal Luczaj <mhal@rbox.co>
Cc: kvm@vger.kernel.org, linux-kselftest@vger.kernel.org,
pbonzini@redhat.com, shuah@kernel.org
Subject: Re: [PATCH 1/2] KVM: x86: emulator: Fix illegal LEA handling
Date: Fri, 29 Jul 2022 16:41:48 +0000 [thread overview]
Message-ID: <YuQNzIOGtOep/qGG@google.com> (raw)
In-Reply-To: <20220729134801.1120-1-mhal@rbox.co>
On Fri, Jul 29, 2022, Michal Luczaj wrote:
> The emulator mishandles LEA with register source operand. Even though such
> LEA is illegal, it can be encoded and fed to CPU. In which case real
> hardware throws #UD. The emulator, instead, returns address of
> x86_emulate_ctxt._regs. This info leak hurts host's kASLR.
>
> Tell the decoder that illegal LEA is not to be emulated.
>
> Signed-off-by: Michal Luczaj <mhal@rbox.co>
> ---
> What the emulator does for LEA is simply:
>
> case 0x8d: /* lea r16/r32, m */
> ctxt->dst.val = ctxt->src.addr.mem.ea;
> break;
>
> And it makes sense if you assume that LEA's source operand is always
> memory. But because there is a race window between VM-exit and the decoder
> instruction fetch, emulator can be force fed an arbitrary opcode of choice.
> Including some that are simply illegal and would cause #UD in normal
> circumstances. Such as a LEA with a register-direct source operand -- for
> which the emulator sets `op->addr.reg`, but reads `op->addr.mem.ea`.
>
> union {
> unsigned long *reg;
> struct segmented_address {
> ulong ea;
> unsigned seg;
> } mem;
> ...
> } addr;
>
> Because `reg` and `mem` are in union, emulator reveals address in host's
> memory.
>
> I hope this patch is not considered an `instr_dual` abuse?
Nope, definitely not abuse. This is very similar to how both SVM and VMX usurped
"reserved" Mod=3 (register) encodings from SGDT, SIDT, LGDT, LIDT, and INVLPG
to implement virtualization instructions. I.e. if the Mod=3 encoding is ever
repurposed, then using instr_dual will become necessary. I'm actually somewhat
surprised that Mod=3 hasn't already been repurposed.
> arch/x86/kvm/emulate.c | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
> index f8382abe22ff..7c14706372d0 100644
> --- a/arch/x86/kvm/emulate.c
> +++ b/arch/x86/kvm/emulate.c
> @@ -4566,6 +4566,10 @@ static const struct mode_dual mode_dual_63 = {
> N, I(DstReg | SrcMem32 | ModRM | Mov, em_movsxd)
> };
>
> +static const struct instr_dual instr_dual_8d = {
> + D(DstReg | SrcMem | ModRM | NoAccess), N
> +};
> +
> static const struct opcode opcode_table[256] = {
> /* 0x00 - 0x07 */
> F6ALU(Lock, em_add),
> @@ -4622,7 +4626,7 @@ static const struct opcode opcode_table[256] = {
> I2bv(DstMem | SrcReg | ModRM | Mov | PageTable, em_mov),
> I2bv(DstReg | SrcMem | ModRM | Mov, em_mov),
> I(DstMem | SrcNone | ModRM | Mov | PageTable, em_mov_rm_sreg),
> - D(ModRM | SrcMem | NoAccess | DstReg),
> + ID(0, &instr_dual_8d),
Somewhat tentatively because I'm terrible at reading the emulator's decoder, but
this looks correct...
Reviewed-by: Sean Christopherson <seanjc@google.com>
> I(ImplicitOps | SrcMem16 | ModRM, em_mov_sreg_rm),
> G(0, group1A),
> /* 0x90 - 0x97 */
> --
> 2.32.0
>
prev parent reply other threads:[~2022-07-29 16:42 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-07-29 13:48 [PATCH 1/2] KVM: x86: emulator: Fix illegal LEA handling Michal Luczaj
2022-07-29 13:48 ` [PATCH 2/2] KVM: selftests: x86: Test " Michal Luczaj
2022-07-29 16:53 ` Sean Christopherson
2022-07-31 20:43 ` Michal Luczaj
2022-07-31 20:46 ` [kvm-unit-tests PATCH v2] " Michal Luczaj
2022-08-01 16:44 ` Sean Christopherson
2022-08-02 23:07 ` Michal Luczaj
2022-08-02 23:41 ` Sean Christopherson
2022-08-03 17:21 ` Michal Luczaj
2022-08-03 17:25 ` [kvm-unit-tests PATCH 1/4] x86: emulator.c cleanup: Save and restore exception handlers Michal Luczaj
2022-08-03 17:25 ` [kvm-unit-tests PATCH 2/4] x86: emulator.c cleanup: Use ASM_TRY for the UD_VECTOR cases Michal Luczaj
2022-08-03 18:21 ` Sean Christopherson
2022-08-05 11:42 ` Paolo Bonzini
2022-08-05 18:55 ` Michal Luczaj
2022-08-05 19:59 ` Sean Christopherson
2022-08-06 2:00 ` Nadav Amit
2022-08-06 11:08 ` Michal Luczaj
2022-08-03 17:25 ` [kvm-unit-tests PATCH 3/4] x86: Test emulator's handling of LEA with /reg Michal Luczaj
2022-08-03 17:25 ` [kvm-unit-tests PATCH 4/4] x86: Extend ASM_TRY to handle #UD thrown by FEP-triggered emulator Michal Luczaj
2022-08-03 18:16 ` Sean Christopherson
2022-08-05 11:50 ` Paolo Bonzini
2022-07-29 16:41 ` Sean Christopherson [this message]
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=YuQNzIOGtOep/qGG@google.com \
--to=seanjc@google.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=mhal@rbox.co \
--cc=pbonzini@redhat.com \
--cc=shuah@kernel.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