[PATCH v2 0/3] vhost_task: Fix a bug where KVM wakes an exited task

STALE359d

24 messages, 4 authors, 2025-09-21 · open the first message on its own page

[PATCH v2 0/3] vhost_task: Fix a bug where KVM wakes an exited task

From: Sean Christopherson <seanjc@google.com>
Date: 2025-08-27 19:41:13

Michael,

Do you want to take this through the vhost tree?  It technically fixes a KVM
bug, but this obviously touches far more vhost code than KVM code, and the
patch that needs to go into 6.17 doesn't touch KVM at all.


Fix a bug where KVM attempts to wake a vhost task that has already exited in
response to a fatal signal, and tack on a few cleanups to harden against
introducing similar bugs in the future.

The issue is firmly a KVM problem, but I opted to fix the bug by making
vhost_task_wake() safe against an exited task as doing so is far simpler and
cleaner than implementing the same functionality in KVM, and I suspect that
if there are other users of vhost_tasks in the future, then there's a good
chance they will want/expect vhost_task to handle that detail.

Note, this only started causing problems when commit 56180dd20c19 ("futex:
Use RCU-based per-CPU reference counting instead of rcuref_t") landed, so
the explosions are "new" in 6.17, but the bug has existed since KVM switched
to vhost_task back in 6.13.

v2:
 - Drop the "safe" postfix variant and make the "default" vhost_task_wake()
   safe. [Michael].
 - Use vhost_task_wake() and __vhost_task_wake() for the public APIs, and
   vhost_task_wake_up_process() for the local helper. [Michael]
 - Drag the signalas back from their Spanish holiday. [Sebastian]

v1: https://lore.kernel.org/all/20250826004012.3835150-1-seanjc@google.com

Sean Christopherson (3):
  vhost_task: Don't wake KVM x86's recovery thread if vhost task was
    killed
  vhost_task: Allow caller to omit handle_sigkill() callback
  KVM: x86/mmu: Don't register a sigkill callback for NX hugepage
    recovery tasks

 arch/x86/kvm/mmu/mmu.c           |  7 +---
 drivers/vhost/vhost.c            |  2 +-
 include/linux/sched/vhost_task.h |  1 +
 kernel/vhost_task.c              | 62 +++++++++++++++++++++++++++-----
 4 files changed, 56 insertions(+), 16 deletions(-)


base-commit: 1b237f190eb3d36f52dffe07a40b5eb210280e00
-- 
2.51.0.268.g9569e192d0-goog

[PATCH v2 1/3] vhost_task: Don't wake KVM x86's recovery thread if vhost task was killed

From: Sean Christopherson <seanjc@google.com>
Date: 2025-08-27 19:41:16

Make the "default" API for waking a vhost task safe against the underlying
task exiting due to a fatal signal.  This fixes a bug in KVM x86 where KVM
attempts to wake an NX hugepage recovery task that exiting before being
explicitly stopped, resulting in a use-after-free and thus crashes, hangs,
and other badness.

  Oops: general protection fault, probably for non-canonical address 0xff0e899fa1566052: 0000 [#1] SMP
  CPU: 51 UID: 0 PID: 53807 Comm: tee Tainted: G S         O        6.17.0-smp--38183c31756a-next #826 NONE
  Tainted: [S]=CPU_OUT_OF_SPEC, [O]=OOT_MODULE
  Hardware name: Google LLC Indus/Indus_QC_03, BIOS 30.110.0 09/13/2024
  RIP: 0010:queued_spin_lock_slowpath+0x123/0x250
  Code: ... <48> 89 8c 02 c0 da 47 a2 83 79 08 00 75 08 f3 90 83 79 08 00 74 f8
  RSP: 0018:ffffbf55cffe7cf8 EFLAGS: 00010006
  RAX: ff0e899fff0e8562 RBX: 0000000000d00000 RCX: ffffa39b40aefac0
  RDX: 0000000000000030 RSI: fffffffffffffff8 RDI: ffffa39d0592e68c
  RBP: 0000000000d00000 R08: 00000000ffffff80 R09: 0000000400000000
  R10: ffffa36cce4fe401 R11: 0000000000000800 R12: 0000000000000003
  R13: 0000000000000000 R14: ffffa39d0592e68c R15: ffffa39b9e672000
  FS:  00007f233b2e9740(0000) GS:ffffa39b9e672000(0000) knlGS:0000000000000000
  CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
  CR2: 00007f233b39fda0 CR3: 00000004d031f002 CR4: 00000000007726f0
  PKRU: 55555554
  Call Trace:
   <TASK>
   _raw_spin_lock_irqsave+0x50/0x60
   try_to_wake_up+0x4f/0x5d0
   set_nx_huge_pages+0xe4/0x1c0 [kvm]
   param_attr_store+0x89/0xf0
   module_attr_store+0x1e/0x30
   kernfs_fop_write_iter+0xe4/0x160
   vfs_write+0x2cb/0x420
   ksys_write+0x7f/0xf0
   do_syscall_64+0x6f/0x1f0
   entry_SYSCALL_64_after_hwframe+0x4b/0x53
  RIP: 0033:0x7f233b4178b3
  R13: 0000000000000002 R14: 00000000226ff3d0 R15: 0000000000000002
   </TASK>

Handle VHOST_TASK_FLAGS_KILLED in vhost_task_wake() instead of forcing KVM
to solve the problem, as KVM would literally just add an equivalent flag,
along with a new lock to protect said flag.  In general, forcing simple
usage of vhost task to care about signals _and_ take non-trivial action to
do the right thing isn't developer friendly, and is likely to lead to
similar bugs in the future.

Keep the existing behavior for vhost (by calling __vhost_task_wake()
instead of vhost_task_wake()), as vhost_worker_killed() takes extra care
to stop and flush all workers, i.e. doesn't need the extra protection, and
because  vhost_vq_work_queue() calls

  vhost_worker_queue()
  |
  -> worker->ops->wakeup(worker)
     |
     -> vhost_task_wakeup()
        |
        -> vhost_task_wake()

while holding RCU and so can't sleep, i.e. can't take exit_mutex.

        rcu_read_lock();
        worker = rcu_dereference(vq->worker);
        if (worker) {
                queued = true;
                vhost_worker_queue(worker, work);
        }
        rcu_read_unlock();

Debugged-by: Sebastian Andrzej Siewior [off-list ref]
Link: https://lore.kernel.org/all/aKkLEtoDXKxAAWju@google.com
Link: https://lore.kernel.org/all/aJ_vEP2EHj6l0xRT@google.com
Suggested-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Fixes: d96c77bd4eeb ("KVM: x86: switch hugepage recovery thread to vhost_task")
Cc: stable@vger.kernel.org
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 drivers/vhost/vhost.c            |  2 +-
 include/linux/sched/vhost_task.h |  1 +
 kernel/vhost_task.c              | 52 +++++++++++++++++++++++++++-----
 3 files changed, 46 insertions(+), 9 deletions(-)
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 8570fdf2e14a..dafce01a9c0d 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -744,7 +744,7 @@ static void vhost_workers_free(struct vhost_dev *dev)
 
 static void vhost_task_wakeup(struct vhost_worker *worker)
 {
-	return vhost_task_wake(worker->vtsk);
+	return __vhost_task_wake(worker->vtsk);
 }
 
 static void vhost_kthread_wakeup(struct vhost_worker *worker)
diff --git a/include/linux/sched/vhost_task.h b/include/linux/sched/vhost_task.h
index 25446c5d3508..1a9c2ac65c9a 100644
--- a/include/linux/sched/vhost_task.h
+++ b/include/linux/sched/vhost_task.h
@@ -10,5 +10,6 @@ struct vhost_task *vhost_task_create(bool (*fn)(void *),
 void vhost_task_start(struct vhost_task *vtsk);
 void vhost_task_stop(struct vhost_task *vtsk);
 void vhost_task_wake(struct vhost_task *vtsk);
+void __vhost_task_wake(struct vhost_task *vtsk);
 
 #endif /* _LINUX_SCHED_VHOST_TASK_H */
diff --git a/kernel/vhost_task.c b/kernel/vhost_task.c
index bc738fa90c1d..bd213d0b6da3 100644
--- a/kernel/vhost_task.c
+++ b/kernel/vhost_task.c
@@ -67,16 +67,52 @@ static int vhost_task_fn(void *data)
 	do_exit(0);
 }
 
-/**
- * vhost_task_wake - wakeup the vhost_task
- * @vtsk: vhost_task to wake
- *
- * wake up the vhost_task worker thread
- */
-void vhost_task_wake(struct vhost_task *vtsk)
+static void vhost_task_wake_up_process(struct vhost_task *vtsk)
 {
 	wake_up_process(vtsk->task);
 }
+
+/**
+ * __vhost_task_wake - wakeup the vhost_task
+ * @vtsk: vhost_task to wake
+ *
+ * Wake up the vhost_task worker thread.  The caller is responsible for ensuring
+ * that the task hasn't exited.
+ */
+void __vhost_task_wake(struct vhost_task *vtsk)
+{
+	/*
+	 * Checking VHOST_TASK_FLAGS_KILLED can race with signal delivery, but
+	 * a race can only result in false negatives and this is just a sanity
+	 * check, i.e. if KILLED is set, the caller is buggy no matter what.
+	 */
+	if (WARN_ON_ONCE(test_bit(VHOST_TASK_FLAGS_KILLED, &vtsk->flags)))
+		return;
+
+	vhost_task_wake_up_process(vtsk);
+}
+EXPORT_SYMBOL_GPL(__vhost_task_wake);
+
+/**
+ * vhost_task_wake - wakeup the vhost_task if it hasn't been killed
+ * @vtsk: vhost_task to wake
+ *
+ * Wake up the vhost_task worker thread if the task hasn't exited, e.g. due to
+ * a signal.
+ */
+void vhost_task_wake(struct vhost_task *vtsk)
+{
+	guard(mutex)(&vtsk->exit_mutex);
+
+	/* Attempting to wake a task that has been explicitly stopped is a bug. */
+	if (WARN_ON_ONCE(test_bit(VHOST_TASK_FLAGS_STOP, &vtsk->flags)))
+		return;
+
+	if (test_bit(VHOST_TASK_FLAGS_KILLED, &vtsk->flags))
+		return;
+
+	vhost_task_wake_up_process(vtsk);
+}
 EXPORT_SYMBOL_GPL(vhost_task_wake);
 
 /**
@@ -91,7 +127,7 @@ void vhost_task_stop(struct vhost_task *vtsk)
 	mutex_lock(&vtsk->exit_mutex);
 	if (!test_bit(VHOST_TASK_FLAGS_KILLED, &vtsk->flags)) {
 		set_bit(VHOST_TASK_FLAGS_STOP, &vtsk->flags);
-		vhost_task_wake(vtsk);
+		vhost_task_wake_up_process(vtsk);
 	}
 	mutex_unlock(&vtsk->exit_mutex);
 
-- 
2.51.0.268.g9569e192d0-goog

[PATCH v2 2/3] vhost_task: Allow caller to omit handle_sigkill() callback

From: Sean Christopherson <seanjc@google.com>
Date: 2025-08-27 19:41:18

Now that vhost_task provides an API to safely wake a task without relying
on the caller to react to signals, make handle_sigkill() optional and
WARN if the "unsafe" __vhost_task_wake() is used without hooking sigkill.
Requiring the user to react to sigkill adds no meaningful value, e.g. it
didn't help KVM do the right thing with respect to signals, and adding a
sanity check in __vhost_task_wake() gives developers a hint as to what
needs to be done in response to sigkill.

Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 kernel/vhost_task.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/kernel/vhost_task.c b/kernel/vhost_task.c
index bd213d0b6da3..01bf7b0e2c5b 100644
--- a/kernel/vhost_task.c
+++ b/kernel/vhost_task.c
@@ -59,7 +59,8 @@ static int vhost_task_fn(void *data)
 	 */
 	if (!test_bit(VHOST_TASK_FLAGS_STOP, &vtsk->flags)) {
 		set_bit(VHOST_TASK_FLAGS_KILLED, &vtsk->flags);
-		vtsk->handle_sigkill(vtsk->data);
+		if (vtsk->handle_sigkill)
+			vtsk->handle_sigkill(vtsk->data);
 	}
 	mutex_unlock(&vtsk->exit_mutex);
 	complete(&vtsk->exited);
@@ -81,6 +82,13 @@ static void vhost_task_wake_up_process(struct vhost_task *vtsk)
  */
 void __vhost_task_wake(struct vhost_task *vtsk)
 {
+	/*
+	 * Waking the task without taking exit_mutex is safe if and only if the
+	 * implementation hooks sigkill, as that's the only way the caller can
+	 * know if the task has exited prematurely due to a signal.
+	 */
+	WARN_ON_ONCE(!vtsk->handle_sigkill);
+
 	/*
 	 * Checking VHOST_TASK_FLAGS_KILLED can race with signal delivery, but
 	 * a race can only result in false negatives and this is just a sanity
-- 
2.51.0.268.g9569e192d0-goog

[PATCH v2 3/3] KVM: x86/mmu: Don't register a sigkill callback for NX hugepage recovery tasks

From: Sean Christopherson <seanjc@google.com>
Date: 2025-08-27 19:41:20

Don't register a sigkill callback with vhost_task when creating NX hugepage
recovery threads now that said callback is optional.  In addition to
removing what is effectively dead code, not registering a sigkill "handler"
also guards against improper use of __vhost_task_wake().

Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/kvm/mmu/mmu.c | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
index 6e838cb6c9e1..ace302137533 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -7677,10 +7677,6 @@ static void kvm_recover_nx_huge_pages(struct kvm *kvm)
 	srcu_read_unlock(&kvm->srcu, rcu_idx);
 }
 
-static void kvm_nx_huge_page_recovery_worker_kill(void *data)
-{
-}
-
 static bool kvm_nx_huge_page_recovery_worker(void *data)
 {
 	struct kvm *kvm = data;
@@ -7713,8 +7709,7 @@ static int kvm_mmu_start_lpage_recovery(struct once *once)
 	struct vhost_task *nx_thread;
 
 	kvm->arch.nx_huge_page_last = get_jiffies_64();
-	nx_thread = vhost_task_create(kvm_nx_huge_page_recovery_worker,
-				      kvm_nx_huge_page_recovery_worker_kill,
+	nx_thread = vhost_task_create(kvm_nx_huge_page_recovery_worker, NULL,
 				      kvm, "kvm-nx-lpage-recovery");
 
 	if (IS_ERR(nx_thread))
-- 
2.51.0.268.g9569e192d0-goog

Re: [PATCH v2 0/3] vhost_task: Fix a bug where KVM wakes an exited task

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: 2025-08-27 20:11:08

On 2025-08-27 12:41:04 [-0700], Sean Christopherson wrote:
Michael,
Sean,

would the bellow work by chance? It is a quick shot but it looks
symmetrical…
diff --git a/kernel/vhost_task.c b/kernel/vhost_task.c
index bc738fa90c1d6..27107dcc1cbfe 100644
--- a/kernel/vhost_task.c
+++ b/kernel/vhost_task.c
@@ -100,6 +100,7 @@ void vhost_task_stop(struct vhost_task *vtsk)
 	 * freeing it below.
 	 */
 	wait_for_completion(&vtsk->exited);
+	put_task_struct(vtsk->task);
 	kfree(vtsk);
 }
 EXPORT_SYMBOL_GPL(vhost_task_stop);
@@ -148,7 +149,7 @@ struct vhost_task *vhost_task_create(bool (*fn)(void *),
 		return ERR_CAST(tsk);
 	}
 
-	vtsk->task = tsk;
+	vtsk->task = get_task_struct(tsk);
 	return vtsk;
 }
 EXPORT_SYMBOL_GPL(vhost_task_create);
Sebastian

Re: [PATCH v2 0/3] vhost_task: Fix a bug where KVM wakes an exited task

From: Sean Christopherson <seanjc@google.com>
Date: 2025-08-28 00:16:37

On Wed, Aug 27, 2025, Sebastian Andrzej Siewior wrote:
On 2025-08-27 12:41:04 [-0700], Sean Christopherson wrote:
quoted
Michael,
Sean,

would the bellow work by chance? It is a quick shot but it looks
symmetrical…
Gah, sorry, I flagged your earlier mail and then forgot to circle back to it
(for whatever reason, I didn't entirely grok what you were suggesting).
quoted hunk
diff --git a/kernel/vhost_task.c b/kernel/vhost_task.c
index bc738fa90c1d6..27107dcc1cbfe 100644
--- a/kernel/vhost_task.c
+++ b/kernel/vhost_task.c
@@ -100,6 +100,7 @@ void vhost_task_stop(struct vhost_task *vtsk)
 	 * freeing it below.
 	 */
 	wait_for_completion(&vtsk->exited);
+	put_task_struct(vtsk->task);
 	kfree(vtsk);
 }
 EXPORT_SYMBOL_GPL(vhost_task_stop);
@@ -148,7 +149,7 @@ struct vhost_task *vhost_task_create(bool (*fn)(void *),
 		return ERR_CAST(tsk);
 	}
 
-	vtsk->task = tsk;
+	vtsk->task = get_task_struct(tsk);
 	return vtsk;
 }
 EXPORT_SYMBOL_GPL(vhost_task_create);
