Skip to content

Commit 129a72a

Browse files
stevenrutherfordbonzini
authored andcommitted
KVM: x86: Introduce segmented_write_std
Introduces segemented_write_std. Switches from emulated reads/writes to standard read/writes in fxsave, fxrstor, sgdt, and sidt. This fixes CVE-2017-2584, a longstanding kernel memory leak. Since commit 283c95d ("KVM: x86: emulate FXSAVE and FXRSTOR", 2016-11-09), which is luckily not yet in any final release, this would also be an exploitable kernel memory *write*! Reported-by: Dmitry Vyukov <[email protected]> Cc: [email protected] Fixes: 9605157 Fixes: 283c95d Suggested-by: Paolo Bonzini <[email protected]> Signed-off-by: Steve Rutherford <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent cef84c3 commit 129a72a

File tree

1 file changed

+18
-4
lines changed

1 file changed

+18
-4
lines changed

arch/x86/kvm/emulate.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,20 @@ static int segmented_read_std(struct x86_emulate_ctxt *ctxt,
818818
return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception);
819819
}
820820

821+
static int segmented_write_std(struct x86_emulate_ctxt *ctxt,
822+
struct segmented_address addr,
823+
void *data,
824+
unsigned int size)
825+
{
826+
int rc;
827+
ulong linear;
828+
829+
rc = linearize(ctxt, addr, size, true, &linear);
830+
if (rc != X86EMUL_CONTINUE)
831+
return rc;
832+
return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception);
833+
}
834+
821835
/*
822836
* Prefetch the remaining bytes of the instruction without crossing page
823837
* boundary if they are not in fetch_cache yet.
@@ -3685,8 +3699,8 @@ static int emulate_store_desc_ptr(struct x86_emulate_ctxt *ctxt,
36853699
}
36863700
/* Disable writeback. */
36873701
ctxt->dst.type = OP_NONE;
3688-
return segmented_write(ctxt, ctxt->dst.addr.mem,
3689-
&desc_ptr, 2 + ctxt->op_bytes);
3702+
return segmented_write_std(ctxt, ctxt->dst.addr.mem,
3703+
&desc_ptr, 2 + ctxt->op_bytes);
36903704
}
36913705

36923706
static int em_sgdt(struct x86_emulate_ctxt *ctxt)
@@ -3932,7 +3946,7 @@ static int em_fxsave(struct x86_emulate_ctxt *ctxt)
39323946
else
39333947
size = offsetof(struct fxregs_state, xmm_space[0]);
39343948

3935-
return segmented_write(ctxt, ctxt->memop.addr.mem, &fx_state, size);
3949+
return segmented_write_std(ctxt, ctxt->memop.addr.mem, &fx_state, size);
39363950
}
39373951

39383952
static int fxrstor_fixup(struct x86_emulate_ctxt *ctxt,
@@ -3974,7 +3988,7 @@ static int em_fxrstor(struct x86_emulate_ctxt *ctxt)
39743988
if (rc != X86EMUL_CONTINUE)
39753989
return rc;
39763990

3977-
rc = segmented_read(ctxt, ctxt->memop.addr.mem, &fx_state, 512);
3991+
rc = segmented_read_std(ctxt, ctxt->memop.addr.mem, &fx_state, 512);
39783992
if (rc != X86EMUL_CONTINUE)
39793993
return rc;
39803994

0 commit comments

Comments
 (0)