Linux v3.18-rc1-422-g2cc91884b6b3
This commit is contained in:
parent
df84d54e05
commit
f42901a61c
@ -1,37 +0,0 @@
|
|||||||
From: Paolo Bonzini <pbonzini@redhat.com>
|
|
||||||
Date: Fri, 24 Oct 2014 17:07:21 +0200
|
|
||||||
Subject: [PATCH] KVM: emulate: avoid accessing NULL ctxt->memopp
|
|
||||||
|
|
||||||
A failure to decode the instruction can cause a NULL pointer access.
|
|
||||||
This is fixed simply by moving the "done" label as close as possible
|
|
||||||
to the return.
|
|
||||||
|
|
||||||
This fixes CVE-2014-8481.
|
|
||||||
|
|
||||||
Reported-by: Andy Lutomirski <luto@amacapital.net>
|
|
||||||
Cc: stable@vger.kernel.org
|
|
||||||
Fixes: 41061cdb98a0bec464278b4db8e894a3121671f5
|
|
||||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
||||||
---
|
|
||||||
arch/x86/kvm/emulate.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
|
|
||||||
index 02c8ea804aaf..eb3b1c46f995 100644
|
|
||||||
--- a/arch/x86/kvm/emulate.c
|
|
||||||
+++ b/arch/x86/kvm/emulate.c
|
|
||||||
@@ -4580,10 +4580,10 @@ done_prefixes:
|
|
||||||
/* Decode and fetch the destination operand: register or memory. */
|
|
||||||
rc = decode_operand(ctxt, &ctxt->dst, (ctxt->d >> DstShift) & OpMask);
|
|
||||||
|
|
||||||
-done:
|
|
||||||
if (ctxt->rip_relative)
|
|
||||||
ctxt->memopp->addr.mem.ea += ctxt->_eip;
|
|
||||||
|
|
||||||
+done:
|
|
||||||
return (rc != X86EMUL_CONTINUE) ? EMULATION_FAILED : EMULATION_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
1.9.3
|
|
||||||
|
|
@ -1,145 +0,0 @@
|
|||||||
From: Nadav Amit <namit@cs.technion.ac.il>
|
|
||||||
Date: Fri, 24 Oct 2014 17:07:12 +0200
|
|
||||||
Subject: [PATCH] KVM: x86: Check non-canonical addresses upon WRMSR
|
|
||||||
|
|
||||||
Upon WRMSR, the CPU should inject #GP if a non-canonical value (address) is
|
|
||||||
written to certain MSRs. The behavior is "almost" identical for AMD and Intel
|
|
||||||
(ignoring MSRs that are not implemented in either architecture since they would
|
|
||||||
anyhow #GP). However, IA32_SYSENTER_ESP and IA32_SYSENTER_EIP cause #GP if
|
|
||||||
non-canonical address is written on Intel but not on AMD (which ignores the top
|
|
||||||
32-bits).
|
|
||||||
|
|
||||||
Accordingly, this patch injects a #GP on the MSRs which behave identically on
|
|
||||||
Intel and AMD. To eliminate the differences between the architecutres, the
|
|
||||||
value which is written to IA32_SYSENTER_ESP and IA32_SYSENTER_EIP is turned to
|
|
||||||
canonical value before writing instead of injecting a #GP.
|
|
||||||
|
|
||||||
Some references from Intel and AMD manuals:
|
|
||||||
|
|
||||||
According to Intel SDM description of WRMSR instruction #GP is expected on
|
|
||||||
WRMSR "If the source register contains a non-canonical address and ECX
|
|
||||||
specifies one of the following MSRs: IA32_DS_AREA, IA32_FS_BASE, IA32_GS_BASE,
|
|
||||||
IA32_KERNEL_GS_BASE, IA32_LSTAR, IA32_SYSENTER_EIP, IA32_SYSENTER_ESP."
|
|
||||||
|
|
||||||
According to AMD manual instruction manual:
|
|
||||||
LSTAR/CSTAR (SYSCALL): "The WRMSR instruction loads the target RIP into the
|
|
||||||
LSTAR and CSTAR registers. If an RIP written by WRMSR is not in canonical
|
|
||||||
form, a general-protection exception (#GP) occurs."
|
|
||||||
IA32_GS_BASE and IA32_FS_BASE (WRFSBASE/WRGSBASE): "The address written to the
|
|
||||||
base field must be in canonical form or a #GP fault will occur."
|
|
||||||
IA32_KERNEL_GS_BASE (SWAPGS): "The address stored in the KernelGSbase MSR must
|
|
||||||
be in canonical form."
|
|
||||||
|
|
||||||
This patch fixes CVE-2014-3610.
|
|
||||||
|
|
||||||
Cc: stable@vger.kernel.org
|
|
||||||
Signed-off-by: Nadav Amit <namit@cs.technion.ac.il>
|
|
||||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
||||||
---
|
|
||||||
arch/x86/include/asm/kvm_host.h | 14 ++++++++++++++
|
|
||||||
arch/x86/kvm/svm.c | 2 +-
|
|
||||||
arch/x86/kvm/vmx.c | 2 +-
|
|
||||||
arch/x86/kvm/x86.c | 27 ++++++++++++++++++++++++++-
|
|
||||||
4 files changed, 42 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
|
|
||||||
index 7d603a71ab3a..ccc94de4ac49 100644
|
|
||||||
--- a/arch/x86/include/asm/kvm_host.h
|
|
||||||
+++ b/arch/x86/include/asm/kvm_host.h
|
|
||||||
@@ -989,6 +989,20 @@ static inline void kvm_inject_gp(struct kvm_vcpu *vcpu, u32 error_code)
|
|
||||||
kvm_queue_exception_e(vcpu, GP_VECTOR, error_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
+static inline u64 get_canonical(u64 la)
|
|
||||||
+{
|
|
||||||
+ return ((int64_t)la << 16) >> 16;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline bool is_noncanonical_address(u64 la)
|
|
||||||
+{
|
|
||||||
+#ifdef CONFIG_X86_64
|
|
||||||
+ return get_canonical(la) != la;
|
|
||||||
+#else
|
|
||||||
+ return false;
|
|
||||||
+#endif
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
#define TSS_IOPB_BASE_OFFSET 0x66
|
|
||||||
#define TSS_BASE_SIZE 0x68
|
|
||||||
#define TSS_IOPB_SIZE (65536 / 8)
|
|
||||||
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
|
|
||||||
index 65510f624dfe..00bed2c5e948 100644
|
|
||||||
--- a/arch/x86/kvm/svm.c
|
|
||||||
+++ b/arch/x86/kvm/svm.c
|
|
||||||
@@ -3251,7 +3251,7 @@ static int wrmsr_interception(struct vcpu_svm *svm)
|
|
||||||
msr.host_initiated = false;
|
|
||||||
|
|
||||||
svm->next_rip = kvm_rip_read(&svm->vcpu) + 2;
|
|
||||||
- if (svm_set_msr(&svm->vcpu, &msr)) {
|
|
||||||
+ if (kvm_set_msr(&svm->vcpu, &msr)) {
|
|
||||||
trace_kvm_msr_write_ex(ecx, data);
|
|
||||||
kvm_inject_gp(&svm->vcpu, 0);
|
|
||||||
} else {
|
|
||||||
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
|
|
||||||
index 0acac81f198b..148020a7dd98 100644
|
|
||||||
--- a/arch/x86/kvm/vmx.c
|
|
||||||
+++ b/arch/x86/kvm/vmx.c
|
|
||||||
@@ -5291,7 +5291,7 @@ static int handle_wrmsr(struct kvm_vcpu *vcpu)
|
|
||||||
msr.data = data;
|
|
||||||
msr.index = ecx;
|
|
||||||
msr.host_initiated = false;
|
|
||||||
- if (vmx_set_msr(vcpu, &msr) != 0) {
|
|
||||||
+ if (kvm_set_msr(vcpu, &msr) != 0) {
|
|
||||||
trace_kvm_msr_write_ex(ecx, data);
|
|
||||||
kvm_inject_gp(vcpu, 0);
|
|
||||||
return 1;
|
|
||||||
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
|
|
||||||
index 34c8f94331f8..5a7195573a32 100644
|
|
||||||
--- a/arch/x86/kvm/x86.c
|
|
||||||
+++ b/arch/x86/kvm/x86.c
|
|
||||||
@@ -987,7 +987,6 @@ void kvm_enable_efer_bits(u64 mask)
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(kvm_enable_efer_bits);
|
|
||||||
|
|
||||||
-
|
|
||||||
/*
|
|
||||||
* Writes msr value into into the appropriate "register".
|
|
||||||
* Returns 0 on success, non-0 otherwise.
|
|
||||||
@@ -995,8 +994,34 @@ EXPORT_SYMBOL_GPL(kvm_enable_efer_bits);
|
|
||||||
*/
|
|
||||||
int kvm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
|
|
||||||
{
|
|
||||||
+ switch (msr->index) {
|
|
||||||
+ case MSR_FS_BASE:
|
|
||||||
+ case MSR_GS_BASE:
|
|
||||||
+ case MSR_KERNEL_GS_BASE:
|
|
||||||
+ case MSR_CSTAR:
|
|
||||||
+ case MSR_LSTAR:
|
|
||||||
+ if (is_noncanonical_address(msr->data))
|
|
||||||
+ return 1;
|
|
||||||
+ break;
|
|
||||||
+ case MSR_IA32_SYSENTER_EIP:
|
|
||||||
+ case MSR_IA32_SYSENTER_ESP:
|
|
||||||
+ /*
|
|
||||||
+ * IA32_SYSENTER_ESP and IA32_SYSENTER_EIP cause #GP if
|
|
||||||
+ * non-canonical address is written on Intel but not on
|
|
||||||
+ * AMD (which ignores the top 32-bits, because it does
|
|
||||||
+ * not implement 64-bit SYSENTER).
|
|
||||||
+ *
|
|
||||||
+ * 64-bit code should hence be able to write a non-canonical
|
|
||||||
+ * value on AMD. Making the address canonical ensures that
|
|
||||||
+ * vmentry does not fail on Intel after writing a non-canonical
|
|
||||||
+ * value, and that something deterministic happens if the guest
|
|
||||||
+ * invokes 64-bit SYSENTER.
|
|
||||||
+ */
|
|
||||||
+ msr->data = get_canonical(msr->data);
|
|
||||||
+ }
|
|
||||||
return kvm_x86_ops->set_msr(vcpu, msr);
|
|
||||||
}
|
|
||||||
+EXPORT_SYMBOL_GPL(kvm_set_msr);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Adapt set_msr() to msr_io()'s calling convention
|
|
||||||
--
|
|
||||||
1.9.3
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
|||||||
From: Nadav Amit <namit@cs.technion.ac.il>
|
|
||||||
Date: Fri, 24 Oct 2014 17:07:20 +0200
|
|
||||||
Subject: [PATCH] KVM: x86: Decoding guest instructions which cross page
|
|
||||||
boundary may fail
|
|
||||||
|
|
||||||
Once an instruction crosses a page boundary, the size read from the second page
|
|
||||||
disregards the common case that part of the operand resides on the first page.
|
|
||||||
As a result, fetch of long insturctions may fail, and thereby cause the
|
|
||||||
decoding to fail as well.
|
|
||||||
|
|
||||||
Cc: stable@vger.kernel.org
|
|
||||||
Fixes: 5cfc7e0f5e5e1adf998df94f8e36edaf5d30d38e
|
|
||||||
Signed-off-by: Nadav Amit <namit@cs.technion.ac.il>
|
|
||||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
||||||
---
|
|
||||||
arch/x86/kvm/emulate.c | 6 ++++--
|
|
||||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
|
|
||||||
index c0deaff8d9f0..02c8ea804aaf 100644
|
|
||||||
--- a/arch/x86/kvm/emulate.c
|
|
||||||
+++ b/arch/x86/kvm/emulate.c
|
|
||||||
@@ -778,8 +778,10 @@ static int __do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt, int op_size)
|
|
||||||
static __always_inline int do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt,
|
|
||||||
unsigned size)
|
|
||||||
{
|
|
||||||
- if (unlikely(ctxt->fetch.end - ctxt->fetch.ptr < size))
|
|
||||||
- return __do_insn_fetch_bytes(ctxt, size);
|
|
||||||
+ unsigned done_size = ctxt->fetch.end - ctxt->fetch.ptr;
|
|
||||||
+
|
|
||||||
+ if (unlikely(done_size < size))
|
|
||||||
+ return __do_insn_fetch_bytes(ctxt, size - done_size);
|
|
||||||
else
|
|
||||||
return X86EMUL_CONTINUE;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
1.9.3
|
|
||||||
|
|
@ -1,77 +0,0 @@
|
|||||||
From: Nadav Amit <namit@cs.technion.ac.il>
|
|
||||||
Date: Fri, 24 Oct 2014 17:07:22 +0200
|
|
||||||
Subject: [PATCH] KVM: x86: Emulator does not decode clflush well
|
|
||||||
|
|
||||||
Currently, all group15 instructions are decoded as clflush (e.g., mfence,
|
|
||||||
xsave). In addition, the clflush instruction requires no prefix (66/f2/f3)
|
|
||||||
would exist. If prefix exists it may encode a different instruction (e.g.,
|
|
||||||
clflushopt).
|
|
||||||
|
|
||||||
Creating a group for clflush, and different group for each prefix.
|
|
||||||
|
|
||||||
This has been the case forever, but the next patch needs the cflush group
|
|
||||||
in order to fix a bug introduced in 3.17.
|
|
||||||
|
|
||||||
Fixes: 41061cdb98a0bec464278b4db8e894a3121671f5
|
|
||||||
Cc: stable@vger.kernel.org
|
|
||||||
Signed-off-by: Nadav Amit <namit@cs.technion.ac.il>
|
|
||||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
||||||
---
|
|
||||||
arch/x86/kvm/emulate.c | 20 +++++++++++++++++---
|
|
||||||
1 file changed, 17 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
|
|
||||||
index eb3b1c46f995..97da5034d812 100644
|
|
||||||
--- a/arch/x86/kvm/emulate.c
|
|
||||||
+++ b/arch/x86/kvm/emulate.c
|
|
||||||
@@ -3462,6 +3462,12 @@ static int em_bswap(struct x86_emulate_ctxt *ctxt)
|
|
||||||
return X86EMUL_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int em_clflush(struct x86_emulate_ctxt *ctxt)
|
|
||||||
+{
|
|
||||||
+ /* emulating clflush regardless of cpuid */
|
|
||||||
+ return X86EMUL_CONTINUE;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static bool valid_cr(int nr)
|
|
||||||
{
|
|
||||||
switch (nr) {
|
|
||||||
@@ -3800,6 +3806,16 @@ static const struct opcode group11[] = {
|
|
||||||
X7(D(Undefined)),
|
|
||||||
};
|
|
||||||
|
|
||||||
+static const struct gprefix pfx_0f_ae_7 = {
|
|
||||||
+ I(0, em_clflush), N, N, N,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static const struct group_dual group15 = { {
|
|
||||||
+ N, N, N, N, N, N, N, GP(0, &pfx_0f_ae_7),
|
|
||||||
+}, {
|
|
||||||
+ N, N, N, N, N, N, N, N,
|
|
||||||
+} };
|
|
||||||
+
|
|
||||||
static const struct gprefix pfx_0f_6f_0f_7f = {
|
|
||||||
I(Mmx, em_mov), I(Sse | Aligned, em_mov), N, I(Sse | Unaligned, em_mov),
|
|
||||||
};
|
|
||||||
@@ -4063,7 +4079,7 @@ static const struct opcode twobyte_table[256] = {
|
|
||||||
F(DstMem | SrcReg | ModRM | BitOp | Lock | PageTable, em_bts),
|
|
||||||
F(DstMem | SrcReg | Src2ImmByte | ModRM, em_shrd),
|
|
||||||
F(DstMem | SrcReg | Src2CL | ModRM, em_shrd),
|
|
||||||
- D(ModRM), F(DstReg | SrcMem | ModRM, em_imul),
|
|
||||||
+ GD(0, &group15), F(DstReg | SrcMem | ModRM, em_imul),
|
|
||||||
/* 0xB0 - 0xB7 */
|
|
||||||
I2bv(DstMem | SrcReg | ModRM | Lock | PageTable, em_cmpxchg),
|
|
||||||
I(DstReg | SrcMemFAddr | ModRM | Src2SS, em_lseg),
|
|
||||||
@@ -4993,8 +5009,6 @@ twobyte_insn:
|
|
||||||
case 0x90 ... 0x9f: /* setcc r/m8 */
|
|
||||||
ctxt->dst.val = test_cc(ctxt->b, ctxt->eflags);
|
|
||||||
break;
|
|
||||||
- case 0xae: /* clflush */
|
|
||||||
- break;
|
|
||||||
case 0xb6 ... 0xb7: /* movzx */
|
|
||||||
ctxt->dst.bytes = ctxt->op_bytes;
|
|
||||||
ctxt->dst.val = (ctxt->src.bytes == 1) ? (u8) ctxt->src.val
|
|
||||||
--
|
|
||||||
1.9.3
|
|
||||||
|
|
@ -1,234 +0,0 @@
|
|||||||
From: Nadav Amit <namit@cs.technion.ac.il>
|
|
||||||
Date: Fri, 24 Oct 2014 17:07:16 +0200
|
|
||||||
Subject: [PATCH] KVM: x86: Emulator fixes for eip canonical checks on near
|
|
||||||
branches
|
|
||||||
|
|
||||||
Before changing rip (during jmp, call, ret, etc.) the target should be asserted
|
|
||||||
to be canonical one, as real CPUs do. During sysret, both target rsp and rip
|
|
||||||
should be canonical. If any of these values is noncanonical, a #GP exception
|
|
||||||
should occur. The exception to this rule are syscall and sysenter instructions
|
|
||||||
in which the assigned rip is checked during the assignment to the relevant
|
|
||||||
MSRs.
|
|
||||||
|
|
||||||
This patch fixes the emulator to behave as real CPUs do for near branches.
|
|
||||||
Far branches are handled by the next patch.
|
|
||||||
|
|
||||||
This fixes CVE-2014-3647.
|
|
||||||
|
|
||||||
Cc: stable@vger.kernel.org
|
|
||||||
Signed-off-by: Nadav Amit <namit@cs.technion.ac.il>
|
|
||||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
||||||
---
|
|
||||||
arch/x86/kvm/emulate.c | 78 ++++++++++++++++++++++++++++++++++----------------
|
|
||||||
1 file changed, 54 insertions(+), 24 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
|
|
||||||
index 047698974799..a1b9139169f6 100644
|
|
||||||
--- a/arch/x86/kvm/emulate.c
|
|
||||||
+++ b/arch/x86/kvm/emulate.c
|
|
||||||
@@ -564,7 +564,8 @@ static int emulate_nm(struct x86_emulate_ctxt *ctxt)
|
|
||||||
return emulate_exception(ctxt, NM_VECTOR, 0, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static inline void assign_eip_near(struct x86_emulate_ctxt *ctxt, ulong dst)
|
|
||||||
+static inline int assign_eip_far(struct x86_emulate_ctxt *ctxt, ulong dst,
|
|
||||||
+ int cs_l)
|
|
||||||
{
|
|
||||||
switch (ctxt->op_bytes) {
|
|
||||||
case 2:
|
|
||||||
@@ -574,16 +575,25 @@ static inline void assign_eip_near(struct x86_emulate_ctxt *ctxt, ulong dst)
|
|
||||||
ctxt->_eip = (u32)dst;
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
+ if ((cs_l && is_noncanonical_address(dst)) ||
|
|
||||||
+ (!cs_l && (dst & ~(u32)-1)))
|
|
||||||
+ return emulate_gp(ctxt, 0);
|
|
||||||
ctxt->_eip = dst;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
WARN(1, "unsupported eip assignment size\n");
|
|
||||||
}
|
|
||||||
+ return X86EMUL_CONTINUE;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline int assign_eip_near(struct x86_emulate_ctxt *ctxt, ulong dst)
|
|
||||||
+{
|
|
||||||
+ return assign_eip_far(ctxt, dst, ctxt->mode == X86EMUL_MODE_PROT64);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static inline void jmp_rel(struct x86_emulate_ctxt *ctxt, int rel)
|
|
||||||
+static inline int jmp_rel(struct x86_emulate_ctxt *ctxt, int rel)
|
|
||||||
{
|
|
||||||
- assign_eip_near(ctxt, ctxt->_eip + rel);
|
|
||||||
+ return assign_eip_near(ctxt, ctxt->_eip + rel);
|
|
||||||
}
|
|
||||||
|
|
||||||
static u16 get_segment_selector(struct x86_emulate_ctxt *ctxt, unsigned seg)
|
|
||||||
@@ -1998,13 +2008,15 @@ static int em_grp45(struct x86_emulate_ctxt *ctxt)
|
|
||||||
case 2: /* call near abs */ {
|
|
||||||
long int old_eip;
|
|
||||||
old_eip = ctxt->_eip;
|
|
||||||
- ctxt->_eip = ctxt->src.val;
|
|
||||||
+ rc = assign_eip_near(ctxt, ctxt->src.val);
|
|
||||||
+ if (rc != X86EMUL_CONTINUE)
|
|
||||||
+ break;
|
|
||||||
ctxt->src.val = old_eip;
|
|
||||||
rc = em_push(ctxt);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 4: /* jmp abs */
|
|
||||||
- ctxt->_eip = ctxt->src.val;
|
|
||||||
+ rc = assign_eip_near(ctxt, ctxt->src.val);
|
|
||||||
break;
|
|
||||||
case 5: /* jmp far */
|
|
||||||
rc = em_jmp_far(ctxt);
|
|
||||||
@@ -2039,10 +2051,14 @@ static int em_cmpxchg8b(struct x86_emulate_ctxt *ctxt)
|
|
||||||
|
|
||||||
static int em_ret(struct x86_emulate_ctxt *ctxt)
|
|
||||||
{
|
|
||||||
- ctxt->dst.type = OP_REG;
|
|
||||||
- ctxt->dst.addr.reg = &ctxt->_eip;
|
|
||||||
- ctxt->dst.bytes = ctxt->op_bytes;
|
|
||||||
- return em_pop(ctxt);
|
|
||||||
+ int rc;
|
|
||||||
+ unsigned long eip;
|
|
||||||
+
|
|
||||||
+ rc = emulate_pop(ctxt, &eip, ctxt->op_bytes);
|
|
||||||
+ if (rc != X86EMUL_CONTINUE)
|
|
||||||
+ return rc;
|
|
||||||
+
|
|
||||||
+ return assign_eip_near(ctxt, eip);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int em_ret_far(struct x86_emulate_ctxt *ctxt)
|
|
||||||
@@ -2323,7 +2339,7 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
|
|
||||||
{
|
|
||||||
const struct x86_emulate_ops *ops = ctxt->ops;
|
|
||||||
struct desc_struct cs, ss;
|
|
||||||
- u64 msr_data;
|
|
||||||
+ u64 msr_data, rcx, rdx;
|
|
||||||
int usermode;
|
|
||||||
u16 cs_sel = 0, ss_sel = 0;
|
|
||||||
|
|
||||||
@@ -2339,6 +2355,9 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
|
|
||||||
else
|
|
||||||
usermode = X86EMUL_MODE_PROT32;
|
|
||||||
|
|
||||||
+ rcx = reg_read(ctxt, VCPU_REGS_RCX);
|
|
||||||
+ rdx = reg_read(ctxt, VCPU_REGS_RDX);
|
|
||||||
+
|
|
||||||
cs.dpl = 3;
|
|
||||||
ss.dpl = 3;
|
|
||||||
ops->get_msr(ctxt, MSR_IA32_SYSENTER_CS, &msr_data);
|
|
||||||
@@ -2356,6 +2375,9 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
|
|
||||||
ss_sel = cs_sel + 8;
|
|
||||||
cs.d = 0;
|
|
||||||
cs.l = 1;
|
|
||||||
+ if (is_noncanonical_address(rcx) ||
|
|
||||||
+ is_noncanonical_address(rdx))
|
|
||||||
+ return emulate_gp(ctxt, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
cs_sel |= SELECTOR_RPL_MASK;
|
|
||||||
@@ -2364,8 +2386,8 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
|
|
||||||
ops->set_segment(ctxt, cs_sel, &cs, 0, VCPU_SREG_CS);
|
|
||||||
ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS);
|
|
||||||
|
|
||||||
- ctxt->_eip = reg_read(ctxt, VCPU_REGS_RDX);
|
|
||||||
- *reg_write(ctxt, VCPU_REGS_RSP) = reg_read(ctxt, VCPU_REGS_RCX);
|
|
||||||
+ ctxt->_eip = rdx;
|
|
||||||
+ *reg_write(ctxt, VCPU_REGS_RSP) = rcx;
|
|
||||||
|
|
||||||
return X86EMUL_CONTINUE;
|
|
||||||
}
|
|
||||||
@@ -2905,10 +2927,13 @@ static int em_aad(struct x86_emulate_ctxt *ctxt)
|
|
||||||
|
|
||||||
static int em_call(struct x86_emulate_ctxt *ctxt)
|
|
||||||
{
|
|
||||||
+ int rc;
|
|
||||||
long rel = ctxt->src.val;
|
|
||||||
|
|
||||||
ctxt->src.val = (unsigned long)ctxt->_eip;
|
|
||||||
- jmp_rel(ctxt, rel);
|
|
||||||
+ rc = jmp_rel(ctxt, rel);
|
|
||||||
+ if (rc != X86EMUL_CONTINUE)
|
|
||||||
+ return rc;
|
|
||||||
return em_push(ctxt);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -2940,11 +2965,12 @@ static int em_call_far(struct x86_emulate_ctxt *ctxt)
|
|
||||||
static int em_ret_near_imm(struct x86_emulate_ctxt *ctxt)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
+ unsigned long eip;
|
|
||||||
|
|
||||||
- ctxt->dst.type = OP_REG;
|
|
||||||
- ctxt->dst.addr.reg = &ctxt->_eip;
|
|
||||||
- ctxt->dst.bytes = ctxt->op_bytes;
|
|
||||||
- rc = emulate_pop(ctxt, &ctxt->dst.val, ctxt->op_bytes);
|
|
||||||
+ rc = emulate_pop(ctxt, &eip, ctxt->op_bytes);
|
|
||||||
+ if (rc != X86EMUL_CONTINUE)
|
|
||||||
+ return rc;
|
|
||||||
+ rc = assign_eip_near(ctxt, eip);
|
|
||||||
if (rc != X86EMUL_CONTINUE)
|
|
||||||
return rc;
|
|
||||||
rsp_increment(ctxt, ctxt->src.val);
|
|
||||||
@@ -3271,20 +3297,24 @@ static int em_lmsw(struct x86_emulate_ctxt *ctxt)
|
|
||||||
|
|
||||||
static int em_loop(struct x86_emulate_ctxt *ctxt)
|
|
||||||
{
|
|
||||||
+ int rc = X86EMUL_CONTINUE;
|
|
||||||
+
|
|
||||||
register_address_increment(ctxt, reg_rmw(ctxt, VCPU_REGS_RCX), -1);
|
|
||||||
if ((address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) != 0) &&
|
|
||||||
(ctxt->b == 0xe2 || test_cc(ctxt->b ^ 0x5, ctxt->eflags)))
|
|
||||||
- jmp_rel(ctxt, ctxt->src.val);
|
|
||||||
+ rc = jmp_rel(ctxt, ctxt->src.val);
|
|
||||||
|
|
||||||
- return X86EMUL_CONTINUE;
|
|
||||||
+ return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int em_jcxz(struct x86_emulate_ctxt *ctxt)
|
|
||||||
{
|
|
||||||
+ int rc = X86EMUL_CONTINUE;
|
|
||||||
+
|
|
||||||
if (address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) == 0)
|
|
||||||
- jmp_rel(ctxt, ctxt->src.val);
|
|
||||||
+ rc = jmp_rel(ctxt, ctxt->src.val);
|
|
||||||
|
|
||||||
- return X86EMUL_CONTINUE;
|
|
||||||
+ return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int em_in(struct x86_emulate_ctxt *ctxt)
|
|
||||||
@@ -4743,7 +4773,7 @@ special_insn:
|
|
||||||
break;
|
|
||||||
case 0x70 ... 0x7f: /* jcc (short) */
|
|
||||||
if (test_cc(ctxt->b, ctxt->eflags))
|
|
||||||
- jmp_rel(ctxt, ctxt->src.val);
|
|
||||||
+ rc = jmp_rel(ctxt, ctxt->src.val);
|
|
||||||
break;
|
|
||||||
case 0x8d: /* lea r16/r32, m */
|
|
||||||
ctxt->dst.val = ctxt->src.addr.mem.ea;
|
|
||||||
@@ -4773,7 +4803,7 @@ special_insn:
|
|
||||||
break;
|
|
||||||
case 0xe9: /* jmp rel */
|
|
||||||
case 0xeb: /* jmp rel short */
|
|
||||||
- jmp_rel(ctxt, ctxt->src.val);
|
|
||||||
+ rc = jmp_rel(ctxt, ctxt->src.val);
|
|
||||||
ctxt->dst.type = OP_NONE; /* Disable writeback. */
|
|
||||||
break;
|
|
||||||
case 0xf4: /* hlt */
|
|
||||||
@@ -4898,7 +4928,7 @@ twobyte_insn:
|
|
||||||
break;
|
|
||||||
case 0x80 ... 0x8f: /* jnz rel, etc*/
|
|
||||||
if (test_cc(ctxt->b, ctxt->eflags))
|
|
||||||
- jmp_rel(ctxt, ctxt->src.val);
|
|
||||||
+ rc = jmp_rel(ctxt, ctxt->src.val);
|
|
||||||
break;
|
|
||||||
case 0x90 ... 0x9f: /* setcc r/m8 */
|
|
||||||
ctxt->dst.val = test_cc(ctxt->b, ctxt->eflags);
|
|
||||||
--
|
|
||||||
1.9.3
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
|||||||
From: Nadav Amit <namit@cs.technion.ac.il>
|
|
||||||
Date: Fri, 24 Oct 2014 17:07:15 +0200
|
|
||||||
Subject: [PATCH] KVM: x86: Fix wrong masking on relative jump/call
|
|
||||||
|
|
||||||
Relative jumps and calls do the masking according to the operand size, and not
|
|
||||||
according to the address size as the KVM emulator does today.
|
|
||||||
|
|
||||||
This patch fixes KVM behavior.
|
|
||||||
|
|
||||||
Cc: stable@vger.kernel.org
|
|
||||||
Signed-off-by: Nadav Amit <namit@cs.technion.ac.il>
|
|
||||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
||||||
---
|
|
||||||
arch/x86/kvm/emulate.c | 27 ++++++++++++++++++++++-----
|
|
||||||
1 file changed, 22 insertions(+), 5 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
|
|
||||||
index a46207a05835..047698974799 100644
|
|
||||||
--- a/arch/x86/kvm/emulate.c
|
|
||||||
+++ b/arch/x86/kvm/emulate.c
|
|
||||||
@@ -504,11 +504,6 @@ static void rsp_increment(struct x86_emulate_ctxt *ctxt, int inc)
|
|
||||||
masked_increment(reg_rmw(ctxt, VCPU_REGS_RSP), stack_mask(ctxt), inc);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static inline void jmp_rel(struct x86_emulate_ctxt *ctxt, int rel)
|
|
||||||
-{
|
|
||||||
- register_address_increment(ctxt, &ctxt->_eip, rel);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
static u32 desc_limit_scaled(struct desc_struct *desc)
|
|
||||||
{
|
|
||||||
u32 limit = get_desc_limit(desc);
|
|
||||||
@@ -569,6 +564,28 @@ static int emulate_nm(struct x86_emulate_ctxt *ctxt)
|
|
||||||
return emulate_exception(ctxt, NM_VECTOR, 0, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
+static inline void assign_eip_near(struct x86_emulate_ctxt *ctxt, ulong dst)
|
|
||||||
+{
|
|
||||||
+ switch (ctxt->op_bytes) {
|
|
||||||
+ case 2:
|
|
||||||
+ ctxt->_eip = (u16)dst;
|
|
||||||
+ break;
|
|
||||||
+ case 4:
|
|
||||||
+ ctxt->_eip = (u32)dst;
|
|
||||||
+ break;
|
|
||||||
+ case 8:
|
|
||||||
+ ctxt->_eip = dst;
|
|
||||||
+ break;
|
|
||||||
+ default:
|
|
||||||
+ WARN(1, "unsupported eip assignment size\n");
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void jmp_rel(struct x86_emulate_ctxt *ctxt, int rel)
|
|
||||||
+{
|
|
||||||
+ assign_eip_near(ctxt, ctxt->_eip + rel);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static u16 get_segment_selector(struct x86_emulate_ctxt *ctxt, unsigned seg)
|
|
||||||
{
|
|
||||||
u16 selector;
|
|
||||||
--
|
|
||||||
1.9.3
|
|
||||||
|
|
@ -1,249 +0,0 @@
|
|||||||
From: Nadav Amit <namit@cs.technion.ac.il>
|
|
||||||
Date: Fri, 24 Oct 2014 17:07:17 +0200
|
|
||||||
Subject: [PATCH] KVM: x86: Handle errors when RIP is set during far jumps
|
|
||||||
|
|
||||||
Far jmp/call/ret may fault while loading a new RIP. Currently KVM does not
|
|
||||||
handle this case, and may result in failed vm-entry once the assignment is
|
|
||||||
done. The tricky part of doing so is that loading the new CS affects the
|
|
||||||
VMCS/VMCB state, so if we fail during loading the new RIP, we are left in
|
|
||||||
unconsistent state. Therefore, this patch saves on 64-bit the old CS
|
|
||||||
descriptor and restores it if loading RIP failed.
|
|
||||||
|
|
||||||
This fixes CVE-2014-3647.
|
|
||||||
|
|
||||||
Cc: stable@vger.kernel.org
|
|
||||||
Signed-off-by: Nadav Amit <namit@cs.technion.ac.il>
|
|
||||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
||||||
---
|
|
||||||
arch/x86/kvm/emulate.c | 118 ++++++++++++++++++++++++++++++++++++-------------
|
|
||||||
1 file changed, 88 insertions(+), 30 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
|
|
||||||
index a1b9139169f6..c0deaff8d9f0 100644
|
|
||||||
--- a/arch/x86/kvm/emulate.c
|
|
||||||
+++ b/arch/x86/kvm/emulate.c
|
|
||||||
@@ -1443,7 +1443,9 @@ static int write_segment_descriptor(struct x86_emulate_ctxt *ctxt,
|
|
||||||
|
|
||||||
/* Does not support long mode */
|
|
||||||
static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
|
|
||||||
- u16 selector, int seg, u8 cpl, bool in_task_switch)
|
|
||||||
+ u16 selector, int seg, u8 cpl,
|
|
||||||
+ bool in_task_switch,
|
|
||||||
+ struct desc_struct *desc)
|
|
||||||
{
|
|
||||||
struct desc_struct seg_desc, old_desc;
|
|
||||||
u8 dpl, rpl;
|
|
||||||
@@ -1584,6 +1586,8 @@ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
|
|
||||||
}
|
|
||||||
load:
|
|
||||||
ctxt->ops->set_segment(ctxt, selector, &seg_desc, base3, seg);
|
|
||||||
+ if (desc)
|
|
||||||
+ *desc = seg_desc;
|
|
||||||
return X86EMUL_CONTINUE;
|
|
||||||
exception:
|
|
||||||
return emulate_exception(ctxt, err_vec, err_code, true);
|
|
||||||
@@ -1593,7 +1597,7 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
|
|
||||||
u16 selector, int seg)
|
|
||||||
{
|
|
||||||
u8 cpl = ctxt->ops->cpl(ctxt);
|
|
||||||
- return __load_segment_descriptor(ctxt, selector, seg, cpl, false);
|
|
||||||
+ return __load_segment_descriptor(ctxt, selector, seg, cpl, false, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void write_register_operand(struct operand *op)
|
|
||||||
@@ -1987,17 +1991,31 @@ static int em_iret(struct x86_emulate_ctxt *ctxt)
|
|
||||||
static int em_jmp_far(struct x86_emulate_ctxt *ctxt)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
- unsigned short sel;
|
|
||||||
+ unsigned short sel, old_sel;
|
|
||||||
+ struct desc_struct old_desc, new_desc;
|
|
||||||
+ const struct x86_emulate_ops *ops = ctxt->ops;
|
|
||||||
+ u8 cpl = ctxt->ops->cpl(ctxt);
|
|
||||||
+
|
|
||||||
+ /* Assignment of RIP may only fail in 64-bit mode */
|
|
||||||
+ if (ctxt->mode == X86EMUL_MODE_PROT64)
|
|
||||||
+ ops->get_segment(ctxt, &old_sel, &old_desc, NULL,
|
|
||||||
+ VCPU_SREG_CS);
|
|
||||||
|
|
||||||
memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2);
|
|
||||||
|
|
||||||
- rc = load_segment_descriptor(ctxt, sel, VCPU_SREG_CS);
|
|
||||||
+ rc = __load_segment_descriptor(ctxt, sel, VCPU_SREG_CS, cpl, false,
|
|
||||||
+ &new_desc);
|
|
||||||
if (rc != X86EMUL_CONTINUE)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
- ctxt->_eip = 0;
|
|
||||||
- memcpy(&ctxt->_eip, ctxt->src.valptr, ctxt->op_bytes);
|
|
||||||
- return X86EMUL_CONTINUE;
|
|
||||||
+ rc = assign_eip_far(ctxt, ctxt->src.val, new_desc.l);
|
|
||||||
+ if (rc != X86EMUL_CONTINUE) {
|
|
||||||
+ WARN_ON(!ctxt->mode != X86EMUL_MODE_PROT64);
|
|
||||||
+ /* assigning eip failed; restore the old cs */
|
|
||||||
+ ops->set_segment(ctxt, old_sel, &old_desc, 0, VCPU_SREG_CS);
|
|
||||||
+ return rc;
|
|
||||||
+ }
|
|
||||||
+ return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int em_grp45(struct x86_emulate_ctxt *ctxt)
|
|
||||||
@@ -2064,21 +2082,34 @@ static int em_ret(struct x86_emulate_ctxt *ctxt)
|
|
||||||
static int em_ret_far(struct x86_emulate_ctxt *ctxt)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
- unsigned long cs;
|
|
||||||
+ unsigned long eip, cs;
|
|
||||||
+ u16 old_cs;
|
|
||||||
int cpl = ctxt->ops->cpl(ctxt);
|
|
||||||
+ struct desc_struct old_desc, new_desc;
|
|
||||||
+ const struct x86_emulate_ops *ops = ctxt->ops;
|
|
||||||
+
|
|
||||||
+ if (ctxt->mode == X86EMUL_MODE_PROT64)
|
|
||||||
+ ops->get_segment(ctxt, &old_cs, &old_desc, NULL,
|
|
||||||
+ VCPU_SREG_CS);
|
|
||||||
|
|
||||||
- rc = emulate_pop(ctxt, &ctxt->_eip, ctxt->op_bytes);
|
|
||||||
+ rc = emulate_pop(ctxt, &eip, ctxt->op_bytes);
|
|
||||||
if (rc != X86EMUL_CONTINUE)
|
|
||||||
return rc;
|
|
||||||
- if (ctxt->op_bytes == 4)
|
|
||||||
- ctxt->_eip = (u32)ctxt->_eip;
|
|
||||||
rc = emulate_pop(ctxt, &cs, ctxt->op_bytes);
|
|
||||||
if (rc != X86EMUL_CONTINUE)
|
|
||||||
return rc;
|
|
||||||
/* Outer-privilege level return is not implemented */
|
|
||||||
if (ctxt->mode >= X86EMUL_MODE_PROT16 && (cs & 3) > cpl)
|
|
||||||
return X86EMUL_UNHANDLEABLE;
|
|
||||||
- rc = load_segment_descriptor(ctxt, (u16)cs, VCPU_SREG_CS);
|
|
||||||
+ rc = __load_segment_descriptor(ctxt, (u16)cs, VCPU_SREG_CS, 0, false,
|
|
||||||
+ &new_desc);
|
|
||||||
+ if (rc != X86EMUL_CONTINUE)
|
|
||||||
+ return rc;
|
|
||||||
+ rc = assign_eip_far(ctxt, eip, new_desc.l);
|
|
||||||
+ if (rc != X86EMUL_CONTINUE) {
|
|
||||||
+ WARN_ON(!ctxt->mode != X86EMUL_MODE_PROT64);
|
|
||||||
+ ops->set_segment(ctxt, old_cs, &old_desc, 0, VCPU_SREG_CS);
|
|
||||||
+ }
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -2505,19 +2536,24 @@ static int load_state_from_tss16(struct x86_emulate_ctxt *ctxt,
|
|
||||||
* Now load segment descriptors. If fault happens at this stage
|
|
||||||
* it is handled in a context of new task
|
|
||||||
*/
|
|
||||||
- ret = __load_segment_descriptor(ctxt, tss->ldt, VCPU_SREG_LDTR, cpl, true);
|
|
||||||
+ ret = __load_segment_descriptor(ctxt, tss->ldt, VCPU_SREG_LDTR, cpl,
|
|
||||||
+ true, NULL);
|
|
||||||
if (ret != X86EMUL_CONTINUE)
|
|
||||||
return ret;
|
|
||||||
- ret = __load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES, cpl, true);
|
|
||||||
+ ret = __load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES, cpl,
|
|
||||||
+ true, NULL);
|
|
||||||
if (ret != X86EMUL_CONTINUE)
|
|
||||||
return ret;
|
|
||||||
- ret = __load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS, cpl, true);
|
|
||||||
+ ret = __load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS, cpl,
|
|
||||||
+ true, NULL);
|
|
||||||
if (ret != X86EMUL_CONTINUE)
|
|
||||||
return ret;
|
|
||||||
- ret = __load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS, cpl, true);
|
|
||||||
+ ret = __load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS, cpl,
|
|
||||||
+ true, NULL);
|
|
||||||
if (ret != X86EMUL_CONTINUE)
|
|
||||||
return ret;
|
|
||||||
- ret = __load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS, cpl, true);
|
|
||||||
+ ret = __load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS, cpl,
|
|
||||||
+ true, NULL);
|
|
||||||
if (ret != X86EMUL_CONTINUE)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
@@ -2642,25 +2678,32 @@ static int load_state_from_tss32(struct x86_emulate_ctxt *ctxt,
|
|
||||||
* Now load segment descriptors. If fault happenes at this stage
|
|
||||||
* it is handled in a context of new task
|
|
||||||
*/
|
|
||||||
- ret = __load_segment_descriptor(ctxt, tss->ldt_selector, VCPU_SREG_LDTR, cpl, true);
|
|
||||||
+ ret = __load_segment_descriptor(ctxt, tss->ldt_selector, VCPU_SREG_LDTR,
|
|
||||||
+ cpl, true, NULL);
|
|
||||||
if (ret != X86EMUL_CONTINUE)
|
|
||||||
return ret;
|
|
||||||
- ret = __load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES, cpl, true);
|
|
||||||
+ ret = __load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES, cpl,
|
|
||||||
+ true, NULL);
|
|
||||||
if (ret != X86EMUL_CONTINUE)
|
|
||||||
return ret;
|
|
||||||
- ret = __load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS, cpl, true);
|
|
||||||
+ ret = __load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS, cpl,
|
|
||||||
+ true, NULL);
|
|
||||||
if (ret != X86EMUL_CONTINUE)
|
|
||||||
return ret;
|
|
||||||
- ret = __load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS, cpl, true);
|
|
||||||
+ ret = __load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS, cpl,
|
|
||||||
+ true, NULL);
|
|
||||||
if (ret != X86EMUL_CONTINUE)
|
|
||||||
return ret;
|
|
||||||
- ret = __load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS, cpl, true);
|
|
||||||
+ ret = __load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS, cpl,
|
|
||||||
+ true, NULL);
|
|
||||||
if (ret != X86EMUL_CONTINUE)
|
|
||||||
return ret;
|
|
||||||
- ret = __load_segment_descriptor(ctxt, tss->fs, VCPU_SREG_FS, cpl, true);
|
|
||||||
+ ret = __load_segment_descriptor(ctxt, tss->fs, VCPU_SREG_FS, cpl,
|
|
||||||
+ true, NULL);
|
|
||||||
if (ret != X86EMUL_CONTINUE)
|
|
||||||
return ret;
|
|
||||||
- ret = __load_segment_descriptor(ctxt, tss->gs, VCPU_SREG_GS, cpl, true);
|
|
||||||
+ ret = __load_segment_descriptor(ctxt, tss->gs, VCPU_SREG_GS, cpl,
|
|
||||||
+ true, NULL);
|
|
||||||
if (ret != X86EMUL_CONTINUE)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
@@ -2942,24 +2985,39 @@ static int em_call_far(struct x86_emulate_ctxt *ctxt)
|
|
||||||
u16 sel, old_cs;
|
|
||||||
ulong old_eip;
|
|
||||||
int rc;
|
|
||||||
+ struct desc_struct old_desc, new_desc;
|
|
||||||
+ const struct x86_emulate_ops *ops = ctxt->ops;
|
|
||||||
+ int cpl = ctxt->ops->cpl(ctxt);
|
|
||||||
|
|
||||||
- old_cs = get_segment_selector(ctxt, VCPU_SREG_CS);
|
|
||||||
old_eip = ctxt->_eip;
|
|
||||||
+ ops->get_segment(ctxt, &old_cs, &old_desc, NULL, VCPU_SREG_CS);
|
|
||||||
|
|
||||||
memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2);
|
|
||||||
- if (load_segment_descriptor(ctxt, sel, VCPU_SREG_CS))
|
|
||||||
+ rc = __load_segment_descriptor(ctxt, sel, VCPU_SREG_CS, cpl, false,
|
|
||||||
+ &new_desc);
|
|
||||||
+ if (rc != X86EMUL_CONTINUE)
|
|
||||||
return X86EMUL_CONTINUE;
|
|
||||||
|
|
||||||
- ctxt->_eip = 0;
|
|
||||||
- memcpy(&ctxt->_eip, ctxt->src.valptr, ctxt->op_bytes);
|
|
||||||
+ rc = assign_eip_far(ctxt, ctxt->src.val, new_desc.l);
|
|
||||||
+ if (rc != X86EMUL_CONTINUE)
|
|
||||||
+ goto fail;
|
|
||||||
|
|
||||||
ctxt->src.val = old_cs;
|
|
||||||
rc = em_push(ctxt);
|
|
||||||
if (rc != X86EMUL_CONTINUE)
|
|
||||||
- return rc;
|
|
||||||
+ goto fail;
|
|
||||||
|
|
||||||
ctxt->src.val = old_eip;
|
|
||||||
- return em_push(ctxt);
|
|
||||||
+ rc = em_push(ctxt);
|
|
||||||
+ /* If we failed, we tainted the memory, but the very least we should
|
|
||||||
+ restore cs */
|
|
||||||
+ if (rc != X86EMUL_CONTINUE)
|
|
||||||
+ goto fail;
|
|
||||||
+ return rc;
|
|
||||||
+fail:
|
|
||||||
+ ops->set_segment(ctxt, old_cs, &old_desc, 0, VCPU_SREG_CS);
|
|
||||||
+ return rc;
|
|
||||||
+
|
|
||||||
}
|
|
||||||
|
|
||||||
static int em_ret_near_imm(struct x86_emulate_ctxt *ctxt)
|
|
||||||
--
|
|
||||||
1.9.3
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
|||||||
From: Andy Honig <ahonig@google.com>
|
|
||||||
Date: Fri, 24 Oct 2014 17:07:14 +0200
|
|
||||||
Subject: [PATCH] KVM: x86: Improve thread safety in pit
|
|
||||||
|
|
||||||
There's a race condition in the PIT emulation code in KVM. In
|
|
||||||
__kvm_migrate_pit_timer the pit_timer object is accessed without
|
|
||||||
synchronization. If the race condition occurs at the wrong time this
|
|
||||||
can crash the host kernel.
|
|
||||||
|
|
||||||
This fixes CVE-2014-3611.
|
|
||||||
|
|
||||||
Cc: stable@vger.kernel.org
|
|
||||||
Signed-off-by: Andrew Honig <ahonig@google.com>
|
|
||||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
||||||
---
|
|
||||||
arch/x86/kvm/i8254.c | 2 ++
|
|
||||||
1 file changed, 2 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
|
|
||||||
index 518d86471b76..298781d4cfb4 100644
|
|
||||||
--- a/arch/x86/kvm/i8254.c
|
|
||||||
+++ b/arch/x86/kvm/i8254.c
|
|
||||||
@@ -262,8 +262,10 @@ void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu)
|
|
||||||
return;
|
|
||||||
|
|
||||||
timer = &pit->pit_state.timer;
|
|
||||||
+ mutex_lock(&pit->pit_state.lock);
|
|
||||||
if (hrtimer_cancel(timer))
|
|
||||||
hrtimer_start_expires(timer, HRTIMER_MODE_ABS);
|
|
||||||
+ mutex_unlock(&pit->pit_state.lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void destroy_pit_timer(struct kvm_pit *pit)
|
|
||||||
--
|
|
||||||
1.9.3
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
|||||||
From: Nadav Amit <namit@cs.technion.ac.il>
|
|
||||||
Date: Fri, 24 Oct 2014 17:07:23 +0200
|
|
||||||
Subject: [PATCH] KVM: x86: PREFETCH and HINT_NOP should have SrcMem flag
|
|
||||||
|
|
||||||
The decode phase of the x86 emulator assumes that every instruction with the
|
|
||||||
ModRM flag, and which can be used with RIP-relative addressing, has either
|
|
||||||
SrcMem or DstMem. This is not the case for several instructions - prefetch,
|
|
||||||
hint-nop and clflush.
|
|
||||||
|
|
||||||
Adding SrcMem|NoAccess for prefetch and hint-nop and SrcMem for clflush.
|
|
||||||
|
|
||||||
This fixes CVE-2014-8480.
|
|
||||||
|
|
||||||
Fixes: 41061cdb98a0bec464278b4db8e894a3121671f5
|
|
||||||
Cc: stable@vger.kernel.org
|
|
||||||
Signed-off-by: Nadav Amit <namit@cs.technion.ac.il>
|
|
||||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
||||||
---
|
|
||||||
arch/x86/kvm/emulate.c | 7 ++++---
|
|
||||||
1 file changed, 4 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
|
|
||||||
index 97da5034d812..749f9fa38254 100644
|
|
||||||
--- a/arch/x86/kvm/emulate.c
|
|
||||||
+++ b/arch/x86/kvm/emulate.c
|
|
||||||
@@ -3807,7 +3807,7 @@ static const struct opcode group11[] = {
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct gprefix pfx_0f_ae_7 = {
|
|
||||||
- I(0, em_clflush), N, N, N,
|
|
||||||
+ I(SrcMem | ByteOp, em_clflush), N, N, N,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct group_dual group15 = { {
|
|
||||||
@@ -4024,10 +4024,11 @@ static const struct opcode twobyte_table[256] = {
|
|
||||||
N, I(ImplicitOps | EmulateOnUD, em_syscall),
|
|
||||||
II(ImplicitOps | Priv, em_clts, clts), N,
|
|
||||||
DI(ImplicitOps | Priv, invd), DI(ImplicitOps | Priv, wbinvd), N, N,
|
|
||||||
- N, D(ImplicitOps | ModRM), N, N,
|
|
||||||
+ N, D(ImplicitOps | ModRM | SrcMem | NoAccess), N, N,
|
|
||||||
/* 0x10 - 0x1F */
|
|
||||||
N, N, N, N, N, N, N, N,
|
|
||||||
- D(ImplicitOps | ModRM), N, N, N, N, N, N, D(ImplicitOps | ModRM),
|
|
||||||
+ D(ImplicitOps | ModRM | SrcMem | NoAccess),
|
|
||||||
+ N, N, N, N, N, N, D(ImplicitOps | ModRM | SrcMem | NoAccess),
|
|
||||||
/* 0x20 - 0x2F */
|
|
||||||
DIP(ModRM | DstMem | Priv | Op3264 | NoMod, cr_read, check_cr_read),
|
|
||||||
DIP(ModRM | DstMem | Priv | Op3264 | NoMod, dr_read, check_dr_read),
|
|
||||||
--
|
|
||||||
1.9.3
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
|||||||
From: Andy Honig <ahonig@google.com>
|
|
||||||
Date: Fri, 24 Oct 2014 17:07:13 +0200
|
|
||||||
Subject: [PATCH] KVM: x86: Prevent host from panicking on shared MSR writes.
|
|
||||||
|
|
||||||
The previous patch blocked invalid writes directly when the MSR
|
|
||||||
is written. As a precaution, prevent future similar mistakes by
|
|
||||||
gracefulling handle GPs caused by writes to shared MSRs.
|
|
||||||
|
|
||||||
Cc: stable@vger.kernel.org
|
|
||||||
Signed-off-by: Andrew Honig <ahonig@google.com>
|
|
||||||
[Remove parts obsoleted by Nadav's patch. - Paolo]
|
|
||||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
||||||
---
|
|
||||||
arch/x86/include/asm/kvm_host.h | 2 +-
|
|
||||||
arch/x86/kvm/vmx.c | 7 +++++--
|
|
||||||
arch/x86/kvm/x86.c | 11 ++++++++---
|
|
||||||
3 files changed, 14 insertions(+), 6 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
|
|
||||||
index ccc94de4ac49..6ed0c30d6a0c 100644
|
|
||||||
--- a/arch/x86/include/asm/kvm_host.h
|
|
||||||
+++ b/arch/x86/include/asm/kvm_host.h
|
|
||||||
@@ -1064,7 +1064,7 @@ void kvm_arch_mmu_notifier_invalidate_page(struct kvm *kvm,
|
|
||||||
unsigned long address);
|
|
||||||
|
|
||||||
void kvm_define_shared_msr(unsigned index, u32 msr);
|
|
||||||
-void kvm_set_shared_msr(unsigned index, u64 val, u64 mask);
|
|
||||||
+int kvm_set_shared_msr(unsigned index, u64 val, u64 mask);
|
|
||||||
|
|
||||||
bool kvm_is_linear_rip(struct kvm_vcpu *vcpu, unsigned long linear_rip);
|
|
||||||
|
|
||||||
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
|
|
||||||
index 148020a7dd98..7e2c098b59c9 100644
|
|
||||||
--- a/arch/x86/kvm/vmx.c
|
|
||||||
+++ b/arch/x86/kvm/vmx.c
|
|
||||||
@@ -2659,12 +2659,15 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
|
||||||
default:
|
|
||||||
msr = find_msr_entry(vmx, msr_index);
|
|
||||||
if (msr) {
|
|
||||||
+ u64 old_msr_data = msr->data;
|
|
||||||
msr->data = data;
|
|
||||||
if (msr - vmx->guest_msrs < vmx->save_nmsrs) {
|
|
||||||
preempt_disable();
|
|
||||||
- kvm_set_shared_msr(msr->index, msr->data,
|
|
||||||
- msr->mask);
|
|
||||||
+ ret = kvm_set_shared_msr(msr->index, msr->data,
|
|
||||||
+ msr->mask);
|
|
||||||
preempt_enable();
|
|
||||||
+ if (ret)
|
|
||||||
+ msr->data = old_msr_data;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
|
|
||||||
index 5a7195573a32..0033df32a745 100644
|
|
||||||
--- a/arch/x86/kvm/x86.c
|
|
||||||
+++ b/arch/x86/kvm/x86.c
|
|
||||||
@@ -229,20 +229,25 @@ static void kvm_shared_msr_cpu_online(void)
|
|
||||||
shared_msr_update(i, shared_msrs_global.msrs[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
-void kvm_set_shared_msr(unsigned slot, u64 value, u64 mask)
|
|
||||||
+int kvm_set_shared_msr(unsigned slot, u64 value, u64 mask)
|
|
||||||
{
|
|
||||||
unsigned int cpu = smp_processor_id();
|
|
||||||
struct kvm_shared_msrs *smsr = per_cpu_ptr(shared_msrs, cpu);
|
|
||||||
+ int err;
|
|
||||||
|
|
||||||
if (((value ^ smsr->values[slot].curr) & mask) == 0)
|
|
||||||
- return;
|
|
||||||
+ return 0;
|
|
||||||
smsr->values[slot].curr = value;
|
|
||||||
- wrmsrl(shared_msrs_global.msrs[slot], value);
|
|
||||||
+ err = wrmsrl_safe(shared_msrs_global.msrs[slot], value);
|
|
||||||
+ if (err)
|
|
||||||
+ return 1;
|
|
||||||
+
|
|
||||||
if (!smsr->registered) {
|
|
||||||
smsr->urn.on_user_return = kvm_on_user_return;
|
|
||||||
user_return_notifier_register(&smsr->urn);
|
|
||||||
smsr->registered = true;
|
|
||||||
}
|
|
||||||
+ return 0;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(kvm_set_shared_msr);
|
|
||||||
|
|
||||||
--
|
|
||||||
1.9.3
|
|
||||||
|
|
@ -4673,6 +4673,7 @@ CONFIG_THERMAL_HWMON=y
|
|||||||
CONFIG_THERMAL_GOV_FAIR_SHARE=y
|
CONFIG_THERMAL_GOV_FAIR_SHARE=y
|
||||||
# CONFIG_THERMAL_GOV_USER_SPACE is not set
|
# CONFIG_THERMAL_GOV_USER_SPACE is not set
|
||||||
CONFIG_THERMAL_GOV_STEP_WISE=y
|
CONFIG_THERMAL_GOV_STEP_WISE=y
|
||||||
|
# CONFIG_THERMAL_GOV_BANG_BANG is not set
|
||||||
# CONFIG_THERMAL_EMULATION is not set
|
# CONFIG_THERMAL_EMULATION is not set
|
||||||
# CONFIG_THERMAL_OF is not set
|
# CONFIG_THERMAL_OF is not set
|
||||||
# CONFIG_CPU_THERMAL is not set
|
# CONFIG_CPU_THERMAL is not set
|
||||||
|
@ -493,6 +493,7 @@ CONFIG_PINCTRL_BAYTRAIL=y
|
|||||||
CONFIG_X86_PKG_TEMP_THERMAL=m
|
CONFIG_X86_PKG_TEMP_THERMAL=m
|
||||||
CONFIG_ACPI_INT3403_THERMAL=m
|
CONFIG_ACPI_INT3403_THERMAL=m
|
||||||
CONFIG_INTEL_SOC_DTS_THERMAL=m
|
CONFIG_INTEL_SOC_DTS_THERMAL=m
|
||||||
|
CONFIG_INT340X_THERMAL=m
|
||||||
|
|
||||||
CONFIG_VMWARE_VMCI=m
|
CONFIG_VMWARE_VMCI=m
|
||||||
CONFIG_VMWARE_VMCI_VSOCKETS=m
|
CONFIG_VMWARE_VMCI_VSOCKETS=m
|
||||||
|
@ -1853,9 +1853,9 @@ index ac9afde..14423f3 100644
|
|||||||
config ARM64
|
config ARM64
|
||||||
def_bool y
|
def_bool y
|
||||||
+ select ACPI_REDUCED_HARDWARE_ONLY if ACPI
|
+ select ACPI_REDUCED_HARDWARE_ONLY if ACPI
|
||||||
|
select ARCH_BINFMT_ELF_RANDOMIZE_PIE
|
||||||
select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
|
select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
|
||||||
select ARCH_HAS_SG_CHAIN
|
select ARCH_HAS_SG_CHAIN
|
||||||
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
|
|
||||||
@@ -267,6 +268,9 @@ config SMP
|
@@ -267,6 +268,9 @@ config SMP
|
||||||
|
|
||||||
If you don't know what to do here, say N.
|
If you don't know what to do here, say N.
|
||||||
@ -3194,13 +3194,13 @@ index 505d4d7..252d0ff 100644
|
|||||||
acpi-y += acpi_lpss.o
|
acpi-y += acpi_lpss.o
|
||||||
acpi-y += acpi_platform.o
|
acpi-y += acpi_platform.o
|
||||||
acpi-y += acpi_pnp.o
|
acpi-y += acpi_pnp.o
|
||||||
|
acpi-y += int340x_thermal.o
|
||||||
acpi-y += power.o
|
acpi-y += power.o
|
||||||
acpi-y += event.o
|
acpi-y += event.o
|
||||||
acpi-y += sysfs.o
|
acpi-y += sysfs.o
|
||||||
+acpi-y += property.o
|
+acpi-y += property.o
|
||||||
acpi-$(CONFIG_X86) += acpi_cmos_rtc.o
|
acpi-$(CONFIG_X86) += acpi_cmos_rtc.o
|
||||||
acpi-$(CONFIG_DEBUG_FS) += debugfs.o
|
acpi-$(CONFIG_DEBUG_FS) += debugfs.o
|
||||||
acpi-$(CONFIG_ACPI_NUMA) += numa.o
|
|
||||||
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
|
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
|
||||||
index 8b67bd0..c412fdb 100644
|
index 8b67bd0..c412fdb 100644
|
||||||
--- a/drivers/acpi/bus.c
|
--- a/drivers/acpi/bus.c
|
||||||
|
45
kernel.spec
45
kernel.spec
@ -42,7 +42,7 @@ Summary: The Linux kernel
|
|||||||
# For non-released -rc kernels, this will be appended after the rcX and
|
# For non-released -rc kernels, this will be appended after the rcX and
|
||||||
# gitX tags, so a 3 here would become part of release "0.rcX.gitX.3"
|
# gitX tags, so a 3 here would become part of release "0.rcX.gitX.3"
|
||||||
#
|
#
|
||||||
%global baserelease 3
|
%global baserelease 1
|
||||||
%global fedora_build %{baserelease}
|
%global fedora_build %{baserelease}
|
||||||
|
|
||||||
# base_sublevel is the kernel version we're starting with and patching
|
# base_sublevel is the kernel version we're starting with and patching
|
||||||
@ -69,7 +69,7 @@ Summary: The Linux kernel
|
|||||||
# The rc snapshot level
|
# The rc snapshot level
|
||||||
%define rcrev 1
|
%define rcrev 1
|
||||||
# The git snapshot level
|
# The git snapshot level
|
||||||
%define gitrev 3
|
%define gitrev 4
|
||||||
# Set rpm version accordingly
|
# Set rpm version accordingly
|
||||||
%define rpmversion 3.%{upstream_sublevel}.0
|
%define rpmversion 3.%{upstream_sublevel}.0
|
||||||
%endif
|
%endif
|
||||||
@ -620,25 +620,6 @@ Patch26058: asus-nb-wmi-Add-wapf4-quirk-for-the-X550VB.patch
|
|||||||
#rhbz 1111138
|
#rhbz 1111138
|
||||||
Patch26059: i8042-Add-notimeout-quirk-for-Fujitsu-Lifebook-A544-.patch
|
Patch26059: i8042-Add-notimeout-quirk-for-Fujitsu-Lifebook-A544-.patch
|
||||||
|
|
||||||
# CVE-2014-3610 kvm: noncanonical MSR writes (rhbz 1144883 1156543)
|
|
||||||
# CVE-2014-3611 kvm: PIT timer race condition (rhbz 1144878 1156537)
|
|
||||||
# CVE-2014-3646 kvm: vmx: invvpid vm exit not handled (rhbz 1144825 1156534)
|
|
||||||
# CVE-2014-8369 kvm: excessive pages un-pinning in kvm_iommu_map error path (rhbz 1156518 1156522)
|
|
||||||
# CVE-2014-8480 CVE-2014-8481 kvm: NULL pointer dereference during rip relative instruction emulation (rhbz 1156615 1156616)
|
|
||||||
Patch26070: KVM-x86-Check-non-canonical-addresses-upon-WRMSR.patch
|
|
||||||
Patch26071: KVM-x86-Prevent-host-from-panicking-on-shared-MSR-wr.patch
|
|
||||||
Patch26072: KVM-x86-Improve-thread-safety-in-pit.patch
|
|
||||||
Patch26073: KVM-x86-Fix-wrong-masking-on-relative-jump-call.patch
|
|
||||||
Patch26074: KVM-x86-Emulator-fixes-for-eip-canonical-checks-on-n.patch
|
|
||||||
Patch26075: KVM-x86-Handle-errors-when-RIP-is-set-during-far-jum.patch
|
|
||||||
Patch26076: kvm-vmx-handle-invvpid-vm-exit-gracefully.patch
|
|
||||||
Patch26077: kvm-x86-don-t-kill-guest-on-unknown-exit-reason.patch
|
|
||||||
Patch26078: KVM-x86-Decoding-guest-instructions-which-cross-page.patch
|
|
||||||
Patch26079: KVM-emulate-avoid-accessing-NULL-ctxt-memopp.patch
|
|
||||||
Patch26080: KVM-x86-Emulator-does-not-decode-clflush-well.patch
|
|
||||||
Patch26081: KVM-x86-PREFETCH-and-HINT_NOP-should-have-SrcMem-fla.patch
|
|
||||||
Patch26082: kvm-fix-excessive-pages-un-pinning-in-kvm_iommu_map-.patch
|
|
||||||
|
|
||||||
# git clone ssh://git.fedorahosted.org/git/kernel-arm64.git, git diff master...devel
|
# git clone ssh://git.fedorahosted.org/git/kernel-arm64.git, git diff master...devel
|
||||||
Patch30000: kernel-arm64.patch
|
Patch30000: kernel-arm64.patch
|
||||||
|
|
||||||
@ -1368,25 +1349,6 @@ ApplyPatch asus-nb-wmi-Add-wapf4-quirk-for-the-X550VB.patch
|
|||||||
#rhbz 1111138
|
#rhbz 1111138
|
||||||
ApplyPatch i8042-Add-notimeout-quirk-for-Fujitsu-Lifebook-A544-.patch
|
ApplyPatch i8042-Add-notimeout-quirk-for-Fujitsu-Lifebook-A544-.patch
|
||||||
|
|
||||||
# CVE-2014-3610 kvm: noncanonical MSR writes (rhbz 1144883 1156543)
|
|
||||||
# CVE-2014-3611 kvm: PIT timer race condition (rhbz 1144878 1156537)
|
|
||||||
# CVE-2014-3646 kvm: vmx: invvpid vm exit not handled (rhbz 1144825 1156534)
|
|
||||||
# CVE-2014-8369 kvm: excessive pages un-pinning in kvm_iommu_map error path (rhbz 1156518 1156522)
|
|
||||||
# CVE-2014-8480 CVE-2014-8481 kvm: NULL pointer dereference during rip relative instruction emulation (rhbz 1156615 1156616)
|
|
||||||
ApplyPatch KVM-x86-Check-non-canonical-addresses-upon-WRMSR.patch
|
|
||||||
ApplyPatch KVM-x86-Prevent-host-from-panicking-on-shared-MSR-wr.patch
|
|
||||||
ApplyPatch KVM-x86-Improve-thread-safety-in-pit.patch
|
|
||||||
ApplyPatch KVM-x86-Fix-wrong-masking-on-relative-jump-call.patch
|
|
||||||
ApplyPatch KVM-x86-Emulator-fixes-for-eip-canonical-checks-on-n.patch
|
|
||||||
ApplyPatch KVM-x86-Handle-errors-when-RIP-is-set-during-far-jum.patch
|
|
||||||
ApplyPatch kvm-vmx-handle-invvpid-vm-exit-gracefully.patch
|
|
||||||
ApplyPatch kvm-x86-don-t-kill-guest-on-unknown-exit-reason.patch
|
|
||||||
ApplyPatch KVM-x86-Decoding-guest-instructions-which-cross-page.patch
|
|
||||||
ApplyPatch KVM-emulate-avoid-accessing-NULL-ctxt-memopp.patch
|
|
||||||
ApplyPatch KVM-x86-Emulator-does-not-decode-clflush-well.patch
|
|
||||||
ApplyPatch KVM-x86-PREFETCH-and-HINT_NOP-should-have-SrcMem-fla.patch
|
|
||||||
ApplyPatch kvm-fix-excessive-pages-un-pinning-in-kvm_iommu_map-.patch
|
|
||||||
|
|
||||||
%if 0%{?aarch64patches}
|
%if 0%{?aarch64patches}
|
||||||
ApplyPatch kernel-arm64.patch
|
ApplyPatch kernel-arm64.patch
|
||||||
%ifnarch aarch64 # this is stupid, but i want to notice before secondary koji does.
|
%ifnarch aarch64 # this is stupid, but i want to notice before secondary koji does.
|
||||||
@ -2255,6 +2217,9 @@ fi
|
|||||||
# ||----w |
|
# ||----w |
|
||||||
# || ||
|
# || ||
|
||||||
%changelog
|
%changelog
|
||||||
|
* Sun Oct 26 2014 Josh Boyer <jwboyer@fedoraproject.org> - 3.18.0-0.rc1.git4.1
|
||||||
|
- Linux v3.18-rc1-422-g2cc91884b6b3
|
||||||
|
|
||||||
* Fri Oct 24 2014 Josh Boyer <jwboyer@fedoraproject.org> - 3.18.0-0.rc1.git3.3
|
* Fri Oct 24 2014 Josh Boyer <jwboyer@fedoraproject.org> - 3.18.0-0.rc1.git3.3
|
||||||
- CVE-2014-3610 kvm: noncanonical MSR writes (rhbz 1144883 1156543)
|
- CVE-2014-3610 kvm: noncanonical MSR writes (rhbz 1144883 1156543)
|
||||||
- CVE-2014-3611 kvm: PIT timer race condition (rhbz 1144878 1156537)
|
- CVE-2014-3611 kvm: PIT timer race condition (rhbz 1144878 1156537)
|
||||||
|
@ -1,78 +0,0 @@
|
|||||||
From: Quentin Casasnovas <quentin.casasnovas@oracle.com>
|
|
||||||
Date: Fri, 24 Oct 2014 17:07:24 +0200
|
|
||||||
Subject: [PATCH] kvm: fix excessive pages un-pinning in kvm_iommu_map error
|
|
||||||
path.
|
|
||||||
|
|
||||||
The third parameter of kvm_unpin_pages() when called from
|
|
||||||
kvm_iommu_map_pages() is wrong, it should be the number of pages to un-pin
|
|
||||||
and not the page size.
|
|
||||||
|
|
||||||
This error was facilitated with an inconsistent API: kvm_pin_pages() takes
|
|
||||||
a size, but kvn_unpin_pages() takes a number of pages, so fix the problem
|
|
||||||
by matching the two.
|
|
||||||
|
|
||||||
This was introduced by commit 350b8bd ("kvm: iommu: fix the third parameter
|
|
||||||
of kvm_iommu_put_pages (CVE-2014-3601)"), which fixes the lack of
|
|
||||||
un-pinning for pages intended to be un-pinned (i.e. memory leak) but
|
|
||||||
unfortunately potentially aggravated the number of pages we un-pin that
|
|
||||||
should have stayed pinned. As far as I understand though, the same
|
|
||||||
practical mitigations apply.
|
|
||||||
|
|
||||||
This issue was found during review of Red Hat 6.6 patches to prepare
|
|
||||||
Ksplice rebootless updates.
|
|
||||||
|
|
||||||
Thanks to Vegard for his time on a late Friday evening to help me in
|
|
||||||
understanding this code.
|
|
||||||
|
|
||||||
Fixes: 350b8bd ("kvm: iommu: fix the third parameter of... (CVE-2014-3601)")
|
|
||||||
Cc: stable@vger.kernel.org
|
|
||||||
Signed-off-by: Quentin Casasnovas <quentin.casasnovas@oracle.com>
|
|
||||||
Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com>
|
|
||||||
Signed-off-by: Jamie Iles <jamie.iles@oracle.com>
|
|
||||||
Reviewed-by: Sasha Levin <sasha.levin@oracle.com>
|
|
||||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
||||||
---
|
|
||||||
virt/kvm/iommu.c | 8 ++++----
|
|
||||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c
|
|
||||||
index e51d9f9b995f..c1e6ae989a43 100644
|
|
||||||
--- a/virt/kvm/iommu.c
|
|
||||||
+++ b/virt/kvm/iommu.c
|
|
||||||
@@ -43,13 +43,13 @@ static void kvm_iommu_put_pages(struct kvm *kvm,
|
|
||||||
gfn_t base_gfn, unsigned long npages);
|
|
||||||
|
|
||||||
static pfn_t kvm_pin_pages(struct kvm_memory_slot *slot, gfn_t gfn,
|
|
||||||
- unsigned long size)
|
|
||||||
+ unsigned long npages)
|
|
||||||
{
|
|
||||||
gfn_t end_gfn;
|
|
||||||
pfn_t pfn;
|
|
||||||
|
|
||||||
pfn = gfn_to_pfn_memslot(slot, gfn);
|
|
||||||
- end_gfn = gfn + (size >> PAGE_SHIFT);
|
|
||||||
+ end_gfn = gfn + npages;
|
|
||||||
gfn += 1;
|
|
||||||
|
|
||||||
if (is_error_noslot_pfn(pfn))
|
|
||||||
@@ -119,7 +119,7 @@ int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot)
|
|
||||||
* Pin all pages we are about to map in memory. This is
|
|
||||||
* important because we unmap and unpin in 4kb steps later.
|
|
||||||
*/
|
|
||||||
- pfn = kvm_pin_pages(slot, gfn, page_size);
|
|
||||||
+ pfn = kvm_pin_pages(slot, gfn, page_size >> PAGE_SHIFT);
|
|
||||||
if (is_error_noslot_pfn(pfn)) {
|
|
||||||
gfn += 1;
|
|
||||||
continue;
|
|
||||||
@@ -131,7 +131,7 @@ int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot)
|
|
||||||
if (r) {
|
|
||||||
printk(KERN_ERR "kvm_iommu_map_address:"
|
|
||||||
"iommu failed to map pfn=%llx\n", pfn);
|
|
||||||
- kvm_unpin_pages(kvm, pfn, page_size);
|
|
||||||
+ kvm_unpin_pages(kvm, pfn, page_size >> PAGE_SHIFT);
|
|
||||||
goto unmap_pages;
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
1.9.3
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
|||||||
From: Petr Matousek <pmatouse@redhat.com>
|
|
||||||
Date: Fri, 24 Oct 2014 17:07:18 +0200
|
|
||||||
Subject: [PATCH] kvm: vmx: handle invvpid vm exit gracefully
|
|
||||||
|
|
||||||
On systems with invvpid instruction support (corresponding bit in
|
|
||||||
IA32_VMX_EPT_VPID_CAP MSR is set) guest invocation of invvpid
|
|
||||||
causes vm exit, which is currently not handled and results in
|
|
||||||
propagation of unknown exit to userspace.
|
|
||||||
|
|
||||||
Fix this by installing an invvpid vm exit handler.
|
|
||||||
|
|
||||||
This is CVE-2014-3646.
|
|
||||||
|
|
||||||
Cc: stable@vger.kernel.org
|
|
||||||
Signed-off-by: Petr Matousek <pmatouse@redhat.com>
|
|
||||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
||||||
---
|
|
||||||
arch/x86/include/uapi/asm/vmx.h | 2 ++
|
|
||||||
arch/x86/kvm/vmx.c | 9 ++++++++-
|
|
||||||
2 files changed, 10 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/arch/x86/include/uapi/asm/vmx.h b/arch/x86/include/uapi/asm/vmx.h
|
|
||||||
index 0e79420376eb..990a2fe1588d 100644
|
|
||||||
--- a/arch/x86/include/uapi/asm/vmx.h
|
|
||||||
+++ b/arch/x86/include/uapi/asm/vmx.h
|
|
||||||
@@ -67,6 +67,7 @@
|
|
||||||
#define EXIT_REASON_EPT_MISCONFIG 49
|
|
||||||
#define EXIT_REASON_INVEPT 50
|
|
||||||
#define EXIT_REASON_PREEMPTION_TIMER 52
|
|
||||||
+#define EXIT_REASON_INVVPID 53
|
|
||||||
#define EXIT_REASON_WBINVD 54
|
|
||||||
#define EXIT_REASON_XSETBV 55
|
|
||||||
#define EXIT_REASON_APIC_WRITE 56
|
|
||||||
@@ -114,6 +115,7 @@
|
|
||||||
{ EXIT_REASON_EOI_INDUCED, "EOI_INDUCED" }, \
|
|
||||||
{ EXIT_REASON_INVALID_STATE, "INVALID_STATE" }, \
|
|
||||||
{ EXIT_REASON_INVD, "INVD" }, \
|
|
||||||
+ { EXIT_REASON_INVVPID, "INVVPID" }, \
|
|
||||||
{ EXIT_REASON_INVPCID, "INVPCID" }
|
|
||||||
|
|
||||||
#endif /* _UAPIVMX_H */
|
|
||||||
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
|
|
||||||
index 7e2c098b59c9..cf3cd079ec52 100644
|
|
||||||
--- a/arch/x86/kvm/vmx.c
|
|
||||||
+++ b/arch/x86/kvm/vmx.c
|
|
||||||
@@ -6746,6 +6746,12 @@ static int handle_invept(struct kvm_vcpu *vcpu)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int handle_invvpid(struct kvm_vcpu *vcpu)
|
|
||||||
+{
|
|
||||||
+ kvm_queue_exception(vcpu, UD_VECTOR);
|
|
||||||
+ return 1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* The exit handlers return 1 if the exit was handled fully and guest execution
|
|
||||||
* may resume. Otherwise they set the kvm_run parameter to indicate what needs
|
|
||||||
@@ -6791,6 +6797,7 @@ static int (*const kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
|
|
||||||
[EXIT_REASON_MWAIT_INSTRUCTION] = handle_mwait,
|
|
||||||
[EXIT_REASON_MONITOR_INSTRUCTION] = handle_monitor,
|
|
||||||
[EXIT_REASON_INVEPT] = handle_invept,
|
|
||||||
+ [EXIT_REASON_INVVPID] = handle_invvpid,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const int kvm_vmx_max_exit_handlers =
|
|
||||||
@@ -7026,7 +7033,7 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
|
|
||||||
case EXIT_REASON_VMPTRST: case EXIT_REASON_VMREAD:
|
|
||||||
case EXIT_REASON_VMRESUME: case EXIT_REASON_VMWRITE:
|
|
||||||
case EXIT_REASON_VMOFF: case EXIT_REASON_VMON:
|
|
||||||
- case EXIT_REASON_INVEPT:
|
|
||||||
+ case EXIT_REASON_INVEPT: case EXIT_REASON_INVVPID:
|
|
||||||
/*
|
|
||||||
* VMX instructions trap unconditionally. This allows L1 to
|
|
||||||
* emulate them for its L2 guest, i.e., allows 3-level nesting!
|
|
||||||
--
|
|
||||||
1.9.3
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
|||||||
From: "Michael S. Tsirkin" <mst@redhat.com>
|
|
||||||
Date: Fri, 24 Oct 2014 17:07:19 +0200
|
|
||||||
Subject: [PATCH] kvm: x86: don't kill guest on unknown exit reason
|
|
||||||
|
|
||||||
KVM_EXIT_UNKNOWN is a kvm bug, we don't really know whether it was
|
|
||||||
triggered by a priveledged application. Let's not kill the guest: WARN
|
|
||||||
and inject #UD instead.
|
|
||||||
|
|
||||||
Cc: stable@vger.kernel.org
|
|
||||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
|
||||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
||||||
---
|
|
||||||
arch/x86/kvm/svm.c | 6 +++---
|
|
||||||
arch/x86/kvm/vmx.c | 6 +++---
|
|
||||||
2 files changed, 6 insertions(+), 6 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
|
|
||||||
index 00bed2c5e948..7527cefc5a43 100644
|
|
||||||
--- a/arch/x86/kvm/svm.c
|
|
||||||
+++ b/arch/x86/kvm/svm.c
|
|
||||||
@@ -3551,9 +3551,9 @@ static int handle_exit(struct kvm_vcpu *vcpu)
|
|
||||||
|
|
||||||
if (exit_code >= ARRAY_SIZE(svm_exit_handlers)
|
|
||||||
|| !svm_exit_handlers[exit_code]) {
|
|
||||||
- kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
|
|
||||||
- kvm_run->hw.hardware_exit_reason = exit_code;
|
|
||||||
- return 0;
|
|
||||||
+ WARN_ONCE(1, "vmx: unexpected exit reason 0x%x\n", exit_code);
|
|
||||||
+ kvm_queue_exception(vcpu, UD_VECTOR);
|
|
||||||
+ return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return svm_exit_handlers[exit_code](svm);
|
|
||||||
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
|
|
||||||
index cf3cd079ec52..a8b76c4c95e2 100644
|
|
||||||
--- a/arch/x86/kvm/vmx.c
|
|
||||||
+++ b/arch/x86/kvm/vmx.c
|
|
||||||
@@ -7174,10 +7174,10 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu)
|
|
||||||
&& kvm_vmx_exit_handlers[exit_reason])
|
|
||||||
return kvm_vmx_exit_handlers[exit_reason](vcpu);
|
|
||||||
else {
|
|
||||||
- vcpu->run->exit_reason = KVM_EXIT_UNKNOWN;
|
|
||||||
- vcpu->run->hw.hardware_exit_reason = exit_reason;
|
|
||||||
+ WARN_ONCE(1, "vmx: unexpected exit reason 0x%x\n", exit_reason);
|
|
||||||
+ kvm_queue_exception(vcpu, UD_VECTOR);
|
|
||||||
+ return 1;
|
|
||||||
}
|
|
||||||
- return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
|
|
||||||
--
|
|
||||||
1.9.3
|
|
||||||
|
|
2
sources
2
sources
@ -1,4 +1,4 @@
|
|||||||
fb30d0f29214d75cddd2faa94f73d5cf linux-3.17.tar.xz
|
fb30d0f29214d75cddd2faa94f73d5cf linux-3.17.tar.xz
|
||||||
159e969cbc27201d8e2fa0f609dc722f perf-man-3.17.tar.gz
|
159e969cbc27201d8e2fa0f609dc722f perf-man-3.17.tar.gz
|
||||||
e765b9b3a7db1a947467cb27dbc15314 patch-3.18-rc1.xz
|
e765b9b3a7db1a947467cb27dbc15314 patch-3.18-rc1.xz
|
||||||
c92d73fbb956a1738060366236d0aa73 patch-3.18-rc1-git3.xz
|
87538a9bd6256b980e3788f91a301385 patch-3.18-rc1-git4.xz
|
||||||
|
Loading…
Reference in New Issue
Block a user