io_uring: retain sockaddr_storage across send/recvmsg async punt
authorJens Axboe <axboe@kernel.dk>
Sun, 9 Feb 2020 18:29:15 +0000 (11:29 -0700)
committerJens Axboe <axboe@kernel.dk>
Sun, 9 Feb 2020 18:32:10 +0000 (11:32 -0700)
Jonas reports that he sometimes sees -97/-22 error returns from
sendmsg, if it gets punted async. This is due to not retaining the
sockaddr_storage between calls. Include that in the state we copy when
going async.

Cc: stable@vger.kernel.org # 5.3+
Reported-by: Jonas Bonn <jonas@norrbonn.se>
Tested-by: Jonas Bonn <jonas@norrbonn.se>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
fs/io_uring.c

index 971d51c..6d4e20d 100644 (file)
@@ -442,6 +442,7 @@ struct io_async_msghdr {
        struct iovec                    *iov;
        struct sockaddr __user          *uaddr;
        struct msghdr                   msg;
+       struct sockaddr_storage         addr;
 };
 
 struct io_async_rw {
@@ -3032,12 +3033,11 @@ static int io_sendmsg(struct io_kiocb *req, struct io_kiocb **nxt,
        sock = sock_from_file(req->file, &ret);
        if (sock) {
                struct io_async_ctx io;
-               struct sockaddr_storage addr;
                unsigned flags;
 
                if (req->io) {
                        kmsg = &req->io->msg;
-                       kmsg->msg.msg_name = &addr;
+                       kmsg->msg.msg_name = &req->io->msg.addr;
                        /* if iov is set, it's allocated already */
                        if (!kmsg->iov)
                                kmsg->iov = kmsg->fast_iov;
@@ -3046,7 +3046,7 @@ static int io_sendmsg(struct io_kiocb *req, struct io_kiocb **nxt,
                        struct io_sr_msg *sr = &req->sr_msg;
 
                        kmsg = &io.msg;
-                       kmsg->msg.msg_name = &addr;
+                       kmsg->msg.msg_name = &io.msg.addr;
 
                        io.msg.iov = io.msg.fast_iov;
                        ret = sendmsg_copy_msghdr(&io.msg.msg, sr->msg,
@@ -3185,12 +3185,11 @@ static int io_recvmsg(struct io_kiocb *req, struct io_kiocb **nxt,
        sock = sock_from_file(req->file, &ret);
        if (sock) {
                struct io_async_ctx io;
-               struct sockaddr_storage addr;
                unsigned flags;
 
                if (req->io) {
                        kmsg = &req->io->msg;
-                       kmsg->msg.msg_name = &addr;
+                       kmsg->msg.msg_name = &req->io->msg.addr;
                        /* if iov is set, it's allocated already */
                        if (!kmsg->iov)
                                kmsg->iov = kmsg->fast_iov;
@@ -3199,7 +3198,7 @@ static int io_recvmsg(struct io_kiocb *req, struct io_kiocb **nxt,
                        struct io_sr_msg *sr = &req->sr_msg;
 
                        kmsg = &io.msg;
-                       kmsg->msg.msg_name = &addr;
+                       kmsg->msg.msg_name = &io.msg.addr;
 
                        io.msg.iov = io.msg.fast_iov;
                        ret = recvmsg_copy_msghdr(&io.msg.msg, sr->msg,