Nice!  This fixes things too.  Either solution works for me.  Or maybe do both?
Attempting to wake a task that vhost_task knows has exited (is exiting?) is a
bit gross, but even with that hardening, guarding against UAF is very nice to
have too.

Tested-by: Sean Christopherson <seanjc@google.com>

Re: [PATCH v2 0/3] vhost_task: Fix a bug where KVM wakes an exited task

From: Lei Yang <hidden>
Date: 2025-08-28 02:43:28

Tested this series of patches's v2 again with vhost-net regression
tests, everything works fine.

Tested-by: Lei Yang <redacted>

On Thu, Aug 28, 2025 at 4:11 AM Sebastian Andrzej Siewior
[off-list ref] wrote:
quoted hunk
On 2025-08-27 12:41:04 [-0700], Sean Christopherson wrote:
quoted
Michael,
Sean,

would the bellow work by chance? It is a quick shot but it looks
symmetrical…
diff --git a/kernel/vhost_task.c b/kernel/vhost_task.c
index bc738fa90c1d6..27107dcc1cbfe 100644
--- a/kernel/vhost_task.c
+++ b/kernel/vhost_task.c
@@ -100,6 +100,7 @@ void vhost_task_stop(struct vhost_task *vtsk)
         * freeing it below.
         */
        wait_for_completion(&vtsk->exited);
