From patchwork Mon Mar 27 06:23:20 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Wanpeng Li X-Patchwork-Id: 9645377 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id E957B602BF for ; Mon, 27 Mar 2017 06:23:46 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DA26728174 for ; Mon, 27 Mar 2017 06:23:46 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CE3682818B; Mon, 27 Mar 2017 06:23:46 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5D6AD28174 for ; Mon, 27 Mar 2017 06:23:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751993AbdC0GXp (ORCPT ); Mon, 27 Mar 2017 02:23:45 -0400 Received: from mail-pg0-f68.google.com ([74.125.83.68]:36524 "EHLO mail-pg0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751465AbdC0GXo (ORCPT ); Mon, 27 Mar 2017 02:23:44 -0400 Received: by mail-pg0-f68.google.com with SMTP id 81so10106015pgh.3; Sun, 26 Mar 2017 23:23:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=20QttL+JRQmTgLpVeA06uimZhMsan5vEUxyvnOqfN3M=; b=c6QMjeQsTPMj5nP/OVZnnO0fopAc/ZAsdMXWUJAMOwY208EKnWMtgTJffg0QEUlEnl a5V0Kxh06BIldB7GNMUf42g5nske5j+bH9hhRQY5Vi8VC2uNuorgDFNZEoFKZ0guquRo SJAfL38Mwt4NTBB5k+STy8zcJpyp61lPIVwQEoZh7rBiMFPsjnenjcZgoUcK9TDxdSyV jR83/rxquyyUS3RzkVS62cx3AV4Gy80sbrU6NFz/kkXK/StplDdq5FGgybtCzSN9IZZV eLbwD2hJJ3neIL3OBTaauqu/yMNybzdQg44AgfpD9hgz1+Od892HgnPPE0hthMg/1N2y 3puQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=20QttL+JRQmTgLpVeA06uimZhMsan5vEUxyvnOqfN3M=; b=K+xFIeAw5zNFmEKr7IVi5e2J+uJEeVxgNqif+TaOaW+BwnJ9yoa9Rxgq1hOkuJYrjN X5CN5z4+zbwDzNDD/zWo9KpnWdtgss3omUB0sWKlP0Vo5wXvtSGjJ7mFglo6gNWMBoLe 0jQbk1h2ir6vGNcidopd99+eau6y6NSmP1e0+htYYhVupsu8jk6I5m+oS1x9KoIakyV8 45ArQ8vPzSvos1AUoIRRTYA9ogPjttRiFLjWsjZsLrgFOkCsGqmdHWDxXAihCC1oKbAe 6lfofx1TPSAc0QDjYHS4geHyl8Gd8fq8P2zsmK1KkqglGdCSn5LXRXW4sEpsXCl+Ieq2 NaxA== X-Gm-Message-State: AFeK/H0nJnGPBQj+ATcXMhDZCW3ZUZXbkEiuZT1drexO36Re7Rr05gKmYNAFLDMxjgqagA== X-Received: by 10.98.14.81 with SMTP id w78mr23948319pfi.9.1490595812084; Sun, 26 Mar 2017 23:23:32 -0700 (PDT) Received: from localhost ([203.205.141.123]) by smtp.gmail.com with ESMTPSA id r17sm18300798pgg.19.2017.03.26.23.23.30 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 26 Mar 2017 23:23:31 -0700 (PDT) From: Wanpeng Li X-Google-Original-From: Wanpeng Li To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: Paolo Bonzini , =?UTF-8?q?Radim=20Kr=C4=8Dm=C3=A1=C5=99?= , Wanpeng Li , Dmitry Vyukov , Alex Williamson , "# v3 . 10+" Subject: [PATCH] KVM: mmu: Fix overlap with private memslots Date: Sun, 26 Mar 2017 23:23:20 -0700 Message-Id: <1490595800-15060-1-git-send-email-wanpeng.li@hotmail.com> X-Mailer: git-send-email 2.7.4 MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Wanpeng Li Reported by syzkaller: pte_list_remove: ffff9714eb1f8078 0->BUG ------------[ cut here ]------------ kernel BUG at arch/x86/kvm/mmu.c:1157! invalid opcode: 0000 [#1] SMP RIP: 0010:pte_list_remove+0x11b/0x120 [kvm] Call Trace: drop_spte+0x83/0xb0 [kvm] mmu_page_zap_pte+0xcc/0xe0 [kvm] kvm_mmu_prepare_zap_page+0x81/0x4a0 [kvm] kvm_mmu_invalidate_zap_all_pages+0x159/0x220 [kvm] kvm_arch_flush_shadow_all+0xe/0x10 [kvm] kvm_mmu_notifier_release+0x6c/0xa0 [kvm] ? kvm_mmu_notifier_release+0x5/0xa0 [kvm] __mmu_notifier_release+0x79/0x110 ? __mmu_notifier_release+0x5/0x110 exit_mmap+0x15a/0x170 ? do_exit+0x281/0xcb0 mmput+0x66/0x160 do_exit+0x2c9/0xcb0 ? __context_tracking_exit.part.5+0x4a/0x150 do_group_exit+0x50/0xd0 SyS_exit_group+0x14/0x20 do_syscall_64+0x73/0x1f0 entry_SYSCALL64_slow_path+0x25/0x25 The reason is that when creates new memslot, there is no guarantee for new memslot not overlap with private memslots. This can be triggered by the following program: #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include long r[16]; int main() { void *p = valloc(0x4000); r[2] = open("/dev/kvm", 0); r[3] = ioctl(r[2], KVM_CREATE_VM, 0x0ul); uint64_t addr = 0xf000; ioctl(r[3], KVM_SET_IDENTITY_MAP_ADDR, &addr); r[6] = ioctl(r[3], KVM_CREATE_VCPU, 0x0ul); ioctl(r[3], KVM_SET_TSS_ADDR, 0x0ul); ioctl(r[6], KVM_RUN, 0); ioctl(r[6], KVM_RUN, 0); struct kvm_userspace_memory_region mr = { .slot = 0, .flags = KVM_MEM_LOG_DIRTY_PAGES, .guest_phys_addr = 0xf000, .memory_size = 0x4000, .userspace_addr = (uintptr_t) p }; ioctl(r[3], KVM_SET_USER_MEMORY_REGION, &mr); return 0; } This bug is caused by 'commit 5419369ed6bd ("KVM: Fix user memslot overlap check")' which removes the check to avoid to add new memslot who overlaps with private memslots. This patch fixes it by not add new memslot if it is also overlap with private memslots. Reported-by: Dmitry Vyukov Cc: Paolo Bonzini Cc: Radim Krčmář Cc: Dmitry Vyukov Cc: Alex Williamson Cc: # v3.10+ Fixes: 5419369ed (KVM: Fix user memslot overlap check) Signed-off-by: Wanpeng Li --- virt/kvm/kvm_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index a17d787..ddeb18a 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -978,8 +978,7 @@ int __kvm_set_memory_region(struct kvm *kvm, /* Check for overlaps */ r = -EEXIST; kvm_for_each_memslot(slot, __kvm_memslots(kvm, as_id)) { - if ((slot->id >= KVM_USER_MEM_SLOTS) || - (slot->id == id)) + if (slot->id == id) continue; if (!((base_gfn + npages <= slot->base_gfn) || (base_gfn >= slot->base_gfn + slot->npages)))