]> git.ipfire.org Git - thirdparty/kernel/linux.git/blobdiff - virt/kvm/pfncache.c
KVM: Check validity of offset+length of gfn_to_pfn_cache prior to activation
[thirdparty/kernel/linux.git] / virt / kvm / pfncache.c
index 8f2121b5f2a0afe45702d01ad3f27f23a7f3e408..91b0e329006ba4379c2e468afd1a195fb2018098 100644 (file)
@@ -245,8 +245,7 @@ out_error:
        return -EFAULT;
 }
 
-static int __kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned long uhva,
-                            unsigned long len)
+static int __kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned long uhva)
 {
        unsigned long page_offset;
        bool unmap_old = false;
@@ -260,9 +259,6 @@ static int __kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned l
        if (WARN_ON_ONCE(kvm_is_error_gpa(gpa) == kvm_is_error_hva(uhva)))
                return -EINVAL;
 
-       if (!kvm_gpc_is_valid_len(gpa, uhva, len))
-               return -EINVAL;
-
        lockdep_assert_held(&gpc->refresh_lock);
 
        write_lock_irq(&gpc->lock);
@@ -365,6 +361,9 @@ int kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, unsigned long len)
 
        guard(mutex)(&gpc->refresh_lock);
 
+       if (!kvm_gpc_is_valid_len(gpc->gpa, gpc->uhva, len))
+               return -EINVAL;
+
        /*
         * If the GPA is valid then ignore the HVA, as a cache can be GPA-based
         * or HVA-based, not both.  For GPA-based caches, the HVA will be
@@ -372,7 +371,7 @@ int kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, unsigned long len)
         */
        uhva = kvm_is_error_gpa(gpc->gpa) ? gpc->uhva : KVM_HVA_ERR_BAD;
 
-       return __kvm_gpc_refresh(gpc, gpc->gpa, uhva, len);
+       return __kvm_gpc_refresh(gpc, gpc->gpa, uhva);
 }
 
 void kvm_gpc_init(struct gfn_to_pfn_cache *gpc, struct kvm *kvm)
@@ -392,6 +391,9 @@ static int __kvm_gpc_activate(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned
 {
        struct kvm *kvm = gpc->kvm;
 
+       if (!kvm_gpc_is_valid_len(gpa, uhva, len))
+               return -EINVAL;
+
        guard(mutex)(&gpc->refresh_lock);
 
        if (!gpc->active) {
@@ -411,7 +413,7 @@ static int __kvm_gpc_activate(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned
                gpc->active = true;
                write_unlock_irq(&gpc->lock);
        }
-       return __kvm_gpc_refresh(gpc, gpa, uhva, len);
+       return __kvm_gpc_refresh(gpc, gpa, uhva);
 }
 
 int kvm_gpc_activate(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned long len)