Skip to content

Commit 4e4f38f

Browse files
committed
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.
2 parents 5cf32af + 0cc3cb2 commit 4e4f38f

File tree

3 files changed

+21
-27
lines changed

3 files changed

+21
-27
lines changed

arch/x86/kvm/x86.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12800,7 +12800,8 @@ void __user * __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa,
1280012800
struct kvm_memslots *slots = kvm_memslots(kvm);
1280112801
struct kvm_memory_slot *slot;
1280212802

12803-
/* Called with kvm->slots_lock held. */
12803+
lockdep_assert_held(&kvm->slots_lock);
12804+
1280412805
if (WARN_ON(id >= KVM_MEM_SLOTS_NUM))
1280512806
return ERR_PTR_USR(-EINVAL);
1280612807

@@ -12833,7 +12834,7 @@ void __user * __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa,
1283312834
m.guest_phys_addr = gpa;
1283412835
m.userspace_addr = hva;
1283512836
m.memory_size = size;
12836-
r = __kvm_set_memory_region(kvm, &m);
12837+
r = kvm_set_internal_memslot(kvm, &m);
1283712838
if (r < 0)
1283812839
return ERR_PTR_USR(r);
1283912840
}
@@ -12934,7 +12935,7 @@ static int kvm_alloc_memslot_metadata(struct kvm *kvm,
1293412935

1293512936
/*
1293612937
* Clear out the previous array pointers for the KVM_MR_MOVE case. The
12937-
* old arrays will be freed by __kvm_set_memory_region() if installing
12938+
* old arrays will be freed by kvm_set_memory_region() if installing
1293812939
* the new memslot is successful.
1293912940
*/
1294012941
memset(&slot->arch, 0, sizeof(slot->arch));

include/linux/kvm_host.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,7 +1183,7 @@ struct kvm_memory_slot *kvm_vcpu_gfn_to_memslot(struct kvm_vcpu *vcpu, gfn_t gfn
11831183
* -- just change its flags
11841184
*
11851185
* Since flags can be changed by some of these operations, the following
1186-
* differentiation is the best we can do for __kvm_set_memory_region():
1186+
* differentiation is the best we can do for kvm_set_memory_region():
11871187
*/
11881188
enum kvm_mr_change {
11891189
KVM_MR_CREATE,
@@ -1192,10 +1192,8 @@ enum kvm_mr_change {
11921192
KVM_MR_FLAGS_ONLY,
11931193
};
11941194

1195-
int kvm_set_memory_region(struct kvm *kvm,
1196-
const struct kvm_userspace_memory_region2 *mem);
1197-
int __kvm_set_memory_region(struct kvm *kvm,
1198-
const struct kvm_userspace_memory_region2 *mem);
1195+
int kvm_set_internal_memslot(struct kvm *kvm,
1196+
const struct kvm_userspace_memory_region2 *mem);
11991197
void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *slot);
12001198
void kvm_arch_memslots_updated(struct kvm *kvm, u64 gen);
12011199
int kvm_arch_prepare_memory_region(struct kvm *kvm,

virt/kvm/kvm_main.c

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1926,16 +1926,8 @@ static bool kvm_check_memslot_overlap(struct kvm_memslots *slots, int id,
19261926
return false;
19271927
}
19281928

1929-
/*
1930-
* Allocate some memory and give it an address in the guest physical address
1931-
* space.
1932-
*
1933-
* Discontiguous memory is allowed, mostly for framebuffers.
1934-
*
1935-
* Must be called holding kvm->slots_lock for write.
1936-
*/
1937-
int __kvm_set_memory_region(struct kvm *kvm,
1938-
const struct kvm_userspace_memory_region2 *mem)
1929+
static int kvm_set_memory_region(struct kvm *kvm,
1930+
const struct kvm_userspace_memory_region2 *mem)
19391931
{
19401932
struct kvm_memory_slot *old, *new;
19411933
struct kvm_memslots *slots;
@@ -1945,6 +1937,8 @@ int __kvm_set_memory_region(struct kvm *kvm,
19451937
int as_id, id;
19461938
int r;
19471939

1940+
lockdep_assert_held(&kvm->slots_lock);
1941+
19481942
r = check_memory_region_flags(kvm, mem);
19491943
if (r)
19501944
return r;
@@ -2056,26 +2050,27 @@ int __kvm_set_memory_region(struct kvm *kvm,
20562050
kfree(new);
20572051
return r;
20582052
}
2059-
EXPORT_SYMBOL_GPL(__kvm_set_memory_region);
20602053

2061-
int kvm_set_memory_region(struct kvm *kvm,
2062-
const struct kvm_userspace_memory_region2 *mem)
2054+
int kvm_set_internal_memslot(struct kvm *kvm,
2055+
const struct kvm_userspace_memory_region2 *mem)
20632056
{
2064-
int r;
2057+
if (WARN_ON_ONCE(mem->slot < KVM_USER_MEM_SLOTS))
2058+
return -EINVAL;
20652059

2066-
mutex_lock(&kvm->slots_lock);
2067-
r = __kvm_set_memory_region(kvm, mem);
2068-
mutex_unlock(&kvm->slots_lock);
2069-
return r;
2060+
if (WARN_ON_ONCE(mem->flags))
2061+
return -EINVAL;
2062+
2063+
return kvm_set_memory_region(kvm, mem);
20702064
}
2071-
EXPORT_SYMBOL_GPL(kvm_set_memory_region);
2065+
EXPORT_SYMBOL_GPL(kvm_set_internal_memslot);
20722066

20732067
static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,
20742068
struct kvm_userspace_memory_region2 *mem)
20752069
{
20762070
if ((u16)mem->slot >= KVM_USER_MEM_SLOTS)
20772071
return -EINVAL;
20782072

2073+
guard(mutex)(&kvm->slots_lock);
20792074
return kvm_set_memory_region(kvm, mem);
20802075
}
20812076

0 commit comments

Comments
 (0)