Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp2244022imm; Thu, 7 Jun 2018 07:36:51 -0700 (PDT) X-Google-Smtp-Source: ADUXVKI/LqqsY+8A+fSCp15nY9CIivMkB6+MBeH0eUwCvYCftjldrAlWdvAAAZHdFU70fGftCPy2 X-Received: by 2002:a63:88c3:: with SMTP id l186-v6mr1839524pgd.226.1528382211899; Thu, 07 Jun 2018 07:36:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1528382211; cv=none; d=google.com; s=arc-20160816; b=HcEuccEUWLuA4KvL+sBYSk6kb9NJnhk34KSKMAbIbm5M83TqvI/guoHO6p4pt5nGSJ HyJmtp8MwSd+KnHODX3TufLpMNEHcgcAHSHD8/sDxbW9tC66c2hOi0u799tosV3og022 QRjmbnvpXiLjn0hubv4JNgPHbu9KlrzaCpXcshZFHzglIri7ZCf9y0tPQsb3zhbOlcoy MHi3yf6+NujxjWfBofm2lmeB+9S0O/r1rlwSJyEwfsoN6+oSQs/CCF9xZu90lMELynoP nXtzZI94eQpIsmKXURBSUASpHLXr4/hUnogzVtvfDtjAUL8hKtYZBgad6dIJzGn5U0c8 bcsw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:in-reply-to:subject:message-id:date:cc:to :from:mime-version:content-transfer-encoding:content-disposition :arc-authentication-results; bh=neEjnhEDKHRn3GhsQzldatCwK/S+QF/c1nEnLHQq934=; b=TNvGTVtFWZ7qGXUAFHat8YukX/8x7bTq7VQyYMX+5IeHmi/Ip3SdJX8Jbmb1xMF2n1 ulxr172B/TSjIHFsvOhc7rXhKoBnNQTqnyqrljTA3IhAfWI00RiQuivXxXLrqitkjQ9t W0XC+FGY/vWhaqdm9lufgcClz96A8JbNIwYapVv2UobxekqL4uSvGH4a6savkyLIk/c3 VlsucPVrfxWGlFvQO46S0oxRcTfpxECw4MCDfc/7d7Tx7zdLO+HPhND9n3lLR1vYBdw5 hSiKVo9QhKd0vK1oEwiiGAVZJe5vRJMxji4OWyTGOtGAV24YfLN5PU54g0uCotLyakgc dnnQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id u13-v6si24836823pfh.282.2018.06.07.07.36.37; Thu, 07 Jun 2018 07:36:51 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934057AbeFGOff (ORCPT + 99 others); Thu, 7 Jun 2018 10:35:35 -0400 Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:40392 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934039AbeFGOf1 (ORCPT ); Thu, 7 Jun 2018 10:35:27 -0400 Received: from [148.252.241.226] (helo=deadeye) by shadbolt.decadent.org.uk with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1fQvbX-0005dI-CA; Thu, 07 Jun 2018 15:09:31 +0100 Received: from ben by deadeye with local (Exim 4.91) (envelope-from ) id 1fQvb9-000378-IR; Thu, 07 Jun 2018 15:09:07 +0100 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org CC: akpm@linux-foundation.org, "Radim =?UTF-8?Q?Kr=C4=8Dm=C3=A1=C5=99?=" , "Wanpeng Li" , "Paolo Bonzini" , "Eric Biggers" , "Dmitry Vyukov" Date: Thu, 07 Jun 2018 15:05:21 +0100 Message-ID: X-Mailer: LinuxStableQueue (scripts by bwh) Subject: [PATCH 3.16 279/410] KVM: mmu: Fix overlap between public and private memslots In-Reply-To: X-SA-Exim-Connect-IP: 148.252.241.226 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 3.16.57-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Wanpeng Li commit b28676bb8ae4569cced423dc2a88f7cb319d5379 upstream. 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 patch fixes the bug by not adding a new memslot even if it overlaps with private memslots. Reported-by: Dmitry Vyukov Cc: Paolo Bonzini Cc: Radim Krčmář Cc: Dmitry Vyukov Cc: Eric Biggers Signed-off-by: Wanpeng Li [bwh: Backported to 3.16: adjust context] Signed-off-by: Ben Hutchings --- virt/kvm/kvm_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -837,8 +837,7 @@ int __kvm_set_memory_region(struct kvm * /* Check for overlaps */ r = -EEXIST; kvm_for_each_memslot(slot, kvm->memslots) { - if ((slot->id >= KVM_USER_MEM_SLOTS) || - (slot->id == mem->slot)) + if (slot->id == mem->slot) continue; if (!((base_gfn + npages <= slot->base_gfn) || (base_gfn >= slot->base_gfn + slot->npages)))