mirror of
https://github.com/torvalds/linux.git
synced 2024-12-25 04:11:49 +00:00
x86 fixes for overflows and other nastiness.
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQEbBAABAgAGBQJcp6fbAAoJEL/70l94x66DpFIH+M/M5gWfGGJ2zbZGhSJpQAjd 5MvoZbJGCKqN/NVGvcjWES09z7iA79t34jMEYSBpAM1VQ5XJumpC6ITpSLg26lrD 6MCftkAQTkN+xkJMHtKENsosqrqXb+CszTC/46CkNB65xbQQuaG5HRzIbQp7VccE 3xt4FHibPC4QzjXrlOyDnzUF3TUYheVOxN3u7L5xBrmXq3tpW5U+RuCF5O9Xs0OR slf1RM4L9GBIOciaE6Q0633wDml3L/+kDg00xZ8COxIOZ7ilrgFNbtc2O6GKk1cu PFZ3D0+eoSmRoJWPEOUb4O0uPyzujo08iR7GU6Rhl4oBNA+8UqK4SYIIJtUWig== =rPQV -----END PGP SIGNATURE----- Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm Pull kvm fixes from Paolo Bonzini: "x86 fixes for overflows and other nastiness" * tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: KVM: x86: nVMX: fix x2APIC VTPR read intercept KVM: x86: nVMX: close leak of L0's x2APIC MSRs (CVE-2019-3887) KVM: SVM: prevent DBG_DECRYPT and DBG_ENCRYPT overflow kvm: svm: fix potential get_num_contig_pages overflow
This commit is contained in:
commit
bc5725f974
@ -6422,11 +6422,11 @@ e_free:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int get_num_contig_pages(int idx, struct page **inpages,
|
||||
unsigned long npages)
|
||||
static unsigned long get_num_contig_pages(unsigned long idx,
|
||||
struct page **inpages, unsigned long npages)
|
||||
{
|
||||
unsigned long paddr, next_paddr;
|
||||
int i = idx + 1, pages = 1;
|
||||
unsigned long i = idx + 1, pages = 1;
|
||||
|
||||
/* find the number of contiguous pages starting from idx */
|
||||
paddr = __sme_page_pa(inpages[idx]);
|
||||
@ -6445,12 +6445,12 @@ static int get_num_contig_pages(int idx, struct page **inpages,
|
||||
|
||||
static int sev_launch_update_data(struct kvm *kvm, struct kvm_sev_cmd *argp)
|
||||
{
|
||||
unsigned long vaddr, vaddr_end, next_vaddr, npages, size;
|
||||
unsigned long vaddr, vaddr_end, next_vaddr, npages, pages, size, i;
|
||||
struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info;
|
||||
struct kvm_sev_launch_update_data params;
|
||||
struct sev_data_launch_update_data *data;
|
||||
struct page **inpages;
|
||||
int i, ret, pages;
|
||||
int ret;
|
||||
|
||||
if (!sev_guest(kvm))
|
||||
return -ENOTTY;
|
||||
@ -6799,7 +6799,8 @@ static int sev_dbg_crypt(struct kvm *kvm, struct kvm_sev_cmd *argp, bool dec)
|
||||
struct page **src_p, **dst_p;
|
||||
struct kvm_sev_dbg debug;
|
||||
unsigned long n;
|
||||
int ret, size;
|
||||
unsigned int size;
|
||||
int ret;
|
||||
|
||||
if (!sev_guest(kvm))
|
||||
return -ENOTTY;
|
||||
@ -6807,6 +6808,11 @@ static int sev_dbg_crypt(struct kvm *kvm, struct kvm_sev_cmd *argp, bool dec)
|
||||
if (copy_from_user(&debug, (void __user *)(uintptr_t)argp->data, sizeof(debug)))
|
||||
return -EFAULT;
|
||||
|
||||
if (!debug.len || debug.src_uaddr + debug.len < debug.src_uaddr)
|
||||
return -EINVAL;
|
||||
if (!debug.dst_uaddr)
|
||||
return -EINVAL;
|
||||
|
||||
vaddr = debug.src_uaddr;
|
||||
size = debug.len;
|
||||
vaddr_end = vaddr + size;
|
||||
@ -6857,8 +6863,8 @@ static int sev_dbg_crypt(struct kvm *kvm, struct kvm_sev_cmd *argp, bool dec)
|
||||
dst_vaddr,
|
||||
len, &argp->error);
|
||||
|
||||
sev_unpin_memory(kvm, src_p, 1);
|
||||
sev_unpin_memory(kvm, dst_p, 1);
|
||||
sev_unpin_memory(kvm, src_p, n);
|
||||
sev_unpin_memory(kvm, dst_p, n);
|
||||
|
||||
if (ret)
|
||||
goto err;
|
||||
|
@ -500,6 +500,17 @@ static void nested_vmx_disable_intercept_for_msr(unsigned long *msr_bitmap_l1,
|
||||
}
|
||||
}
|
||||
|
||||
static inline void enable_x2apic_msr_intercepts(unsigned long *msr_bitmap) {
|
||||
int msr;
|
||||
|
||||
for (msr = 0x800; msr <= 0x8ff; msr += BITS_PER_LONG) {
|
||||
unsigned word = msr / BITS_PER_LONG;
|
||||
|
||||
msr_bitmap[word] = ~0;
|
||||
msr_bitmap[word + (0x800 / sizeof(long))] = ~0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Merge L0's and L1's MSR bitmap, return false to indicate that
|
||||
* we do not use the hardware.
|
||||
@ -541,29 +552,33 @@ static inline bool nested_vmx_prepare_msr_bitmap(struct kvm_vcpu *vcpu,
|
||||
return false;
|
||||
|
||||
msr_bitmap_l1 = (unsigned long *)kmap(page);
|
||||
|
||||
/*
|
||||
* To keep the control flow simple, pay eight 8-byte writes (sixteen
|
||||
* 4-byte writes on 32-bit systems) up front to enable intercepts for
|
||||
* the x2APIC MSR range and selectively disable them below.
|
||||
*/
|
||||
enable_x2apic_msr_intercepts(msr_bitmap_l0);
|
||||
|
||||
if (nested_cpu_has_virt_x2apic_mode(vmcs12)) {
|
||||
if (nested_cpu_has_apic_reg_virt(vmcs12)) {
|
||||
/*
|
||||
* L0 need not intercept reads for MSRs between 0x800 and 0x8ff, it
|
||||
* just lets the processor take the value from the virtual-APIC page;
|
||||
* take those 256 bits directly from the L1 bitmap.
|
||||
* L0 need not intercept reads for MSRs between 0x800
|
||||
* and 0x8ff, it just lets the processor take the value
|
||||
* from the virtual-APIC page; take those 256 bits
|
||||
* directly from the L1 bitmap.
|
||||
*/
|
||||
for (msr = 0x800; msr <= 0x8ff; msr += BITS_PER_LONG) {
|
||||
unsigned word = msr / BITS_PER_LONG;
|
||||
|
||||
msr_bitmap_l0[word] = msr_bitmap_l1[word];
|
||||
msr_bitmap_l0[word + (0x800 / sizeof(long))] = ~0;
|
||||
}
|
||||
} else {
|
||||
for (msr = 0x800; msr <= 0x8ff; msr += BITS_PER_LONG) {
|
||||
unsigned word = msr / BITS_PER_LONG;
|
||||
msr_bitmap_l0[word] = ~0;
|
||||
msr_bitmap_l0[word + (0x800 / sizeof(long))] = ~0;
|
||||
}
|
||||
}
|
||||
|
||||
nested_vmx_disable_intercept_for_msr(
|
||||
msr_bitmap_l1, msr_bitmap_l0,
|
||||
X2APIC_MSR(APIC_TASKPRI),
|
||||
MSR_TYPE_W);
|
||||
MSR_TYPE_R | MSR_TYPE_W);
|
||||
|
||||
if (nested_cpu_has_vid(vmcs12)) {
|
||||
nested_vmx_disable_intercept_for_msr(
|
||||
@ -575,6 +590,7 @@ static inline bool nested_vmx_prepare_msr_bitmap(struct kvm_vcpu *vcpu,
|
||||
X2APIC_MSR(APIC_SELF_IPI),
|
||||
MSR_TYPE_W);
|
||||
}
|
||||
}
|
||||
|
||||
if (spec_ctrl)
|
||||
nested_vmx_disable_intercept_for_msr(
|
||||
|
Loading…
Reference in New Issue
Block a user