All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sabyrzhan Tasbolatov <snovitoll@gmail.com>
To: seanjc@google.com, vkuznets@redhat.com, wanpengli@tencent.com,
	jmattson@google.com, joro@8bytes.org, hpa@zytor.com
Cc: pbonzini@redhat.com, tglx@linutronix.de, mingo@redhat.com,
	bp@alien8.de, x86@kernel.org, kvm@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	Sabyrzhan Tasbolatov <snovitoll@gmail.com>,
	syzbot+e0de2333cbf95ea473e8@syzkaller.appspotmail.com
Subject: [PATCH] x86/kvm: restrict kvm user region memory size
Date: Thu, 14 Oct 2021 12:01:51 +0000	[thread overview]
Message-ID: <20211014120151.1437018-1-snovitoll@gmail.com> (raw)

syzbot found WARNING in memslot_rmap_alloc[1] when
struct kvm_userspace_memory_region .memory_size is bigger than
0x40000000000, which is 4GB, e.g. KMALLOC_MAX_SIZE * 100 * PAGE_SIZE.

Here is the PoC to trigger the warning:

    struct kvm_userspace_memory_region mem = {
        .slot = 0,
        .guest_phys_addr = 0,
        /* + 0x100 extra to trigger kmalloc WARNING */
        .memory_size = 0x40000000000 + 0x100,
        .userspace_addr = 0,
    };

    ioctl(kvm_fd, KVM_SET_USER_MEMORY_REGION, &mem);

I couldn't find any relevant max constant to restrict unsigned long npages.
There might be another solution with chunking big portions of pages, but
there is already KVM_MAX_HUGEPAGE_LEVEL, though warning happens in
memslot_rmap_alloc() when level = 1, base_gfn = 0, e.g.
on the very first KVM_NR_PAGE_SIZES iteration.

This is, seems, valid for early Linux versions as well. Can't tell which is
exactly can be considered for git bisect.
Here is Commit d89cc617b954af ("KVM: Push rmap into kvm_arch_memory_slot")
for example, Linux 3.7.

[1]
Call Trace:
 kvmalloc include/linux/mm.h:806 [inline]
 kvmalloc_array include/linux/mm.h:824 [inline]
 kvcalloc include/linux/mm.h:829 [inline]
 memslot_rmap_alloc+0xf6/0x310 arch/x86/kvm/x86.c:11320
 kvm_alloc_memslot_metadata arch/x86/kvm/x86.c:11388 [inline]
 kvm_arch_prepare_memory_region+0x48d/0x610 arch/x86/kvm/x86.c:11462
 kvm_set_memslot+0xfe/0x1700 arch/x86/kvm/../../../virt/kvm/kvm_main.c:1505
 ...
 kvm_set_memory_region arch/x86/kvm/../../../virt/kvm/kvm_main.c:1689
 kvm_vm_ioctl_set_memory_region arch/x86/kvm/../../../virt/kvm/kvm_main.c

Reported-by: syzbot+e0de2333cbf95ea473e8@syzkaller.appspotmail.com
Signed-off-by: Sabyrzhan Tasbolatov <snovitoll@gmail.com>
---
 arch/x86/kvm/mmu/page_track.c | 3 +++
 arch/x86/kvm/x86.c            | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/arch/x86/kvm/mmu/page_track.c b/arch/x86/kvm/mmu/page_track.c
index 21427e84a82e..e790bb341680 100644
--- a/arch/x86/kvm/mmu/page_track.c
+++ b/arch/x86/kvm/mmu/page_track.c
@@ -35,6 +35,9 @@ int kvm_page_track_create_memslot(struct kvm_memory_slot *slot,
 	int  i;
 
 	for (i = 0; i < KVM_PAGE_TRACK_MAX; i++) {
+		if (npages > KMALLOC_MAX_SIZE)
+			return -ENOMEM;
+
 		slot->arch.gfn_track[i] =
 			kvcalloc(npages, sizeof(*slot->arch.gfn_track[i]),
 				 GFP_KERNEL_ACCOUNT);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index aabd3a2ec1bc..2bad607976a9 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -11394,6 +11394,9 @@ static int memslot_rmap_alloc(struct kvm_memory_slot *slot,
 
 		WARN_ON(slot->arch.rmap[i]);
 
+		if (lpages > KMALLOC_MAX_SIZE)
+			return -ENOMEM;
+
 		slot->arch.rmap[i] = kvcalloc(lpages, sz, GFP_KERNEL_ACCOUNT);
 		if (!slot->arch.rmap[i]) {
 			memslot_rmap_free(slot);
-- 
2.25.1


             reply	other threads:[~2021-10-14 12:02 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-14 12:01 Sabyrzhan Tasbolatov [this message]
2021-10-14 12:23 ` [PATCH] x86/kvm: restrict kvm user region memory size Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211014120151.1437018-1-snovitoll@gmail.com \
    --to=snovitoll@gmail.com \
    --cc=bp@alien8.de \
    --cc=hpa@zytor.com \
    --cc=jmattson@google.com \
    --cc=joro@8bytes.org \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=seanjc@google.com \
    --cc=syzbot+e0de2333cbf95ea473e8@syzkaller.appspotmail.com \
    --cc=tglx@linutronix.de \
    --cc=vkuznets@redhat.com \
    --cc=wanpengli@tencent.com \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.