Skip to content

Commit 100d6b1

Browse files
isilenceaxboe
authored andcommitted
io_uring: fix multishot recv request leaks
Having REQ_F_POLLED set doesn't guarantee that the request is executed as a multishot from the polling path. Fortunately for us, if the code thinks it's multishot issue when it's not, it can only ask to skip completion so leaking the request. Use issue_flags to mark multipoll issues. Cc: stable@vger.kernel.org Fixes: 1300ebb ("io_uring: multishot recv") Signed-off-by: Pavel Begunkov <asml.silence@gmail.com> Link: https://lore.kernel.org/r/37762040ba9c52b81b92a2f5ebfd4ee484088951.1668710222.git.asml.silence@gmail.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 9148286 commit 100d6b1

File tree

1 file changed

+7
-9
lines changed

1 file changed

+7
-9
lines changed

io_uring/net.c

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,6 @@ struct io_sr_msg {
6767
struct io_kiocb *notif;
6868
};
6969

70-
#define IO_APOLL_MULTI_POLLED (REQ_F_APOLL_MULTISHOT | REQ_F_POLLED)
71-
7270
int io_shutdown_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
7371
{
7472
struct io_shutdown *shutdown = io_kiocb_to_cmd(req, struct io_shutdown);
@@ -591,7 +589,8 @@ static inline void io_recv_prep_retry(struct io_kiocb *req)
591589
* again (for multishot).
592590
*/
593591
static inline bool io_recv_finish(struct io_kiocb *req, int *ret,
594-
unsigned int cflags, bool mshot_finished)
592+
unsigned int cflags, bool mshot_finished,
593+
unsigned issue_flags)
595594
{
596595
if (!(req->flags & REQ_F_APOLL_MULTISHOT)) {
597596
io_req_set_res(req, *ret, cflags);
@@ -614,7 +613,7 @@ static inline bool io_recv_finish(struct io_kiocb *req, int *ret,
614613

615614
io_req_set_res(req, *ret, cflags);
616615

617-
if (req->flags & REQ_F_POLLED)
616+
if (issue_flags & IO_URING_F_MULTISHOT)
618617
*ret = IOU_STOP_MULTISHOT;
619618
else
620619
*ret = IOU_OK;
@@ -773,8 +772,7 @@ int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
773772
if (ret < min_ret) {
774773
if (ret == -EAGAIN && force_nonblock) {
775774
ret = io_setup_async_msg(req, kmsg, issue_flags);
776-
if (ret == -EAGAIN && (req->flags & IO_APOLL_MULTI_POLLED) ==
777-
IO_APOLL_MULTI_POLLED) {
775+
if (ret == -EAGAIN && (issue_flags & IO_URING_F_MULTISHOT)) {
778776
io_kbuf_recycle(req, issue_flags);
779777
return IOU_ISSUE_SKIP_COMPLETE;
780778
}
@@ -803,7 +801,7 @@ int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
803801
if (kmsg->msg.msg_inq)
804802
cflags |= IORING_CQE_F_SOCK_NONEMPTY;
805803

806-
if (!io_recv_finish(req, &ret, cflags, mshot_finished))
804+
if (!io_recv_finish(req, &ret, cflags, mshot_finished, issue_flags))
807805
goto retry_multishot;
808806

809807
if (mshot_finished) {
@@ -869,7 +867,7 @@ int io_recv(struct io_kiocb *req, unsigned int issue_flags)
869867
ret = sock_recvmsg(sock, &msg, flags);
870868
if (ret < min_ret) {
871869
if (ret == -EAGAIN && force_nonblock) {
872-
if ((req->flags & IO_APOLL_MULTI_POLLED) == IO_APOLL_MULTI_POLLED) {
870+
if (issue_flags & IO_URING_F_MULTISHOT) {
873871
io_kbuf_recycle(req, issue_flags);
874872
return IOU_ISSUE_SKIP_COMPLETE;
875873
}
@@ -902,7 +900,7 @@ int io_recv(struct io_kiocb *req, unsigned int issue_flags)
902900
if (msg.msg_inq)
903901
cflags |= IORING_CQE_F_SOCK_NONEMPTY;
904902

905-
if (!io_recv_finish(req, &ret, cflags, ret <= 0))
903+
if (!io_recv_finish(req, &ret, cflags, ret <= 0, issue_flags))
906904
goto retry_multishot;
907905

908906
return ret;

0 commit comments

Comments
 (0)