+       put_task_struct(vtsk->task);
        kfree(vtsk);
 }
 EXPORT_SYMBOL_GPL(vhost_task_stop);
@@ -148,7 +149,7 @@ struct vhost_task *vhost_task_create(bool (*fn)(void *),
                return ERR_CAST(tsk);
        }

-       vtsk->task = tsk;
+       vtsk->task = get_task_struct(tsk);
        return vtsk;
 }
 EXPORT_SYMBOL_GPL(vhost_task_create);
Sebastian

Re: [PATCH v2 0/3] vhost_task: Fix a bug where KVM wakes an exited task

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: 2025-08-28 06:48:44

On 2025-08-27 17:16:35 [-0700], Sean Christopherson wrote:
Nice!  This fixes things too.  Either solution works for me.  Or maybe do both?
Attempting to wake a task that vhost_task knows has exited (is exiting?) is a
bit gross, but even with that hardening, guarding against UAF is very nice to
have too.
I don't mind either way.
If this is requested I can submit a proper patch.
Tested-by: Sean Christopherson <seanjc@google.com>
Sebastian

Re: [PATCH v2 0/3] vhost_task: Fix a bug where KVM wakes an exited task

From: Sean Christopherson <seanjc@google.com>
Date: 2025-09-15 21:03:02

