| From 103c763c72dd2df3e8c91f2d7ec88f98ed391111 Mon Sep 17 00:00:00 2001 |
| From: Eric Biggers <ebiggers@google.com> |
| Date: Wed, 31 Jan 2018 17:30:21 -0800 |
| Subject: KVM/x86: remove WARN_ON() for when vm_munmap() fails |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Eric Biggers <ebiggers@google.com> |
| |
| commit 103c763c72dd2df3e8c91f2d7ec88f98ed391111 upstream. |
| |
| On x86, special KVM memslots such as the TSS region have anonymous |
| memory mappings created on behalf of userspace, and these mappings are |
| removed when the VM is destroyed. |
| |
| It is however possible for removing these mappings via vm_munmap() to |
| fail. This can most easily happen if the thread receives SIGKILL while |
| it's waiting to acquire ->mmap_sem. This triggers the 'WARN_ON(r < 0)' |
| in __x86_set_memory_region(). syzkaller was able to hit this, using |
| 'exit()' to send the SIGKILL. Note that while the vm_munmap() failure |
| results in the mapping not being removed immediately, it is not leaked |
| forever but rather will be freed when the process exits. |
| |
| It's not really possible to handle this failure properly, so almost |
| every other caller of vm_munmap() doesn't check the return value. It's |
| a limitation of having the kernel manage these mappings rather than |
| userspace. |
| |
| So just remove the WARN_ON() so that users can't spam the kernel log |
| with this warning. |
| |
| Fixes: f0d648bdf0a5 ("KVM: x86: map/unmap private slots in __x86_set_memory_region") |
| Reported-by: syzbot <syzkaller@googlegroups.com> |
| Signed-off-by: Eric Biggers <ebiggers@google.com> |
| Signed-off-by: Radim Krčmář <rkrcmar@redhat.com> |
| Signed-off-by: Jack Wang <jinpu.wang@profitbricks.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/x86/kvm/x86.c | 6 ++---- |
| 1 file changed, 2 insertions(+), 4 deletions(-) |
| |
| --- a/arch/x86/kvm/x86.c |
| +++ b/arch/x86/kvm/x86.c |
| @@ -8251,10 +8251,8 @@ int __x86_set_memory_region(struct kvm * |
| return r; |
| } |
| |
| - if (!size) { |
| - r = vm_munmap(old.userspace_addr, old.npages * PAGE_SIZE); |
| - WARN_ON(r < 0); |
| - } |
| + if (!size) |
| + vm_munmap(old.userspace_addr, old.npages * PAGE_SIZE); |
| |
| return 0; |
| } |