Miscellaneous bugfixes. The main interesting one is a NULL pointer dereference
reported by syzkaller ("KVM: x86: Immediately reset the MMU context when the SMM flag is cleared"). -----BEGIN PGP SIGNATURE----- iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmDLldwUHHBib256aW5p QHJlZGhhdC5jb20ACgkQv/vSX3jHroPTOgf/XpAehLdWlx2877ulcBD0Kjt0tLvH OFHRD1Ir0d1Ay3DX8qmxLquXHB4CoDGZBwi1d7AI165kUP/XLmV0bY6TZ74inI/P CaD8Bsbm8+iBl5jrovEPc+223bK+3OFOvo2pk6M/MlsO/ExRikaPDtHOnkfousbl nLX8v2qd7ihWyJOdLJMU9pV8E2iczQoCuH9yWBHdCrxRxWtPzkEekPWb0sujByiF 4tD7sqiEA3ugbF1Wm5keQV63NLplfxx+Zun0FV+tbpjjxQWAGl81dP+zmqok0sM/ qQCyZevt6jLLkL+Fn6hI6PP9OTeYreX2fgwhWXs71d2js33yNg5Veqx5Bw== =Gs/y -----END PGP SIGNATURE----- Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm Pull kvm fixes from Paolo Bonzini: "Miscellaneous bugfixes. The main interesting one is a NULL pointer dereference reported by syzkaller ("KVM: x86: Immediately reset the MMU context when the SMM flag is cleared")" * tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: KVM: selftests: Fix kvm_check_cap() assertion KVM: x86/mmu: Calculate and check "full" mmu_role for nested MMU KVM: X86: Fix x86_emulator slab cache leak KVM: SVM: Call SEV Guest Decommission if ASID binding fails KVM: x86: Immediately reset the MMU context when the SMM flag is cleared KVM: x86: Fix fall-through warnings for Clang KVM: SVM: fix doc warnings KVM: selftests: Fix compiling errors when initializing the static structure kvm: LAPIC: Restore guard to prevent illegal APIC register access
This commit is contained in:
commit
fd0aa1a456
|
@ -655,6 +655,7 @@ static int __do_cpuid_func_emulated(struct kvm_cpuid_array *array, u32 func)
|
|||
if (kvm_cpu_cap_has(X86_FEATURE_RDTSCP))
|
||||
entry->ecx = F(RDPID);
|
||||
++array->nent;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1410,6 +1410,9 @@ int kvm_lapic_reg_read(struct kvm_lapic *apic, u32 offset, int len,
|
|||
if (!apic_x2apic_mode(apic))
|
||||
valid_reg_mask |= APIC_REG_MASK(APIC_ARBPRI);
|
||||
|
||||
if (alignment + len > 4)
|
||||
return 1;
|
||||
|
||||
if (offset > 0x3f0 || !(valid_reg_mask & APIC_REG_MASK(offset)))
|
||||
return 1;
|
||||
|
||||
|
|
|
@ -4739,9 +4739,33 @@ static void init_kvm_softmmu(struct kvm_vcpu *vcpu)
|
|||
context->inject_page_fault = kvm_inject_page_fault;
|
||||
}
|
||||
|
||||
static union kvm_mmu_role kvm_calc_nested_mmu_role(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
union kvm_mmu_role role = kvm_calc_shadow_root_page_role_common(vcpu, false);
|
||||
|
||||
/*
|
||||
* Nested MMUs are used only for walking L2's gva->gpa, they never have
|
||||
* shadow pages of their own and so "direct" has no meaning. Set it
|
||||
* to "true" to try to detect bogus usage of the nested MMU.
|
||||
*/
|
||||
role.base.direct = true;
|
||||
|
||||
if (!is_paging(vcpu))
|
||||
role.base.level = 0;
|
||||
else if (is_long_mode(vcpu))
|
||||
role.base.level = is_la57_mode(vcpu) ? PT64_ROOT_5LEVEL :
|
||||
PT64_ROOT_4LEVEL;
|
||||
else if (is_pae(vcpu))
|
||||
role.base.level = PT32E_ROOT_LEVEL;
|
||||
else
|
||||
role.base.level = PT32_ROOT_LEVEL;
|
||||
|
||||
return role;
|
||||
}
|
||||
|
||||
static void init_kvm_nested_mmu(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
union kvm_mmu_role new_role = kvm_calc_mmu_role_common(vcpu, false);
|
||||
union kvm_mmu_role new_role = kvm_calc_nested_mmu_role(vcpu);
|
||||
struct kvm_mmu *g_context = &vcpu->arch.nested_mmu;
|
||||
|
||||
if (new_role.as_u64 == g_context->mmu_role.as_u64)
|
||||
|
|
|
@ -221,7 +221,7 @@ static u64 *avic_get_physical_id_entry(struct kvm_vcpu *vcpu,
|
|||
return &avic_physical_id_table[index];
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Note:
|
||||
* AVIC hardware walks the nested page table to check permissions,
|
||||
* but does not use the SPA address specified in the leaf page
|
||||
|
@ -764,7 +764,7 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Note:
|
||||
* The HW cannot support posting multicast/broadcast
|
||||
* interrupts to a vCPU. So, we still use legacy interrupt
|
||||
|
@ -1005,7 +1005,7 @@ void avic_vcpu_put(struct kvm_vcpu *vcpu)
|
|||
WRITE_ONCE(*(svm->avic_physical_id_cache), entry);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* This function is called during VCPU halt/unhalt.
|
||||
*/
|
||||
static void avic_set_running(struct kvm_vcpu *vcpu, bool is_run)
|
||||
|
|
|
@ -199,9 +199,19 @@ static void sev_asid_free(struct kvm_sev_info *sev)
|
|||
sev->misc_cg = NULL;
|
||||
}
|
||||
|
||||
static void sev_unbind_asid(struct kvm *kvm, unsigned int handle)
|
||||
static void sev_decommission(unsigned int handle)
|
||||
{
|
||||
struct sev_data_decommission decommission;
|
||||
|
||||
if (!handle)
|
||||
return;
|
||||
|
||||
decommission.handle = handle;
|
||||
sev_guest_decommission(&decommission, NULL);
|
||||
}
|
||||
|
||||
static void sev_unbind_asid(struct kvm *kvm, unsigned int handle)
|
||||
{
|
||||
struct sev_data_deactivate deactivate;
|
||||
|
||||
if (!handle)
|
||||
|
@ -214,9 +224,7 @@ static void sev_unbind_asid(struct kvm *kvm, unsigned int handle)
|
|||
sev_guest_deactivate(&deactivate, NULL);
|
||||
up_read(&sev_deactivate_lock);
|
||||
|
||||
/* decommission handle */
|
||||
decommission.handle = handle;
|
||||
sev_guest_decommission(&decommission, NULL);
|
||||
sev_decommission(handle);
|
||||
}
|
||||
|
||||
static int sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp)
|
||||
|
@ -341,8 +349,10 @@ static int sev_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp)
|
|||
|
||||
/* Bind ASID to this guest */
|
||||
ret = sev_bind_asid(kvm, start.handle, error);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
sev_decommission(start.handle);
|
||||
goto e_free_session;
|
||||
}
|
||||
|
||||
/* return handle to userspace */
|
||||
params.handle = start.handle;
|
||||
|
|
|
@ -6247,6 +6247,7 @@ void vmx_set_virtual_apic_mode(struct kvm_vcpu *vcpu)
|
|||
switch (kvm_get_apic_mode(vcpu)) {
|
||||
case LAPIC_MODE_INVALID:
|
||||
WARN_ONCE(true, "Invalid local APIC state");
|
||||
break;
|
||||
case LAPIC_MODE_DISABLED:
|
||||
break;
|
||||
case LAPIC_MODE_XAPIC:
|
||||
|
|
|
@ -7106,7 +7106,10 @@ static unsigned emulator_get_hflags(struct x86_emulate_ctxt *ctxt)
|
|||
|
||||
static void emulator_set_hflags(struct x86_emulate_ctxt *ctxt, unsigned emul_flags)
|
||||
{
|
||||
emul_to_vcpu(ctxt)->arch.hflags = emul_flags;
|
||||
struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
|
||||
|
||||
vcpu->arch.hflags = emul_flags;
|
||||
kvm_mmu_reset_context(vcpu);
|
||||
}
|
||||
|
||||
static int emulator_pre_leave_smm(struct x86_emulate_ctxt *ctxt,
|
||||
|
@ -8258,6 +8261,7 @@ void kvm_arch_exit(void)
|
|||
kvm_x86_ops.hardware_enable = NULL;
|
||||
kvm_mmu_module_exit();
|
||||
free_percpu(user_return_msrs);
|
||||
kmem_cache_destroy(x86_emulator_cache);
|
||||
kmem_cache_destroy(x86_fpu_cache);
|
||||
#ifdef CONFIG_KVM_XEN
|
||||
static_key_deferred_flush(&kvm_xen_enabled);
|
||||
|
|
|
@ -82,7 +82,7 @@ int kvm_check_cap(long cap)
|
|||
|
||||
kvm_fd = open_kvm_dev_path_or_exit();
|
||||
ret = ioctl(kvm_fd, KVM_CHECK_EXTENSION, cap);
|
||||
TEST_ASSERT(ret != -1, "KVM_CHECK_EXTENSION IOCTL failed,\n"
|
||||
TEST_ASSERT(ret >= 0, "KVM_CHECK_EXTENSION IOCTL failed,\n"
|
||||
" rc: %i errno: %i", ret, errno);
|
||||
|
||||
close(kvm_fd);
|
||||
|
|
|
@ -166,75 +166,75 @@ size_t get_def_hugetlb_pagesz(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define ANON_FLAGS (MAP_PRIVATE | MAP_ANONYMOUS)
|
||||
#define ANON_HUGE_FLAGS (ANON_FLAGS | MAP_HUGETLB)
|
||||
|
||||
const struct vm_mem_backing_src_alias *vm_mem_backing_src_alias(uint32_t i)
|
||||
{
|
||||
static const int anon_flags = MAP_PRIVATE | MAP_ANONYMOUS;
|
||||
static const int anon_huge_flags = anon_flags | MAP_HUGETLB;
|
||||
|
||||
static const struct vm_mem_backing_src_alias aliases[] = {
|
||||
[VM_MEM_SRC_ANONYMOUS] = {
|
||||
.name = "anonymous",
|
||||
.flag = anon_flags,
|
||||
.flag = ANON_FLAGS,
|
||||
},
|
||||
[VM_MEM_SRC_ANONYMOUS_THP] = {
|
||||
.name = "anonymous_thp",
|
||||
.flag = anon_flags,
|
||||
.flag = ANON_FLAGS,
|
||||
},
|
||||
[VM_MEM_SRC_ANONYMOUS_HUGETLB] = {
|
||||
.name = "anonymous_hugetlb",
|
||||
.flag = anon_huge_flags,
|
||||
.flag = ANON_HUGE_FLAGS,
|
||||
},
|
||||
[VM_MEM_SRC_ANONYMOUS_HUGETLB_16KB] = {
|
||||
.name = "anonymous_hugetlb_16kb",
|
||||
.flag = anon_huge_flags | MAP_HUGE_16KB,
|
||||
.flag = ANON_HUGE_FLAGS | MAP_HUGE_16KB,
|
||||
},
|
||||
[VM_MEM_SRC_ANONYMOUS_HUGETLB_64KB] = {
|
||||
.name = "anonymous_hugetlb_64kb",
|
||||
.flag = anon_huge_flags | MAP_HUGE_64KB,
|
||||
.flag = ANON_HUGE_FLAGS | MAP_HUGE_64KB,
|
||||
},
|
||||
[VM_MEM_SRC_ANONYMOUS_HUGETLB_512KB] = {
|
||||
.name = "anonymous_hugetlb_512kb",
|
||||
.flag = anon_huge_flags | MAP_HUGE_512KB,
|
||||
.flag = ANON_HUGE_FLAGS | MAP_HUGE_512KB,
|
||||
},
|
||||
[VM_MEM_SRC_ANONYMOUS_HUGETLB_1MB] = {
|
||||
.name = "anonymous_hugetlb_1mb",
|
||||
.flag = anon_huge_flags | MAP_HUGE_1MB,
|
||||
.flag = ANON_HUGE_FLAGS | MAP_HUGE_1MB,
|
||||
},
|
||||
[VM_MEM_SRC_ANONYMOUS_HUGETLB_2MB] = {
|
||||
.name = "anonymous_hugetlb_2mb",
|
||||
.flag = anon_huge_flags | MAP_HUGE_2MB,
|
||||
.flag = ANON_HUGE_FLAGS | MAP_HUGE_2MB,
|
||||
},
|
||||
[VM_MEM_SRC_ANONYMOUS_HUGETLB_8MB] = {
|
||||
.name = "anonymous_hugetlb_8mb",
|
||||
.flag = anon_huge_flags | MAP_HUGE_8MB,
|
||||
.flag = ANON_HUGE_FLAGS | MAP_HUGE_8MB,
|
||||
},
|
||||
[VM_MEM_SRC_ANONYMOUS_HUGETLB_16MB] = {
|
||||
.name = "anonymous_hugetlb_16mb",
|
||||
.flag = anon_huge_flags | MAP_HUGE_16MB,
|
||||
.flag = ANON_HUGE_FLAGS | MAP_HUGE_16MB,
|
||||
},
|
||||
[VM_MEM_SRC_ANONYMOUS_HUGETLB_32MB] = {
|
||||
.name = "anonymous_hugetlb_32mb",
|
||||
.flag = anon_huge_flags | MAP_HUGE_32MB,
|
||||
.flag = ANON_HUGE_FLAGS | MAP_HUGE_32MB,
|
||||
},
|
||||
[VM_MEM_SRC_ANONYMOUS_HUGETLB_256MB] = {
|
||||
.name = "anonymous_hugetlb_256mb",
|
||||
.flag = anon_huge_flags | MAP_HUGE_256MB,
|
||||
.flag = ANON_HUGE_FLAGS | MAP_HUGE_256MB,
|
||||
},
|
||||
[VM_MEM_SRC_ANONYMOUS_HUGETLB_512MB] = {
|
||||
.name = "anonymous_hugetlb_512mb",
|
||||
.flag = anon_huge_flags | MAP_HUGE_512MB,
|
||||
.flag = ANON_HUGE_FLAGS | MAP_HUGE_512MB,
|
||||
},
|
||||
[VM_MEM_SRC_ANONYMOUS_HUGETLB_1GB] = {
|
||||
.name = "anonymous_hugetlb_1gb",
|
||||
.flag = anon_huge_flags | MAP_HUGE_1GB,
|
||||
.flag = ANON_HUGE_FLAGS | MAP_HUGE_1GB,
|
||||
},
|
||||
[VM_MEM_SRC_ANONYMOUS_HUGETLB_2GB] = {
|
||||
.name = "anonymous_hugetlb_2gb",
|
||||
.flag = anon_huge_flags | MAP_HUGE_2GB,
|
||||
.flag = ANON_HUGE_FLAGS | MAP_HUGE_2GB,
|
||||
},
|
||||
[VM_MEM_SRC_ANONYMOUS_HUGETLB_16GB] = {
|
||||
.name = "anonymous_hugetlb_16gb",
|
||||
.flag = anon_huge_flags | MAP_HUGE_16GB,
|
||||
.flag = ANON_HUGE_FLAGS | MAP_HUGE_16GB,
|
||||
},
|
||||
[VM_MEM_SRC_SHMEM] = {
|
||||
.name = "shmem",
|
||||
|
|
Loading…
Reference in New Issue