On Wed, Aug 27, 2025, Sean Christopherson wrote:
Michael,

Do you want to take this through the vhost tree?  It technically fixes a KVM
bug, but this obviously touches far more vhost code than KVM code, and the
patch that needs to go into 6.17 doesn't touch KVM at all.
Can this be squeezed into 6.17?  I know it's very late in the cycle, and that the
KVM bug is pre-existing, but the increased impact of the bug is new in 6.17 and I
don't want 6.17 to release without a fix.

Re: [PATCH v2 0/3] vhost_task: Fix a bug where KVM wakes an exited task

From: "Michael S. Tsirkin" <mst@redhat.com>
Date: 2025-09-15 22:20:38

On Mon, Sep 15, 2025 at 02:03:00PM -0700, Sean Christopherson wrote:
On Wed, Aug 27, 2025, Sean Christopherson wrote:
quoted
Michael,

Do you want to take this through the vhost tree?  It technically fixes a KVM
bug, but this obviously touches far more vhost code than KVM code, and the
patch that needs to go into 6.17 doesn't touch KVM at all.
Can this be squeezed into 6.17?  I know it's very late in the cycle, and that the
KVM bug is pre-existing, but the increased impact of the bug is new in 6.17 and I
don't want 6.17 to release without a fix.
To clarify you just mean 1/3, yes?

