mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Florent Revest <florent.revest@arm.com>
To: linux-arm-kernel@lists.infradead.org
Cc: matt@codeblueprint.co.uk, ard.biesheuvel@linaro.org,
	pbonzini@redhat.com, rkrcmar@redhat.com,
	christoffer.dall@linaro.org, catalin.marinas@arm.com,
	will.deacon@arm.com, mark.rutland@arm.com, marc.zyngier@arm.com,
	linux-efi@vger.kernel.org, linux-kernel@vger.kernel.org,
	kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu,
	leif.lindholm@arm.com, revestflo@gmail.com,
	Florent Revest <florent.revest@arm.com>
Subject: [RFC 03/11] KVM: Allow VM lifecycle management without userspace
Date: Fri, 25 Aug 2017 09:31:33 +0100	[thread overview]
Message-ID: <1503649901-5834-4-git-send-email-florent.revest@arm.com> (raw)
In-Reply-To: <1503649901-5834-1-git-send-email-florent.revest@arm.com>

The current codebase of KVM makes many assumptions regarding the origin of
the virtual machine being executed or configured. Indeed, the KVM API
implementation has been written with userspace usage in mind and lots of
userspace-specific code is used (namely preempt_notifiers, eventfd, mmu
notifiers, current->mm...)

The aim of this patch is to make the KVM API (create_vm, create_vcpu etc)
usable from a kernel context. A simple trick is used to distinguish
userspace VMs (coming from QEMU or LKVM...) from internal VMs. (coming
from other subsystems, for example for sandboxing purpose):
  - When a VM is created from an ioctl, kvm->mm is set to current->mm
  - When a VM is created from the kernel, kvm->mm must be set to NULL

This ensures that no userspace program can create internal VMs and allows
to easily check whether a given VM is attached to a process or is internal.

This patch simply encloses the userspace-specific pieces of code of
kvm_main in conditions checking if kvm->mm is present and modifies the
prototype of kvm_create_vm to enable NULL mm.

Signed-off-by: Florent Revest <florent.revest@arm.com>
---
 virt/kvm/kvm_main.c | 64 ++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 41 insertions(+), 23 deletions(-)

diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 15252d7..2e7af1a 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -154,7 +154,8 @@ int vcpu_load(struct kvm_vcpu *vcpu)
        if (mutex_lock_killable(&vcpu->mutex))
                return -EINTR;
        cpu = get_cpu();
-       preempt_notifier_register(&vcpu->preempt_notifier);
+       if (vcpu->kvm->mm)
+               preempt_notifier_register(&vcpu->preempt_notifier);
        kvm_arch_vcpu_load(vcpu, cpu);
        put_cpu();
        return 0;
@@ -165,7 +166,8 @@ void vcpu_put(struct kvm_vcpu *vcpu)
 {
        preempt_disable();
        kvm_arch_vcpu_put(vcpu);
-       preempt_notifier_unregister(&vcpu->preempt_notifier);
+       if (vcpu->kvm->mm)
+               preempt_notifier_unregister(&vcpu->preempt_notifier);
        preempt_enable();
        mutex_unlock(&vcpu->mutex);
 }
@@ -640,7 +642,7 @@ static int kvm_create_vm_debugfs(struct kvm *kvm, int fd)
        return 0;
 }

-static struct kvm *kvm_create_vm(unsigned long type)
+static struct kvm *kvm_create_vm(unsigned long type, struct mm_struct *mm)
 {
        int r, i;
        struct kvm *kvm = kvm_arch_alloc_vm();
@@ -649,9 +651,11 @@ static struct kvm *kvm_create_vm(unsigned long type)
                return ERR_PTR(-ENOMEM);

        spin_lock_init(&kvm->mmu_lock);
-       mmgrab(current->mm);
-       kvm->mm = current->mm;
-       kvm_eventfd_init(kvm);
+       kvm->mm = mm;
+       if (mm) {
+               mmgrab(current->mm);
+               kvm_eventfd_init(kvm);
+       }
        mutex_init(&kvm->lock);
        mutex_init(&kvm->irq_lock);
        mutex_init(&kvm->slots_lock);
@@ -697,15 +701,18 @@ static struct kvm *kvm_create_vm(unsigned long type)
                        goto out_err;
        }

-       r = kvm_init_mmu_notifier(kvm);
-       if (r)
-               goto out_err;
+       if (mm) {
+               r = kvm_init_mmu_notifier(kvm);
+               if (r)
+                       goto out_err;
+       }

        spin_lock(&kvm_lock);
        list_add(&kvm->vm_list, &vm_list);
        spin_unlock(&kvm_lock);

-       preempt_notifier_inc();
+       if (mm)
+               preempt_notifier_inc();

        return kvm;

@@ -721,7 +728,8 @@ static struct kvm *kvm_create_vm(unsigned long type)
        for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++)
                kvm_free_memslots(kvm, __kvm_memslots(kvm, i));
        kvm_arch_free_vm(kvm);
-       mmdrop(current->mm);
+       if (mm)
+               mmdrop(mm);
        return ERR_PTR(r);
 }

@@ -772,9 +780,11 @@ static void kvm_destroy_vm(struct kvm *kvm)
        cleanup_srcu_struct(&kvm->irq_srcu);
        cleanup_srcu_struct(&kvm->srcu);
        kvm_arch_free_vm(kvm);
-       preempt_notifier_dec();
+       if (mm)
+               preempt_notifier_dec();
        hardware_disable_all();
