* [PATCH] mshv_vtl: reject poll files with multiple waitqueues
@ 2026-10-16 6:11 Daehyeon Ko
2026-10-19 5:10 ` Naman Jain
0 siblings, 1 reply; 4+ messages in thread
From: Daehyeon Ko @ 2026-10-16 6:11 UTC (permalink / raw)
To: Haiyang Zhang, Wei Liu, Dexuan Cui
Cc: Naman Jain, Saurabh Sengar, Michael Kelley, Roman Kisel,
linux-hyperv, linux-kernel
MSHV_SET_POLL_FILE invokes a file descriptor poll callback with a poll
table backed by a single embedded wait entry. A poll callback may,
however, register the table with more than one waitqueue. pipe_poll()
does this naturally for an O_RDWR FIFO.
The second registration currently warns but then inserts the same list
node into another list. The new insertion overwrites the entry links while
the first waitqueue still points at it, corrupting the first waitqueue and
causing an invalid callback traversal when that queue wakes.
Reject a second distinct waitqueue, remove the first registration, and
return -EINVAL from the ioctl. Repeated registration of the same waitqueue
is treated as a no-op. A rejected replacement leaves the CPU slot
unregistered, consistent with the existing remove-before-register ordering.
Single-waitqueue users such as the OpenHCL io_uring poll file keep their
existing behavior.
Fixes: 7bfe3b8ea6e3 ("Drivers: hv: Introduce mshv_vtl driver")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Daehyeon Ko <4ncienth@gmail.com>
---
drivers/hv/mshv_vtl_main.c | 24 ++++++++++++++++++++++--
1 file changed, 22 insertions(+), 2 deletions(-)
diff --git a/drivers/hv/mshv_vtl_main.c b/drivers/hv/mshv_vtl_main.c
index 6e3c11c681717..158409b67a046 100644
--- a/drivers/hv/mshv_vtl_main.c
+++ b/drivers/hv/mshv_vtl_main.c
@@ -72,6 +72,7 @@ struct mshv_vtl_poll_file {
wait_queue_entry_t wait;
wait_queue_head_t *wqh;
poll_table pt;
+ int error;
int cpu;
};
@@ -458,7 +459,19 @@ static void mshv_vtl_ptable_queue_proc(struct file *file, wait_queue_head_t *wqh
{
struct mshv_vtl_poll_file *poll_file = container_of(pt, struct mshv_vtl_poll_file, pt);
- WARN_ON(poll_file->wqh);
+ if (poll_file->error)
+ return;
+
+ if (poll_file->wqh) {
+ if (poll_file->wqh == wqh)
+ return;
+
+ remove_wait_queue(poll_file->wqh, &poll_file->wait);
+ poll_file->wqh = NULL;
+ poll_file->error = -EINVAL;
+ return;
+ }
+
poll_file->wqh = wqh;
add_wait_queue(wqh, &poll_file->wait);
}
@@ -468,6 +481,7 @@ static int mshv_vtl_ioctl_set_poll_file(struct mshv_vtl_set_poll_file __user *us
struct file *file, *old_file;
struct mshv_vtl_poll_file *poll_file;
struct mshv_vtl_set_poll_file input;
+ int ret;
if (copy_from_user(&input, user_input, sizeof(input)))
return -EFAULT;
@@ -496,6 +510,7 @@ static int mshv_vtl_ioctl_set_poll_file(struct mshv_vtl_set_poll_file __user *us
old_file = poll_file->file;
poll_file->file = file;
+ poll_file->error = 0;
poll_file->cpu = input.cpu;
if (file) {
@@ -503,13 +518,18 @@ static int mshv_vtl_ioctl_set_poll_file(struct mshv_vtl_set_poll_file __user *us
init_poll_funcptr(&poll_file->pt, mshv_vtl_ptable_queue_proc);
vfs_poll(file, &poll_file->pt);
}
+ ret = poll_file->error;
+ if (ret)
+ poll_file->file = NULL;
mutex_unlock(&mshv_vtl_poll_file_lock);
if (old_file)
fput(old_file);
+ if (ret)
+ fput(file);
- return 0;
+ return ret;
}
/* Static table mapping register names to their corresponding actions */
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] mshv_vtl: reject poll files with multiple waitqueues
2026-10-16 6:11 [PATCH] mshv_vtl: reject poll files with multiple waitqueues Daehyeon Ko
@ 2026-10-19 5:10 ` Naman Jain
2026-10-19 7:04 ` [PATCH v2] " Daehyeon Ko
0 siblings, 1 reply; 4+ messages in thread
From: Naman Jain @ 2026-10-19 5:10 UTC (permalink / raw)
To: Daehyeon Ko, Haiyang Zhang, Wei Liu, Dexuan Cui
Cc: Saurabh Sengar, Michael Kelley, Roman Kisel, linux-hyperv, linux-kernel
On 10/16/2026 11:41 AM, Daehyeon Ko wrote:
> MSHV_SET_POLL_FILE invokes a file descriptor poll callback with a poll
> table backed by a single embedded wait entry. A poll callback may,
> however, register the table with more than one waitqueue. pipe_poll()
> does this naturally for an O_RDWR FIFO.
>
> The second registration currently warns but then inserts the same list
> node into another list. The new insertion overwrites the entry links while
> the first waitqueue still points at it, corrupting the first waitqueue and
> causing an invalid callback traversal when that queue wakes.
>
> Reject a second distinct waitqueue, remove the first registration, and
> return -EINVAL from the ioctl. Repeated registration of the same waitqueue
> is treated as a no-op. A rejected replacement leaves the CPU slot
> unregistered, consistent with the existing remove-before-register ordering.
> Single-waitqueue users such as the OpenHCL io_uring poll file keep their
> existing behavior.
>
> Fixes: 7bfe3b8ea6e3 ("Drivers: hv: Introduce mshv_vtl driver")
> Cc: stable@vger.kernel.org
> Assisted-by: LLM
This tag is no longer valid on latest linux-next tip and gives
checkpatch error.
Code changes LGTM.
> Signed-off-by: Daehyeon Ko <4ncienth@gmail.com>
> ---
> drivers/hv/mshv_vtl_main.c | 24 ++++++++++++++++++++++--
> 1 file changed, 22 insertions(+), 2 deletions(-)
>
Regards,
Naman
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH v2] mshv_vtl: reject poll files with multiple waitqueues
2026-10-19 5:10 ` Naman Jain
@ 2026-10-19 7:04 ` Daehyeon Ko
2026-10-19 7:34 ` Daehyeon Ko
0 siblings, 1 reply; 4+ messages in thread
From: Daehyeon Ko @ 2026-10-19 7:04 UTC (permalink / raw)
To: Haiyang Zhang, Wei Liu, Dexuan Cui
Cc: Naman Jain, Saurabh Sengar, Michael Kelley, linux-hyperv, linux-kernel
MSHV_SET_POLL_FILE invokes a file descriptor poll callback with a poll
table backed by a single embedded wait entry. A poll callback may,
however, register the table with more than one waitqueue. pipe_poll()
does this naturally for an O_RDWR FIFO.
The second registration currently warns but then inserts the same list
node into another list. The new insertion overwrites the entry links while
the first waitqueue still points at it, corrupting the first waitqueue and
causing an invalid callback traversal when that queue wakes.
Reject a second distinct waitqueue, remove the first registration, and
return -EINVAL from the ioctl. Repeated registration of the same waitqueue
is treated as a no-op. A rejected replacement leaves the CPU slot
unregistered, consistent with the existing remove-before-register ordering.
Single-waitqueue users such as the OpenHCL io_uring poll file keep their
existing behavior.
An LLM-assisted source audit was used to find the issue and develop and
test this fix.
Fixes: 7bfe3b8ea6e3 ("Drivers: hv: Introduce mshv_vtl driver")
Cc: stable@vger.kernel.org
Signed-off-by: Daehyeon Ko <4ncienth@gmail.com>
---
Changes in v2:
- Replace the no-longer-supported Assisted-by trailer with changelog prose.
- No code changes.
- Link to v1: https://lore.kernel.org/r/20261016061114.1686153-1-4ncienth@gmail.com
drivers/hv/mshv_vtl_main.c | 24 ++++++++++++++++++++++--
1 file changed, 22 insertions(+), 2 deletions(-)
diff --git a/drivers/hv/mshv_vtl_main.c b/drivers/hv/mshv_vtl_main.c
index 6e3c11c681717..158409b67a046 100644
--- a/drivers/hv/mshv_vtl_main.c
+++ b/drivers/hv/mshv_vtl_main.c
@@ -72,6 +72,7 @@ struct mshv_vtl_poll_file {
wait_queue_entry_t wait;
wait_queue_head_t *wqh;
poll_table pt;
+ int error;
int cpu;
};
@@ -458,7 +459,19 @@ static void mshv_vtl_ptable_queue_proc(struct file *file, wait_queue_head_t *wqh
{
struct mshv_vtl_poll_file *poll_file = container_of(pt, struct mshv_vtl_poll_file, pt);
- WARN_ON(poll_file->wqh);
+ if (poll_file->error)
+ return;
+
+ if (poll_file->wqh) {
+ if (poll_file->wqh == wqh)
+ return;
+
+ remove_wait_queue(poll_file->wqh, &poll_file->wait);
+ poll_file->wqh = NULL;
+ poll_file->error = -EINVAL;
+ return;
+ }
+
poll_file->wqh = wqh;
add_wait_queue(wqh, &poll_file->wait);
}
@@ -468,6 +481,7 @@ static int mshv_vtl_ioctl_set_poll_file(struct mshv_vtl_set_poll_file __user *us
struct file *file, *old_file;
struct mshv_vtl_poll_file *poll_file;
struct mshv_vtl_set_poll_file input;
+ int ret;
if (copy_from_user(&input, user_input, sizeof(input)))
return -EFAULT;
@@ -496,6 +510,7 @@ static int mshv_vtl_ioctl_set_poll_file(struct mshv_vtl_set_poll_file __user *us
old_file = poll_file->file;
poll_file->file = file;
+ poll_file->error = 0;
poll_file->cpu = input.cpu;
if (file) {
@@ -503,13 +518,18 @@ static int mshv_vtl_ioctl_set_poll_file(struct mshv_vtl_set_poll_file __user *us
init_poll_funcptr(&poll_file->pt, mshv_vtl_ptable_queue_proc);
vfs_poll(file, &poll_file->pt);
}
+ ret = poll_file->error;
+ if (ret)
+ poll_file->file = NULL;
mutex_unlock(&mshv_vtl_poll_file_lock);
if (old_file)
fput(old_file);
+ if (ret)
+ fput(file);
- return 0;
+ return ret;
}
/* Static table mapping register names to their corresponding actions */
--
2.55.0
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH v2] mshv_vtl: reject poll files with multiple waitqueues
2026-10-19 7:04 ` [PATCH v2] " Daehyeon Ko
@ 2026-10-19 7:34 ` Daehyeon Ko
0 siblings, 0 replies; 4+ messages in thread
From: Daehyeon Ko @ 2026-10-19 7:34 UTC (permalink / raw)
To: Naman Jain
Cc: Haiyang Zhang, Wei Liu, Dexuan Cui, Saurabh Sengar,
Michael Kelley, linux-hyperv, linux-kernel
Hi Naman,
I sent the standalone v2 before noticing your follow-up on the POLLFREE
patch asking that the two fixes be combined.
Please disregard this standalone v2. I will rebase both fixes onto the
latest tip and send them as a two-patch series, with the common waitqueue
removal helper shared as requested.
Sorry for the confusion.
Regards,
Daehyeon
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-10-19 7:34 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-16 6:11 [PATCH] mshv_vtl: reject poll files with multiple waitqueues Daehyeon Ko
2026-10-19 5:10 ` Naman Jain
2026-10-19 7:04 ` [PATCH v2] " Daehyeon Ko
2026-10-19 7:34 ` Daehyeon Ko
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®