Re: [PATCH v2 0/3] vhost_task: Fix a bug where KVM wakes an exited task

From: Sean Christopherson <seanjc@google.com>
Date: 2025-09-15 22:22:46

On Mon, Sep 15, 2025, Michael S. Tsirkin wrote:
On Mon, Sep 15, 2025 at 02:03:00PM -0700, Sean Christopherson wrote:
quoted
On Wed, Aug 27, 2025, Sean Christopherson wrote:
quoted
Michael,

Do you want to take this through the vhost tree?  It technically fixes a KVM
bug, but this obviously touches far more vhost code than KVM code, and the
patch that needs to go into 6.17 doesn't touch KVM at all.
Can this be squeezed into 6.17?  I know it's very late in the cycle, and that the
KVM bug is pre-existing, but the increased impact of the bug is new in 6.17 and I
don't want 6.17 to release without a fix.
To clarify you just mean 1/3, yes?
Correct, 2 and 3 aren't urgent.

Re: [PATCH v2 0/3] vhost_task: Fix a bug where KVM wakes an exited task

From: "Michael S. Tsirkin" <mst@redhat.com>
Date: 2025-09-15 22:23:48

On Wed, Aug 27, 2025 at 05:16:35PM -0700, Sean Christopherson wrote:
On Wed, Aug 27, 2025, Sebastian Andrzej Siewior wrote:
quoted
On 2025-08-27 12:41:04 [-0700], Sean Christopherson wrote:
quoted
Michael,
Sean,

would the bellow work by chance? It is a quick shot but it looks
symmetrical…
Gah, sorry, I flagged your earlier mail and then forgot to circle back to it
(for whatever reason, I didn't entirely grok what you were suggesting).
quoted
diff --git a/kernel/vhost_task.c b/kernel/vhost_task.c
index bc738fa90c1d6..27107dcc1cbfe 100644
--- a/kernel/vhost_task.c
+++ b/kernel/vhost_task.c
@@ -100,6 +100,7 @@ void vhost_task_stop(struct vhost_task *vtsk)
 	 * freeing it below.
 	 */
 	wait_for_completion(&vtsk->exited);
+	put_task_struct(vtsk->task);
 	kfree(vtsk);
 }
 EXPORT_SYMBOL_GPL(vhost_task_stop);
@@ -148,7 +149,7 @@ struct vhost_task *vhost_task_create(bool (*fn)(void *),
 		return ERR_CAST(tsk);
 	}
 
-	vtsk->task = tsk;
+	vtsk->task = get_task_struct(tsk);
 	return vtsk;
 }
 EXPORT_SYMBOL_GPL(vhost_task_create);
Nice!  This fixes things too.  Either solution works for me.  Or maybe do both?
Attempting to wake a task that vhost_task knows has exited (is exiting?) is a
bit gross, but even with that hardening, guarding against UAF is very nice to
have too.

Tested-by: Sean Christopherson <seanjc@google.com>
Sure let's do both.

-- 
MST

Re: [PATCH v2 0/3] vhost_task: Fix a bug where KVM wakes an exited task

From: "Michael S. Tsirkin" <mst@redhat.com>
Date: 2025-09-18 15:09:13

On Wed, Aug 27, 2025 at 10:10:59PM +0200, Sebastian Andrzej Siewior wrote:
quoted hunk
On 2025-08-27 12:41:04 [-0700], Sean Christopherson wrote:
quoted
Michael,
Sean,

would the bellow work by chance? It is a quick shot but it looks
symmetrical…
diff --git a/kernel/vhost_task.c b/kernel/vhost_task.c
index bc738fa90c1d6..27107dcc1cbfe 100644
--- a/kernel/vhost_task.c
+++ b/kernel/vhost_task.c
@@ -100,6 +100,7 @@ void vhost_task_stop(struct vhost_task *vtsk)
 	 * freeing it below.
 	 */
 	wait_for_completion(&vtsk->exited);
+	put_task_struct(vtsk->task);
 	kfree(vtsk);
 }
 EXPORT_SYMBOL_GPL(vhost_task_stop);
@@ -148,7 +149,7 @@ struct vhost_task *vhost_task_create(bool (*fn)(void *),
 		return ERR_CAST(tsk);
 	}
 
