From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wr1-f53.google.com (mail-wr1-f53.google.com [209.85.221.53]) (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 B7D6A3ADB99 for ; Thu, 16 Jul 2026 16:08:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.53 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784218106; cv=none; b=izbsq9uh3R1YJc69Gnq+h5HM0dYFs1FgovdHEzSgDptbCaRHXbJ6xAg4qZurebloaMtQtG55rBKopFaSdXxIyHSQeQPpcW9OsH5UTML+AqDH31Ap/Sma0zPsrbXNv23bc26rtRnLcOwGUZYlp3fs8ELWSrQaTv9S6DSOWPepFF8= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784218106; c=relaxed/simple; bh=XXD5JiD6MbZACed2L2oAqZip9Q+NlM5VYmK7EyLsEnA=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=LIDOK0xmZ6gWL1uHa9XyqFqiPUD2Hz+2Y5JGwxH41GngXKPyMDKRA8medXO/wdYpisVVh3vYMonQ6lH0oF3VkPOIGpwZV85lFHLaVJ5bJDwDO21FHgz2oVg29YBOlHaIG6tMruIg6tfppQ9tPbarcdyLdNZo7f9KT8/8YpWptQI= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=Hf0MdhKq; arc=none smtp.client-ip=209.85.221.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="Hf0MdhKq" Received: by mail-wr1-f53.google.com with SMTP id ffacd0b85a97d-47d70879764so4822508f8f.2 for ; Thu, 16 Jul 2026 09:08:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1784218103; x=1784822903; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=P33ACgM5WRF/Wf41Mm64IYg79T9oy5SYkqINyFAwCd0=; b=Hf0MdhKqRcUjzFV9CsuUQAhPnmoc8sL+xKctst+Ohwk1wIW/eZvVAENs5nCLFtFclL pxRQuHz5nSpBsJueHDd9Nulg9m5/O/z8tWvIC5PiVBmgqLydsIfmlewJuAjkoGFtpT12 laWxdnqu3ggaVRytTjyJTZk2sAYWbUwLvRKL0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784218103; x=1784822903; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=P33ACgM5WRF/Wf41Mm64IYg79T9oy5SYkqINyFAwCd0=; b=nexRrfJ1MuA7FZ7B4vsTefqw/Z8lJMm1GJFKFp7B8aOUIgRqzcv9ECkIXsbGihduHo 4SktXuv3DGcS/zd63gsgEiAlqLANpE2y5fHw93Xz3vwhmgsWbqqfd2891VfAP5kQ7lbR Ms+owOxhZ4fauMghkOtay6V8JBn/FaEvivy7l/TJUGIa2cicAXr/f3DHdZQ2sgTSWrpi EVSxGACHAckOX6JFmkXXYIZGtf6PldKto+8z7gEwTvmCj2NQnp9ozr9QEyy2/gC1eS4F saxukzJ+9xtaI72RH45NO16GNnpJZhv53Rq3EIjctEbzREe8Kc2wGyE4ev0u5a93ob/f Y2uQ== X-Forwarded-Encrypted: i=1; AHgh+Rr7J1J76BF6KZAIoH4FQBDv6OJp4B2k594Kqd+nzPob9tzqyZXYd9LMQStcFjYvaI5VEh8INycdjID9/qI=@vger.kernel.org X-Gm-Message-State: AOJu0YwL8EvLGMRP3wusKpZnyK6evYDJS+FvYtblHIHWtLtcETlNiQQ0 xZo/Ot2xokGoGwVm8q/FwcJ1Bhu9gaewnHI7LR2FX51cxLm3wlLInp6ZnBpqBZuOnEurRsRlK/t RgzU= X-Gm-Gg: AfdE7cn6lwiRGEiGvhxP/CcQTKZ423IG0ZzSBzDa5yxsiEEQv1ciLc3wHS4h20F9mpM kF5sIW/7P05rwXJY+cfXJVbzf2K2iX3m5KoKhZR/NQY82V4pZMs83VFuaQPxHDWhB5+XaOmXEDa OSfBYDculoSib59MKwQ206E0Gof7HlRi2VaE27bA54FeNny5OLp4Xc3ipv7rQfgIf6JaMZeJHwv BlQ4MLOD0wZR68CAVeO6bzTL1NDqtSk9VngSga1hzywpF3lPV+CWSQU8H5/DQvZMEo/WAfpppre l9S0L2YtBg3o2abaLDTyENGp40arJnBLvOwDeSHGdPPEK+ogCm3GBPF7mdAGzEglu8uiBaH/ogv fHwOjt28cn+O8Rsjhb23D4Nw48vGf8OpWHfsHUDMPj4KZA17s/a/GVqIpout6cvJIBopIfgj1El NfaZEDqPGnYEggXbh2ab4i/hHd4zIKdK+9WJRsq7hqT6Al4AQYOwlexzIGgdmpryQ= X-Received: by 2002:a05:600c:3144:b0:493:f6c1:2f09 with SMTP id 5b1f17b1804b1-4953c145152mr93839855e9.6.1784218102908; Thu, 16 Jul 2026 09:08:22 -0700 (PDT) Received: from dmaluka.c.googlers.com.com (206.39.187.35.bc.googleusercontent.com. [35.187.39.206]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-49541e93295sm65511545e9.10.2026.07.16.09.08.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 Jul 2026 09:08:22 -0700 (PDT) From: Dmytro Maluka To: Sean Christopherson Cc: Paolo Bonzini , Dave Hansen , Zeng Guang , Chao Gao , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Vineeth Pillai , Chuanxiao Dong , Aashish Sharma , Grzegorz Jaszczyk , Dmytro Maluka Subject: [PATCH] KVM: VMX: Postpone IPIv setup after successful vCPU creation Date: Thu, 16 Jul 2026 16:08:01 +0000 Message-ID: <20260716160801.3155582-1-dmaluka@chromium.org> X-Mailer: git-send-email 2.55.0.141.g00534a21ce-goog Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit vCPU creation in kvm_vm_ioctl_create_vcpu() may fail after kvm_arch_vcpu_create() -> vmx_vcpu_create() already succeeded. In such case kvm_vm_ioctl_create_vcpu() destroys the newly created vCPU in the failure path. However, that leaves a side effect: the IPIv pid_table entry remains configured with this vCPU's pi_desc address. As a result, when another vCPU sends an IPI to the APIC ID of this failed-to-create vCPU, it will cause HW to write to this (freed!) pi_desc memory. [*] An easy fix would be to clear the pid_table entry in vmx_vcpu_free(). However that would be still problematic, for the following reason: userspace may try to create a vCPU with the same vcpu_id as an existing one; vmx_vcpu_create() will succeed, and only after that kvm_vm_ioctl_create_vcpu() will check for the duplicate vcpu_id and fail with -EEXIST and then free the vCPU in the failure path. So in this failure path, vmx_vcpu_free() would clear the pid_table entry for that already existing good vCPU, i.e. effectively disable IPIv for that vCPU. So instead fix the issue by moving the pid_table entry setup from .vcpu_create() to the newly introduced .vcpu_postcreate() callback called at the end of kvm_vm_ioctl_create_vcpu(), when we are sure that the vCPU creation succeeded. [*] Although, since this memory is freed into the kvm_vcpu_cache kmem cache which is only used for allocating kvm_vcpus, _maybe_ this memory will only be reused for pi_desc of another vCPU, not for anything else. So _maybe_ this will only result in delivering the IPI to a wrong vCPU (possibly of another VM) in the worst case, not in a random corruption of kernel memory. Fixes: d588bb9be1da ("KVM: VMX: enable IPI virtualization") Signed-off-by: Dmytro Maluka --- arch/x86/include/asm/kvm-x86-ops.h | 1 + arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/vmx/main.c | 9 +++++++++ arch/x86/kvm/vmx/vmx.c | 11 +++++++---- arch/x86/kvm/vmx/x86_ops.h | 1 + arch/x86/kvm/x86.c | 1 + 6 files changed, 20 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/kvm-x86-ops.h b/arch/x86/include/asm/kvm-x86-ops.h index 83dc5086138b..aecbe9c54004 100644 --- a/arch/x86/include/asm/kvm-x86-ops.h +++ b/arch/x86/include/asm/kvm-x86-ops.h @@ -25,6 +25,7 @@ KVM_X86_OP_OPTIONAL(vm_destroy) KVM_X86_OP_OPTIONAL(vm_pre_destroy) KVM_X86_OP_OPTIONAL_RET0(vcpu_precreate) KVM_X86_OP(vcpu_create) +KVM_X86_OP_OPTIONAL(vcpu_postcreate) KVM_X86_OP(vcpu_free) KVM_X86_OP(vcpu_reset) KVM_X86_OP(prepare_switch_to_guest) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 5f6c1ce9673b..3ed9d8fc3b96 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1803,6 +1803,7 @@ struct kvm_x86_ops { /* Create, but do not attach this VCPU */ int (*vcpu_precreate)(struct kvm *kvm); int (*vcpu_create)(struct kvm_vcpu *vcpu); + void (*vcpu_postcreate)(struct kvm_vcpu *vcpu); void (*vcpu_free)(struct kvm_vcpu *vcpu); void (*vcpu_reset)(struct kvm_vcpu *vcpu, bool init_event); diff --git a/arch/x86/kvm/vmx/main.c b/arch/x86/kvm/vmx/main.c index 83d9921277ea..bdf5ba3155f6 100644 --- a/arch/x86/kvm/vmx/main.c +++ b/arch/x86/kvm/vmx/main.c @@ -78,6 +78,14 @@ static int vt_vcpu_create(struct kvm_vcpu *vcpu) return vmx_vcpu_create(vcpu); } +static void vt_vcpu_postcreate(struct kvm_vcpu *vcpu) +{ + if (is_td_vcpu(vcpu)) + return; + + vmx_vcpu_postcreate(vcpu); +} + static void vt_vcpu_free(struct kvm_vcpu *vcpu) { if (is_td_vcpu(vcpu)) { @@ -898,6 +906,7 @@ struct kvm_x86_ops vt_x86_ops __initdata = { .vcpu_precreate = vt_op(vcpu_precreate), .vcpu_create = vt_op(vcpu_create), + .vcpu_postcreate = vt_op(vcpu_postcreate), .vcpu_free = vt_op(vcpu_free), .vcpu_reset = vt_op(vcpu_reset), diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index cc75feec05da..ae6cef9c13e0 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -7752,10 +7752,6 @@ int vmx_vcpu_create(struct kvm_vcpu *vcpu) vmx->ve_info = page_to_virt(page); } - if (vmx_can_use_ipiv(vcpu)) - WRITE_ONCE(to_kvm_vmx(vcpu->kvm)->pid_table[vcpu->vcpu_id], - __pa(&vmx->vt.pi_desc) | PID_TABLE_ENTRY_VALID); - return 0; free_vmcs: @@ -7767,6 +7763,13 @@ int vmx_vcpu_create(struct kvm_vcpu *vcpu) return err; } +void vmx_vcpu_postcreate(struct kvm_vcpu *vcpu) +{ + if (vmx_can_use_ipiv(vcpu)) + WRITE_ONCE(to_kvm_vmx(vcpu->kvm)->pid_table[vcpu->vcpu_id], + __pa(&to_vmx(vcpu)->vt.pi_desc) | PID_TABLE_ENTRY_VALID); +} + #define L1TF_MSG_SMT "L1TF CPU bug present and SMT on, data leak possible. See CVE-2018-3646 and https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/l1tf.html for details.\n" #define L1TF_MSG_L1D "L1TF CPU bug present and virtualization mitigation disabled, data leak possible. See CVE-2018-3646 and https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/l1tf.html for details.\n" diff --git a/arch/x86/kvm/vmx/x86_ops.h b/arch/x86/kvm/vmx/x86_ops.h index 409858074246..defc2c3a37c8 100644 --- a/arch/x86/kvm/vmx/x86_ops.h +++ b/arch/x86/kvm/vmx/x86_ops.h @@ -21,6 +21,7 @@ int vmx_vm_init(struct kvm *kvm); void vmx_vm_destroy(struct kvm *kvm); int vmx_vcpu_precreate(struct kvm *kvm); int vmx_vcpu_create(struct kvm_vcpu *vcpu); +void vmx_vcpu_postcreate(struct kvm_vcpu *vcpu); int vmx_vcpu_pre_run(struct kvm_vcpu *vcpu); fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags); void vmx_vcpu_free(struct kvm_vcpu *vcpu); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index afcac1042947..c9f512a30fec 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -12873,6 +12873,7 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu) return; vcpu_load(vcpu); kvm_synchronize_tsc(vcpu, NULL); + kvm_x86_call(vcpu_postcreate)(vcpu); vcpu_put(vcpu); /* poll control enabled by default */ -- 2.55.0.141.g00534a21ce-goog