From nobody Wed Nov 27 16:44:30 2024 Received: from mail-yw1-f201.google.com (mail-yw1-f201.google.com [209.85.128.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6C0B11DFD84 for ; Wed, 9 Oct 2024 15:05:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728486306; cv=none; b=exJuKGExaFuyEhHRKz7rHjgr6gam1edHg00cHlOaGp970p8xvac6ZWQ81X5eufBbDdaMT2N1hASpuD86DinyS2dlk5IH2dGQwLGvlmSY+g9fRyBi0/wHIUkKkVKIfhxcJNj+TswhNjFbMHdbi5UalwqwvMqqwyA5xS9UolHRaV8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728486306; c=relaxed/simple; bh=UUOuALX/8jUEKOE5MK93z/TIwR6ptoN4Q45Bp2t7r80=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=r0p04UXrhHx5WBMUjZi6dKXJg4DPZp6BhEeJAMHt2i0CssldSn9Eu7yFeAr4alHB/eg+avs2/fB0Ukoe1Y5LMti+ATBNDLoq7nWrk23r9aDyDgf4MyjN6/QbLSBW0NbKLoxpkihSVEy8rqvfgm4k9T38Fr+1meDKLFgIOQv6rh8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--seanjc.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=TGgDgmb7; arc=none smtp.client-ip=209.85.128.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--seanjc.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="TGgDgmb7" Received: by mail-yw1-f201.google.com with SMTP id 00721157ae682-6e23ee3110fso128334157b3.1 for ; Wed, 09 Oct 2024 08:05:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1728486303; x=1729091103; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:from:to:cc:subject:date:message-id:reply-to; bh=5SrGD6ntAFoOH+8A+yPE5xRGZ7AhTh5r8ioRJwoyvss=; b=TGgDgmb7U4/+O8I6VcHU5l+lNX8QJ3BOyKQJQzXZ5+KIainT0W0kcJcZ92lXRPmAv6 ew33grIfQl7wTGIgJ8z7RXF4FrMWmW1qF2XX+/Bps4RPAyM3C3T63ynEI+jauCeWCLPH MDudM0l6sf1Wtr1fOBVbhJfnebNaUkdqWD6V8+jj1CYu5OYzSz5PmM1ODOQjn3aq6BwV Pb/oMvBRaYPLLpkHoPg27+CI9sQYdgbcgTNdw4HIHZwPtWpl3SzCvYe3Z9W5ka1RhJZz vbikjorCUyAz5tmYN1TGSNdu6F3OQF5sEN48aA3cEki27gLCB5sfis+jC/JOWl4VUQ6f bPMQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728486303; x=1729091103; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=5SrGD6ntAFoOH+8A+yPE5xRGZ7AhTh5r8ioRJwoyvss=; b=CdOt1tvo3zcL5sMRu8rDDP/dB+tdo8fXD4mDjVUEBGM+wIomYnBB+pNX3TZtHtDsDk NeA+r5OQYnF4VKVW/k2KqRmbJqTO+WzX14x8AzP1ACqSuNa7JteZnl8X0Pi5QYFqEPxb EPZbZZD01yg8m/oV53QcA1oWxo0vjQqUZKK0wUisaoxHhJ228FxrhExOEtc5wWrukb11 ylsURH87f6rU9tgAxmRgerH2/QzliNA5MR2OfbnhZiVYFIQ5oroFDU61eR7Ga0nUoHdu AqRDbHL4LaPHsHoYIIkyoDrE0lSeE+Ya6ESaplPCtMF7YGaqc4M6Nky5UsXAjtuYIle2 iGmg== X-Forwarded-Encrypted: i=1; AJvYcCXJJGzRcGJ0b1APElthL2/M31y81n3dl2eXZlMvd3FGVVA3F35rTMXKPJGbSKXeVdV7dB1Z9y6sfmME18E=@vger.kernel.org X-Gm-Message-State: AOJu0Yz/Uc1DLtCa47qXN9yHUx8WjAZJT6IjUsZSrsrhr9DE1iMOQa4J GwxvXMwnbvZFhuf3PQUB+2t1iFiEHtKFkxEkwYF2nTFM/w7RVvNBdu0tXA1CFVyNYGw0EVQYjo8 swA== X-Google-Smtp-Source: AGHT+IFedXDgPxwolm1IOTnRjA9oTcL70vgsBXdT7cV8n0QPoljgzOxfYmHoJ/QpWjSoaCiWMtRKhm2aykA= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:9d:3983:ac13:c240]) (user=seanjc job=sendgmr) by 2002:a05:690c:3382:b0:6e2:4b3:ee22 with SMTP id 00721157ae682-6e32216166cmr582417b3.6.1728486303499; Wed, 09 Oct 2024 08:05:03 -0700 (PDT) Reply-To: Sean Christopherson Date: Wed, 9 Oct 2024 08:04:52 -0700 In-Reply-To: <20241009150455.1057573-1-seanjc@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20241009150455.1057573-1-seanjc@google.com> X-Mailer: git-send-email 2.47.0.rc0.187.ge670bccf7e-goog Message-ID: <20241009150455.1057573-4-seanjc@google.com> Subject: [PATCH 3/6] KVM: Grab vcpu->mutex across installing the vCPU's fd and bumping online_vcpus From: Sean Christopherson To: Paolo Bonzini Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Will Deacon , Michal Luczaj , Sean Christopherson , Alexander Potapenko , Marc Zyngier , Oliver Upton Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" During vCPU creation, acquire vcpu->mutex prior to exposing the vCPU to userspace, and hold the mutex until online_vcpus is bumped, i.e. until the vCPU is fully online from KVM's perspective. To ensure asynchronous vCPU ioctls also wait for the vCPU to come online, explicitly check online_vcpus at the start of kvm_vcpu_ioctl(), and take the vCPU's mutex to wait if necessary (having to wait for any ioctl should be exceedingly rare, i.e. not worth optimizing). Reported-by: Will Deacon Reported-by: Michal Luczaj Link: https://lore.kernel.org/all/20240730155646.1687-1-will@kernel.org Signed-off-by: Sean Christopherson --- virt/kvm/kvm_main.c | 47 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 05cbb2548d99..fca9f74e9544 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -4287,7 +4287,14 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm,= unsigned long id) if (r) goto unlock_vcpu_destroy; =20 - /* Now it's all set up, let userspace reach it */ + /* + * Now it's all set up, let userspace reach it. Grab the vCPU's mutex + * so that userspace can't invoke vCPU ioctl()s until the vCPU is fully + * visible (per online_vcpus), e.g. so that KVM doesn't get tricked + * into a NULL-pointer dereference because KVM thinks the _current_ + * vCPU doesn't exist. + */ + mutex_lock(&vcpu->mutex); kvm_get_kvm(kvm); r =3D create_vcpu_fd(vcpu); if (r < 0) @@ -4304,6 +4311,7 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, = unsigned long id) */ smp_wmb(); atomic_inc(&kvm->online_vcpus); + mutex_unlock(&vcpu->mutex); =20 mutex_unlock(&kvm->lock); kvm_arch_vcpu_postcreate(vcpu); @@ -4311,6 +4319,7 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, = unsigned long id) return r; =20 kvm_put_xa_release: + mutex_unlock(&vcpu->mutex); kvm_put_kvm_no_destroy(kvm); xa_release(&kvm->vcpu_array, vcpu->vcpu_idx); unlock_vcpu_destroy: @@ -4437,6 +4446,33 @@ static int kvm_vcpu_pre_fault_memory(struct kvm_vcpu= *vcpu, } #endif =20 +static int kvm_wait_for_vcpu_online(struct kvm_vcpu *vcpu) +{ + struct kvm *kvm =3D vcpu->kvm; + + /* + * In practice, this happy path will always be taken, as a well-behaved + * VMM will never invoke a vCPU ioctl() before KVM_CREATE_VCPU returns. + */ + if (likely(vcpu->vcpu_idx < atomic_read(&kvm->online_vcpus))) + return 0; + + /* + * Acquire and release the vCPU's mutex to wait for vCPU creation to + * complete (kvm_vm_ioctl_create_vcpu() holds the mutex until the vCPU + * is fully online). + */ + if (mutex_lock_killable(&vcpu->mutex)) + return -EINTR; + + mutex_unlock(&vcpu->mutex); + + if (WARN_ON_ONCE(!kvm_get_vcpu(kvm, vcpu->vcpu_idx))) + return -EIO; + + return 0; +} + static long kvm_vcpu_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) { @@ -4452,6 +4488,15 @@ static long kvm_vcpu_ioctl(struct file *filp, if (unlikely(_IOC_TYPE(ioctl) !=3D KVMIO)) return -EINVAL; =20 + /* + * Wait for the vCPU to be online before handling the ioctl(), as KVM + * assumes the vCPU is reachable via vcpu_array, i.e. may dereference + * a NULL pointer if userspace invokes an ioctl() before KVM is ready. + */ + r =3D kvm_wait_for_vcpu_online(vcpu); + if (r) + return r; + /* * Some architectures have vcpu ioctls that are asynchronous to vcpu * execution; mutex_lock() would break them. --=20 2.47.0.rc0.187.ge670bccf7e-goog