-	vtsk->task = tsk;
+	vtsk->task = get_task_struct(tsk);
 	return vtsk;
 }
 EXPORT_SYMBOL_GPL(vhost_task_create);
Sebastian

So how about switching to this approach then?
Instead of piling up fixes like we seem to do now ...
Sean?

-- 
MST

Re: [PATCH v2 0/3] vhost_task: Fix a bug where KVM wakes an exited task

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: 2025-09-18 15:48:29

On 2025-09-18 11:09:05 [-0400], Michael S. Tsirkin wrote:
So how about switching to this approach then?
Instead of piling up fixes like we seem to do now ...
Sean?
Since I am in To: here. You want me to resent my diff as a proper patch?

Sebastian

Re: [PATCH v2 0/3] vhost_task: Fix a bug where KVM wakes an exited task

From: Sean Christopherson <seanjc@google.com>
Date: 2025-09-18 16:04:09

On Thu, Sep 18, 2025, Sebastian Andrzej Siewior wrote:
On 2025-09-18 11:09:05 [-0400], Michael S. Tsirkin wrote:
quoted
So how about switching to this approach then?
Instead of piling up fixes like we seem to do now ...
I don't have a strong preference for 6.17, beyond landing a fix of some kind.
I think there are three options for 6.17, in order of "least like to break
something":

 1. Sebastian's get_task_struct() fix
 2. This series, without the KILLED sanity check in __vhost_task_wake()
 3. This series, with my fixup (with which syzbot was happy)

Longer term, I'd still like to land everything though.
quoted
Sean?
Since I am in To: here. You want me to resent my diff as a proper patch?
Ya, I think it makes sense to harden against UAF even if we fix the KVM bug more
directly.

Re: [PATCH v2 0/3] vhost_task: Fix a bug where KVM wakes an exited task

From: "Michael S. Tsirkin" <mst@redhat.com>
Date: 2025-09-18 16:06:40

On Thu, Sep 18, 2025 at 05:48:26PM +0200, Sebastian Andrzej Siewior wrote:
On 2025-09-18 11:09:05 [-0400], Michael S. Tsirkin wrote:
quoted
So how about switching to this approach then?
Instead of piling up fixes like we seem to do now ...
Sean?
Since I am in To: here. You want me to resent my diff as a proper patch?

Sebastian
Yes please, if Sean can ack it.

-- 
MST

Re: [PATCH v2 0/3] vhost_task: Fix a bug where KVM wakes an exited task

From: "Michael S. Tsirkin" <mst@redhat.com>
Date: 2025-09-18 16:08:16

On Thu, Sep 18, 2025 at 09:04:07AM -0700, Sean Christopherson wrote:
On Thu, Sep 18, 2025, Sebastian Andrzej Siewior wrote:
quoted
On 2025-09-18 11:09:05 [-0400], Michael S. Tsirkin wrote:
quoted
So how about switching to this approach then?
Instead of piling up fixes like we seem to do now ...
I don't have a strong preference for 6.17, beyond landing a fix of some kind.
I think there are three options for 6.17, in order of "least like to break
something":

 1. Sebastian's get_task_struct() fix

I am just a bit apprehensive that we don't create a situation
where we leak the task struct somehow, given the limited
testing time. Can you help me get convinced that risk is 0?
 2. This series, without the KILLED sanity check in __vhost_task_wake()
 3. This series, with my fixup (with which syzbot was happy)

Longer term, I'd still like to land everything though.
No problem with that.
quoted
quoted
Sean?
Since I am in To: here. You want me to resent my diff as a proper patch?
Ya, I think it makes sense to harden against UAF even if we fix the KVM bug more
directly.

Re: [PATCH v2 0/3] vhost_task: Fix a bug where KVM wakes an exited task

From: Sean Christopherson <seanjc@google.com>
Date: 2025-09-18 16:52:21

On Thu, Sep 18, 2025, Michael S. Tsirkin wrote:
On Thu, Sep 18, 2025 at 09:04:07AM -0700, Sean Christopherson wrote:
quoted
On Thu, Sep 18, 2025, Sebastian Andrzej Siewior wrote:
quoted
On 2025-09-18 11:09:05 [-0400], Michael S. Tsirkin wrote:
quoted
So how about switching to this approach then?
Instead of piling up fixes like we seem to do now ...
I don't have a strong preference for 6.17, beyond landing a fix of some kind.
I think there are three options for 6.17, in order of "least like to break
something":

 1. Sebastian's get_task_struct() fix

I am just a bit apprehensive that we don't create a situation
where we leak the task struct somehow, given the limited
testing time. Can you help me get convinced that risk is 0?
I doubt it, I share same similar concerns about lack of testing.  So I guess
thinking about this again, #2 is probably safer since it'd only impact KVM?
quoted
 2. This series, without the KILLED sanity check in __vhost_task_wake()
 3. This series, with my fixup (with which syzbot was happy)

Re: [PATCH v2 0/3] vhost_task: Fix a bug where KVM wakes an exited task

From: "Michael S. Tsirkin" <mst@redhat.com>
Date: 2025-09-18 17:40:32