-       mmdrop(mm);
+       if (mm)
+               mmdrop(mm);
 }

 void kvm_get_kvm(struct kvm *kvm)
@@ -1269,6 +1279,9 @@ unsigned long kvm_host_page_size(struct kvm *kvm, gfn_t gfn)
        if (kvm_is_error_hva(addr))
                return PAGE_SIZE;

+       if (!kvm->mm)
+               return PAGE_SIZE;
+
        down_read(&current->mm->mmap_sem);
        vma = find_vma(current->mm, addr);
        if (!vma)
@@ -2486,9 +2499,11 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id)
        if (r)
                goto vcpu_destroy;

-       r = kvm_create_vcpu_debugfs(vcpu);
-       if (r)
-               goto vcpu_destroy;
+       if (kvm->mm) {
+               r = kvm_create_vcpu_debugfs(vcpu);
+               if (r)
+                       goto vcpu_destroy;
+       }

        mutex_lock(&kvm->lock);
        if (kvm_get_vcpu_by_id(kvm, id)) {
@@ -2499,11 +2514,13 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id)
        BUG_ON(kvm->vcpus[atomic_read(&kvm->online_vcpus)]);

        /* Now it's all set up, let userspace reach it */
-       kvm_get_kvm(kvm);
-       r = create_vcpu_fd(vcpu);
-       if (r < 0) {
-               kvm_put_kvm(kvm);
-               goto unlock_vcpu_destroy;
+       if (kvm->mm) {
+               kvm_get_kvm(kvm);
+               r = create_vcpu_fd(vcpu);
+               if (r < 0) {
+                       kvm_put_kvm(kvm);
+                       goto unlock_vcpu_destroy;
+               }
        }

        kvm->vcpus[atomic_read(&kvm->online_vcpus)] = vcpu;
@@ -2521,7 +2538,8 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id)

 unlock_vcpu_destroy:
        mutex_unlock(&kvm->lock);
-       debugfs_remove_recursive(vcpu->debugfs_dentry);
+       if (kvm->mm)
+               debugfs_remove_recursive(vcpu->debugfs_dentry);
 vcpu_destroy:
        kvm_arch_vcpu_destroy(vcpu);
 vcpu_decrement:
@@ -3191,7 +3209,7 @@ static int kvm_dev_ioctl_create_vm(unsigned long type)
        struct kvm *kvm;
        struct file *file;

-       kvm = kvm_create_vm(type);
+       kvm = kvm_create_vm(type, current->mm);
        if (IS_ERR(kvm))
                return PTR_ERR(kvm);
 #ifdef CONFIG_KVM_MMIO
--
1.9.1

IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.

  parent reply	other threads:[~2017-08-25  8:37 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-25  8:31 [RFC 00/11] KVM, EFI, arm64: EFI Runtime Services Sandboxing Florent Revest
2017-08-25  8:31 ` [RFC 01/11] arm64: Add an SMCCC function IDs header Florent Revest
2017-08-25  8:31 ` [RFC 02/11] KVM: arm64: Return an Unknown ID on unhandled HVC Florent Revest
2017-08-25  8:31 ` Florent Revest [this message]
2017-08-25  8:31 ` [RFC 04/11] KVM, arm, arm64: Offer PAs to IPAs idmapping to internal VMs Florent Revest
2017-08-31  9:23   ` Christoffer Dall
2017-09-26 21:14     ` Florent Revest
2017-10-16 20:45       ` Christoffer Dall
2017-08-25  8:31 ` [RFC 05/11] KVM: Expose VM/VCPU creation functions Florent Revest
2017-08-25  8:31 ` [RFC 06/11] KVM, arm64: Expose a VCPU initialization function Florent Revest
2017-08-25  8:31 ` [RFC 07/11] KVM: Allow initialization before the module target Florent Revest
2017-08-25  8:31 ` [RFC 08/11] KVM, arm, arm64: Initialize KVM's core earlier Florent Revest
2017-08-25  8:31 ` [RFC 09/11] EFI, arm, arm64: Enable EFI Runtime Services later Florent Revest
2017-08-25  8:31 ` [RFC 10/11] efi, arm64: Sandbox Runtime Services in a VM Florent Revest
2017-08-25  8:31 ` [RFC 11/11] KVM, arm64: Don't trap internal VMs SMC calls Florent Revest
2017-08-25  9:40 ` [RFC 00/11] KVM, EFI, arm64: EFI Runtime Services Sandboxing Florent Revest
2017-08-31  9:26 ` Christoffer Dall
2017-09-26 21:14   ` Florent Revest
2017-10-16 20:47     ` Christoffer Dall
2017-09-22 21:44 ` Ard Biesheuvel
2017-09-26 21:14   ` Florent Revest

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=1503649901-5834-4-git-send-email-florent.revest@arm.com \
    --to=florent.revest@arm.com \
    --cc=ard.biesheuvel@linaro.org \
    --cc=catalin.marinas@arm.com \
    --cc=christoffer.dall@linaro.org \
    --cc=kvm@vger.kernel.org \
    --cc=kvmarm@lists.cs.columbia.edu \
    --cc=leif.lindholm@arm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-efi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=marc.zyngier@arm.com \
    --cc=mark.rutland@arm.com \
    --cc=matt@codeblueprint.co.uk \
    --cc=pbonzini@redhat.com \
    --cc=revestflo@gmail.com \
    --cc=rkrcmar@redhat.com \
    --cc=will.deacon@arm.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®