mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-28 00:12:28 -04:00
Merge tag 'kvm-memslots-6.14' of https://github.com/kvm-x86/linux into HEAD
KVM kvm_set_memory_region() cleanups and hardening for 6.14: - Add proper lockdep assertions when setting memory regions. - Add a dedicated API for setting KVM-internal memory regions. - Explicitly disallow all flags for KVM-internal memory regions.
This commit is contained in:
@@ -12800,7 +12800,8 @@ void __user * __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa,
|
||||
struct kvm_memslots *slots = kvm_memslots(kvm);
|
||||
struct kvm_memory_slot *slot;
|
||||
|
||||
/* Called with kvm->slots_lock held. */
|
||||
lockdep_assert_held(&kvm->slots_lock);
|
||||
|
||||
if (WARN_ON(id >= KVM_MEM_SLOTS_NUM))
|
||||
return ERR_PTR_USR(-EINVAL);
|
||||
|
||||
@@ -12833,7 +12834,7 @@ void __user * __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa,
|
||||
m.guest_phys_addr = gpa;
|
||||
m.userspace_addr = hva;
|
||||
m.memory_size = size;
|
||||
r = __kvm_set_memory_region(kvm, &m);
|
||||
r = kvm_set_internal_memslot(kvm, &m);
|
||||
if (r < 0)
|
||||
return ERR_PTR_USR(r);
|
||||
}
|
||||
@@ -12934,7 +12935,7 @@ static int kvm_alloc_memslot_metadata(struct kvm *kvm,
|
||||
|
||||
/*
|
||||
* Clear out the previous array pointers for the KVM_MR_MOVE case. The
|
||||
* old arrays will be freed by __kvm_set_memory_region() if installing
|
||||
* old arrays will be freed by kvm_set_memory_region() if installing
|
||||
* the new memslot is successful.
|
||||
*/
|
||||
memset(&slot->arch, 0, sizeof(slot->arch));
|
||||
|
||||
@@ -1183,7 +1183,7 @@ struct kvm_memory_slot *kvm_vcpu_gfn_to_memslot(struct kvm_vcpu *vcpu, gfn_t gfn
|
||||
* -- just change its flags
|
||||
*
|
||||
* Since flags can be changed by some of these operations, the following
|
||||
* differentiation is the best we can do for __kvm_set_memory_region():
|
||||
* differentiation is the best we can do for kvm_set_memory_region():
|
||||
*/
|
||||
enum kvm_mr_change {
|
||||
KVM_MR_CREATE,
|
||||
@@ -1192,10 +1192,8 @@ enum kvm_mr_change {
|
||||
KVM_MR_FLAGS_ONLY,
|
||||
};
|
||||
|
||||
int kvm_set_memory_region(struct kvm *kvm,
|
||||
const struct kvm_userspace_memory_region2 *mem);
|
||||
int __kvm_set_memory_region(struct kvm *kvm,
|
||||
const struct kvm_userspace_memory_region2 *mem);
|
||||
int kvm_set_internal_memslot(struct kvm *kvm,
|
||||
const struct kvm_userspace_memory_region2 *mem);
|
||||
void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *slot);
|
||||
void kvm_arch_memslots_updated(struct kvm *kvm, u64 gen);
|
||||
int kvm_arch_prepare_memory_region(struct kvm *kvm,
|
||||
|
||||
@@ -1926,16 +1926,8 @@ static bool kvm_check_memslot_overlap(struct kvm_memslots *slots, int id,
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate some memory and give it an address in the guest physical address
|
||||
* space.
|
||||
*
|
||||
* Discontiguous memory is allowed, mostly for framebuffers.
|
||||
*
|
||||
* Must be called holding kvm->slots_lock for write.
|
||||
*/
|
||||
int __kvm_set_memory_region(struct kvm *kvm,
|
||||
const struct kvm_userspace_memory_region2 *mem)
|
||||
static int kvm_set_memory_region(struct kvm *kvm,
|
||||
const struct kvm_userspace_memory_region2 *mem)
|
||||
{
|
||||
struct kvm_memory_slot *old, *new;
|
||||
struct kvm_memslots *slots;
|
||||
@@ -1945,6 +1937,8 @@ int __kvm_set_memory_region(struct kvm *kvm,
|
||||
int as_id, id;
|
||||
int r;
|
||||
|
||||
lockdep_assert_held(&kvm->slots_lock);
|
||||
|
||||
r = check_memory_region_flags(kvm, mem);
|
||||
if (r)
|
||||
return r;
|
||||
@@ -2056,19 +2050,19 @@ int __kvm_set_memory_region(struct kvm *kvm,
|
||||
kfree(new);
|
||||
return r;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__kvm_set_memory_region);
|
||||
|
||||
int kvm_set_memory_region(struct kvm *kvm,
|
||||
const struct kvm_userspace_memory_region2 *mem)
|
||||
int kvm_set_internal_memslot(struct kvm *kvm,
|
||||
const struct kvm_userspace_memory_region2 *mem)
|
||||
{
|
||||
int r;
|
||||
if (WARN_ON_ONCE(mem->slot < KVM_USER_MEM_SLOTS))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&kvm->slots_lock);
|
||||
r = __kvm_set_memory_region(kvm, mem);
|
||||
mutex_unlock(&kvm->slots_lock);
|
||||
return r;
|
||||
if (WARN_ON_ONCE(mem->flags))
|
||||
return -EINVAL;
|
||||
|
||||
return kvm_set_memory_region(kvm, mem);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kvm_set_memory_region);
|
||||
EXPORT_SYMBOL_GPL(kvm_set_internal_memslot);
|
||||
|
||||
static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,
|
||||
struct kvm_userspace_memory_region2 *mem)
|
||||
@@ -2076,6 +2070,7 @@ static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,
|
||||
if ((u16)mem->slot >= KVM_USER_MEM_SLOTS)
|
||||
return -EINVAL;
|
||||
|
||||
guard(mutex)(&kvm->slots_lock);
|
||||
return kvm_set_memory_region(kvm, mem);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user