On Thu, Sep 18, 2025 at 09:52:19AM -0700, Sean Christopherson wrote:
On Thu, Sep 18, 2025, Michael S. Tsirkin wrote:
quoted
On Thu, Sep 18, 2025 at 09:04:07AM -0700, Sean Christopherson wrote:
quoted
On Thu, Sep 18, 2025, Sebastian Andrzej Siewior wrote:
quoted
On 2025-09-18 11:09:05 [-0400], Michael S. Tsirkin wrote:
quoted
So how about switching to this approach then?
Instead of piling up fixes like we seem to do now ...
I don't have a strong preference for 6.17, beyond landing a fix of some kind.
I think there are three options for 6.17, in order of "least like to break
something":

 1. Sebastian's get_task_struct() fix

I am just a bit apprehensive that we don't create a situation
where we leak the task struct somehow, given the limited
testing time. Can you help me get convinced that risk is 0?
I doubt it, I share same similar concerns about lack of testing.  So I guess
thinking about this again, #2 is probably safer since it'd only impact KVM?
I can't say I understand completely how we get that state though?
Why did the warning trigger if it's not a UAF?
quoted
quoted
 2. This series, without the KILLED sanity check in __vhost_task_wake()
 3. This series, with my fixup (with which syzbot was happy)

Re: [PATCH v2 0/3] vhost_task: Fix a bug where KVM wakes an exited task

From: Sean Christopherson <seanjc@google.com>
Date: 2025-09-18 17:58:10

On Thu, Sep 18, 2025, Michael S. Tsirkin wrote:
On Thu, Sep 18, 2025 at 09:52:19AM -0700, Sean Christopherson wrote:
quoted
On Thu, Sep 18, 2025, Michael S. Tsirkin wrote:
quoted
On Thu, Sep 18, 2025 at 09:04:07AM -0700, Sean Christopherson wrote:
quoted
On Thu, Sep 18, 2025, Sebastian Andrzej Siewior wrote:
quoted
On 2025-09-18 11:09:05 [-0400], Michael S. Tsirkin wrote:
quoted
So how about switching to this approach then?
Instead of piling up fixes like we seem to do now ...
I don't have a strong preference for 6.17, beyond landing a fix of some kind.
I think there are three options for 6.17, in order of "least like to break
something":

 1. Sebastian's get_task_struct() fix

I am just a bit apprehensive that we don't create a situation
where we leak the task struct somehow, given the limited
testing time. Can you help me get convinced that risk is 0?
I doubt it, I share same similar concerns about lack of testing.  So I guess
thinking about this again, #2 is probably safer since it'd only impact KVM?
I can't say I understand completely how we get that state though?
Why did the warning trigger if it's not a UAF?
It's purely a flaw in the sanity check itself due to the ordering in vhost_task_fn().

As is, vhost_task_fn() marks the task KILLED before invoking ->handle_sigkill(),
i.e. before vhost_worker_killed() is guaranteed to complete, and thus before
worker->killed is set.  As a result, vhost can keep waking workers that have
KILLED set, but haven't actually exited.  That's perfectly fine as UAF won't
occur until do_exit() is called, and that won't happen until ->handle_sigkill()
completes.
quoted
quoted
quoted
 2. This series, without the KILLED sanity check in __vhost_task_wake()
 3. This series, with my fixup (with which syzbot was happy)

[PATCH] vhost: Take a reference on the task that is reference in struct vhost_task.

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: 2025-09-18 18:11:48

vhost_task_create() creates a task and keeps a reference to its
task_struct. That task may exit early via a signal and its task_struct
will be released.
A pending vhost_task_wake() will then attempt to wake the task and
access a task_struct which is no longer there.

Acquire a reference on the task_struct while creating the thread and
release the reference while the struct vhost_task itself is removed.
If the task exits early due to a signal, then the vhost_task_wake() will
still access a valid task_struct. The wake is safe and will be skipped
in this case.

Fixes: f9010dbdce911 ("fork, vhost: Use CLONE_THREAD to fix freezer/ps regression")
Reported-by: Sean Christopherson <seanjc@google.com>
Closes: https://lore.kernel.org/all/aKkLEtoDXKxAAWju@google.com/
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 kernel/vhost_task.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kernel/vhost_task.c b/kernel/vhost_task.c
index bc738fa90c1d6..27107dcc1cbfe 100644
--- a/kernel/vhost_task.c
+++ b/kernel/vhost_task.c
@@ -100,6 +100,7 @@ void vhost_task_stop(struct vhost_task *vtsk)
 	 * freeing it below.
 	 */
 	wait_for_completion(&vtsk->exited);
+	put_task_struct(vtsk->task);
 	kfree(vtsk);
 }
 EXPORT_SYMBOL_GPL(vhost_task_stop);
@@ -148,7 +149,7 @@ struct vhost_task *vhost_task_create(bool (*fn)(void *),
 		return ERR_CAST(tsk);
 	}
 
-	vtsk->task = tsk;
+	vtsk->task = get_task_struct(tsk);
 	return vtsk;
 }
 EXPORT_SYMBOL_GPL(vhost_task_create);
-- 
2.51.0

Re: [PATCH] vhost: Take a reference on the task that is reference in struct vhost_task.

From: Sean Christopherson <seanjc@google.com>
Date: 2025-09-19 21:15:47

