--- /dev/null
+From 66a3a1a04849a845ec2760dabfddaaa5b835cc85 Mon Sep 17 00:00:00 2001
+From: Jens Axboe <axboe@kernel.dk>
+Date: Mon, 1 Dec 2025 13:25:22 -0700
+Subject: io_uring/poll: correctly handle io_poll_add() return value on update
+
+From: Jens Axboe <axboe@kernel.dk>
+
+Commit 84230ad2d2afbf0c44c32967e525c0ad92e26b4e upstream.
+
+When the core of io_uring was updated to handle completions
+consistently and with fixed return codes, the POLL_REMOVE opcode
+with updates got slightly broken. If a POLL_ADD is pending and
+then POLL_REMOVE is used to update the events of that request, if that
+update causes the POLL_ADD to now trigger, then that completion is lost
+and a CQE is never posted.
+
+Additionally, ensure that if an update does cause an existing POLL_ADD
+to complete, that the completion value isn't always overwritten with
+-ECANCELED. For that case, whatever io_poll_add() set the value to
+should just be retained.
+
+Cc: stable@vger.kernel.org
+Fixes: 97b388d70b53 ("io_uring: handle completions in the core")
+Reported-by: syzbot+641eec6b7af1f62f2b99@syzkaller.appspotmail.com
+Tested-by: syzbot+641eec6b7af1f62f2b99@syzkaller.appspotmail.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ io_uring/poll.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/io_uring/poll.c
++++ b/io_uring/poll.c
+@@ -1024,12 +1024,17 @@ found:
+
+ ret2 = io_poll_add(preq, issue_flags & ~IO_URING_F_UNLOCKED);
+ /* successfully updated, don't complete poll request */
+- if (!ret2 || ret2 == -EIOCBQUEUED)
++ if (ret2 == IOU_ISSUE_SKIP_COMPLETE)
+ goto out;
++ /* request completed as part of the update, complete it */
++ else if (ret2 == IOU_OK)
++ goto complete;
+ }
+
+- req_set_fail(preq);
+ io_req_set_res(preq, -ECANCELED, 0);
++complete:
++ if (preq->cqe.res < 0)
++ req_set_fail(preq);
+ preq->io_task_work.func = io_req_task_complete;
+ io_req_task_work_add(preq);
+ out: