| From 2633e16de84ca22217eabad33a1d7be09fa90ba9 Mon Sep 17 00:00:00 2001 |
| From: David Rientjes <rientjes@google.com> |
| Date: Mon, 25 Mar 2019 11:47:31 -0700 |
| Subject: KVM: SVM: prevent DBG_DECRYPT and DBG_ENCRYPT overflow |
| |
| [ Upstream commit b86bc2858b389255cd44555ce4b1e427b2b770c0 ] |
| |
| This ensures that the address and length provided to DBG_DECRYPT and |
| DBG_ENCRYPT do not cause an overflow. |
| |
| At the same time, pass the actual number of pages pinned in memory to |
| sev_unpin_memory() as a cleanup. |
| |
| Reported-by: Cfir Cohen <cfir@google.com> |
| Signed-off-by: David Rientjes <rientjes@google.com> |
| Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
| Signed-off-by: Sasha Levin (Microsoft) <sashal@kernel.org> |
| --- |
| arch/x86/kvm/svm.c | 12 +++++++++--- |
| 1 file changed, 9 insertions(+), 3 deletions(-) |
| |
| diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c |
| index e544cec812f9..2a07e43ee666 100644 |
| --- a/arch/x86/kvm/svm.c |
| +++ b/arch/x86/kvm/svm.c |
| @@ -6815,7 +6815,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; |
| @@ -6823,6 +6824,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; |
| @@ -6873,8 +6879,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; |
| -- |
| 2.20.1 |
| |