On Thu, Sep 18, 2025, Sebastian Andrzej Siewior wrote:
vhost_task_create() creates a task and keeps a reference to its
task_struct. That task may exit early via a signal and its task_struct
will be released.
A pending vhost_task_wake() will then attempt to wake the task and
access a task_struct which is no longer there.

Acquire a reference on the task_struct while creating the thread and
release the reference while the struct vhost_task itself is removed.
If the task exits early due to a signal, then the vhost_task_wake() will
still access a valid task_struct. The wake is safe and will be skipped
in this case.

Fixes: f9010dbdce911 ("fork, vhost: Use CLONE_THREAD to fix freezer/ps regression")
Reported-by: Sean Christopherson <seanjc@google.com>
Closes: https://lore.kernel.org/all/aKkLEtoDXKxAAWju@google.com/
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
Tested-by: Sean Christopherson <seanjc@google.com>

Re: [PATCH] vhost: Take a reference on the task that is reference in struct vhost_task.

From: "Michael S. Tsirkin" <mst@redhat.com>
Date: 2025-09-21 20:56:30

Subject: that is reference -> that is referenced

On Thu, Sep 18, 2025 at 08:11:44PM +0200, Sebastian Andrzej Siewior wrote:
quoted hunk
vhost_task_create() creates a task and keeps a reference to its
task_struct. That task may exit early via a signal and its task_struct
will be released.
A pending vhost_task_wake() will then attempt to wake the task and
access a task_struct which is no longer there.

Acquire a reference on the task_struct while creating the thread and
release the reference while the struct vhost_task itself is removed.
If the task exits early due to a signal, then the vhost_task_wake() will
still access a valid task_struct. The wake is safe and will be skipped
in this case.

Fixes: f9010dbdce911 ("fork, vhost: Use CLONE_THREAD to fix freezer/ps regression")
Reported-by: Sean Christopherson <seanjc@google.com>
Closes: https://lore.kernel.org/all/aKkLEtoDXKxAAWju@google.com/
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 kernel/vhost_task.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kernel/vhost_task.c b/kernel/vhost_task.c
index bc738fa90c1d6..27107dcc1cbfe 100644
--- a/kernel/vhost_task.c
+++ b/kernel/vhost_task.c
@@ -100,6 +100,7 @@ void vhost_task_stop(struct vhost_task *vtsk)
 	 * freeing it below.
 	 */
 	wait_for_completion(&vtsk->exited);
+	put_task_struct(vtsk->task);
 	kfree(vtsk);
 }
 EXPORT_SYMBOL_GPL(vhost_task_stop);
@@ -148,7 +149,7 @@ struct vhost_task *vhost_task_create(bool (*fn)(void *),
 		return ERR_CAST(tsk);
 	}
 
-	vtsk->task = tsk;
+	vtsk->task = get_task_struct(tsk);
 	return vtsk;
 }
 EXPORT_SYMBOL_GPL(vhost_task_create);
-- 
2.51.0

Re: [PATCH] vhost: Take a reference on the task that is reference in struct vhost_task.

From: "Michael S. Tsirkin" <mst@redhat.com>
Date: 2025-09-21 21:40:15

On Sun, Sep 21, 2025 at 04:56:20PM -0400, Michael S. Tsirkin wrote:
Subject: that is reference -> that is referenced
to note i fixed it for now. just dropped "that is referenced"
completely. shorter.
On Thu, Sep 18, 2025 at 08:11:44PM +0200, Sebastian Andrzej Siewior wrote:
quoted
vhost_task_create() creates a task and keeps a reference to its
task_struct. That task may exit early via a signal and its task_struct
will be released.
A pending vhost_task_wake() will then attempt to wake the task and
access a task_struct which is no longer there.

Acquire a reference on the task_struct while creating the thread and
release the reference while the struct vhost_task itself is removed.
If the task exits early due to a signal, then the vhost_task_wake() will
still access a valid task_struct. The wake is safe and will be skipped
in this case.

Fixes: f9010dbdce911 ("fork, vhost: Use CLONE_THREAD to fix freezer/ps regression")
Reported-by: Sean Christopherson <seanjc@google.com>
Closes: https://lore.kernel.org/all/aKkLEtoDXKxAAWju@google.com/
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 kernel/vhost_task.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kernel/vhost_task.c b/kernel/vhost_task.c
index bc738fa90c1d6..27107dcc1cbfe 100644
--- a/kernel/vhost_task.c
+++ b/kernel/vhost_task.c
@@ -100,6 +100,7 @@ void vhost_task_stop(struct vhost_task *vtsk)
 	 * freeing it below.
 	 */
 	wait_for_completion(&vtsk->exited);
+	put_task_struct(vtsk->task);
 	kfree(vtsk);
 }
 EXPORT_SYMBOL_GPL(vhost_task_stop);
@@ -148,7 +149,7 @@ struct vhost_task *vhost_task_create(bool (*fn)(void *),
 		return ERR_CAST(tsk);
 	}
 
-	vtsk->task = tsk;
+	vtsk->task = get_task_struct(tsk);
 	return vtsk;
 }
 EXPORT_SYMBOL_GPL(vhost_task_create);
-- 
2.51.0

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help