From 08ca1409c4fa37ec93de08b9963390ed68a5ae8c Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Mon, 14 Jul 2025 11:57:23 +0100 Subject: [PATCH 1/2] io_uring/zcrx: disallow user selected dmabuf offset and size zcrx shouldn't be so frivolous about cutting a dmabuf sgtable and taking a subrange into it, the dmabuf layer might be not expecting that. It shouldn't be a problem for now, but since the zcrx dmabuf support is new and there shouldn't be any real users, let's play safe and reject user provided ranges into dmabufs. Also, it shouldn't be needed as userspace should size them appropriately. Fixes: a5c98e9424573 ("io_uring/zcrx: dmabuf backed zerocopy receive") Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/be899f1afed32053eb2e2079d0da241514674aca.1752443579.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- io_uring/zcrx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/io_uring/zcrx.c b/io_uring/zcrx.c index 67c518d22e0c..e3eef4ee4454 100644 --- a/io_uring/zcrx.c +++ b/io_uring/zcrx.c @@ -76,6 +76,8 @@ static int io_import_dmabuf(struct io_zcrx_ifq *ifq, int dmabuf_fd = area_reg->dmabuf_fd; int i, ret; + if (off) + return -EINVAL; if (WARN_ON_ONCE(!ifq->dev)) return -EFAULT; if (!IS_ENABLED(CONFIG_DMA_SHARED_BUFFER)) @@ -106,7 +108,7 @@ static int io_import_dmabuf(struct io_zcrx_ifq *ifq, for_each_sgtable_dma_sg(mem->sgt, sg, i) total_size += sg_dma_len(sg); - if (total_size < off + len) { + if (total_size != len) { ret = -EINVAL; goto err; } From c7cafd5b81cc07fb402e3068d134c21e60ea688c Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Wed, 16 Jul 2025 17:20:17 +0100 Subject: [PATCH 2/2] io_uring/poll: fix POLLERR handling 8c8492ca64e7 ("io_uring/net: don't retry connect operation on EPOLLERR") is a little dirty hack that 1) wrongfully assumes that POLLERR equals to a failed request, which breaks all POLLERR users, e.g. all error queue recv interfaces. 2) deviates the connection request behaviour from connect(2), and 3) racy and solved at a wrong level. Nothing can be done with 2) now, and 3) is beyond the scope of the patch. At least solve 1) by moving the hack out of generic poll handling into io_connect(). Cc: stable@vger.kernel.org Fixes: 8c8492ca64e79 ("io_uring/net: don't retry connect operation on EPOLLERR") Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/3dc89036388d602ebd84c28e5042e457bdfc952b.1752682444.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- io_uring/net.c | 12 ++++++++---- io_uring/poll.c | 2 -- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/io_uring/net.c b/io_uring/net.c index 43a43522f406..bec8c6ed0a93 100644 --- a/io_uring/net.c +++ b/io_uring/net.c @@ -1738,9 +1738,11 @@ int io_connect(struct io_kiocb *req, unsigned int issue_flags) int ret; bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK; - if (unlikely(req->flags & REQ_F_FAIL)) { - ret = -ECONNRESET; - goto out; + if (connect->in_progress) { + struct poll_table_struct pt = { ._key = EPOLLERR }; + + if (vfs_poll(req->file, &pt) & EPOLLERR) + goto get_sock_err; } file_flags = force_nonblock ? O_NONBLOCK : 0; @@ -1765,8 +1767,10 @@ int io_connect(struct io_kiocb *req, unsigned int issue_flags) * which means the previous result is good. For both of these, * grab the sock_error() and use that for the completion. */ - if (ret == -EBADFD || ret == -EISCONN) + if (ret == -EBADFD || ret == -EISCONN) { +get_sock_err: ret = sock_error(sock_from_file(req->file)->sk); + } } if (ret == -ERESTARTSYS) ret = -EINTR; diff --git a/io_uring/poll.c b/io_uring/poll.c index 0526062e2f81..20e9b46a4adf 100644 --- a/io_uring/poll.c +++ b/io_uring/poll.c @@ -273,8 +273,6 @@ static int io_poll_check_events(struct io_kiocb *req, io_tw_token_t tw) return IOU_POLL_REISSUE; } } - if (unlikely(req->cqe.res & EPOLLERR)) - req_set_fail(req); if (req->apoll_events & EPOLLONESHOT) return IOU_POLL_DONE;