Skip to content

Commit c559780

Browse files
committed
io_uring/net: move receive multishot out of the generic msghdr path
Move the actual user_msghdr / compat_msghdr into the send and receive sides, respectively, so we can move the uaddr receive handling into its own handler, and ditto the multishot with buffer selection logic. Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 52307ac commit c559780

File tree

1 file changed

+91
-70
lines changed

1 file changed

+91
-70
lines changed

io_uring/net.c

Lines changed: 91 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -204,46 +204,26 @@ static int io_setup_async_msg(struct io_kiocb *req,
204204
return -EAGAIN;
205205
}
206206

207-
static bool io_recvmsg_multishot_overflow(struct io_async_msghdr *iomsg)
208-
{
209-
int hdr;
210-
211-
if (iomsg->namelen < 0)
212-
return true;
213-
if (check_add_overflow((int)sizeof(struct io_uring_recvmsg_out),
214-
iomsg->namelen, &hdr))
215-
return true;
216-
if (check_add_overflow(hdr, (int)iomsg->controllen, &hdr))
217-
return true;
218-
219-
return false;
220-
}
221-
222207
#ifdef CONFIG_COMPAT
223-
static int __io_compat_msg_copy_hdr(struct io_kiocb *req,
224-
struct io_async_msghdr *iomsg,
225-
struct sockaddr __user **addr, int ddir)
208+
static int io_compat_msg_copy_hdr(struct io_kiocb *req,
209+
struct io_async_msghdr *iomsg,
210+
struct compat_msghdr *msg, int ddir)
226211
{
227212
struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);
228-
struct compat_msghdr msg;
229213
struct compat_iovec __user *uiov;
230214
int ret;
231215

232-
if (copy_from_user(&msg, sr->umsg_compat, sizeof(msg)))
216+
if (copy_from_user(msg, sr->umsg_compat, sizeof(*msg)))
233217
return -EFAULT;
234218

235-
ret = __get_compat_msghdr(&iomsg->msg, &msg, addr);
236-
if (ret)
237-
return ret;
238-
239-
uiov = compat_ptr(msg.msg_iov);
219+
uiov = compat_ptr(msg->msg_iov);
240220
if (req->flags & REQ_F_BUFFER_SELECT) {
241221
compat_ssize_t clen;
242222

243223
iomsg->free_iov = NULL;
244-
if (msg.msg_iovlen == 0) {
224+
if (msg->msg_iovlen == 0) {
245225
sr->len = 0;
246-
} else if (msg.msg_iovlen > 1) {
226+
} else if (msg->msg_iovlen > 1) {
247227
return -EINVAL;
248228
} else {
249229
if (!access_ok(uiov, sizeof(*uiov)))
@@ -255,18 +235,11 @@ static int __io_compat_msg_copy_hdr(struct io_kiocb *req,
255235
sr->len = clen;
256236
}
257237

258-
if (ddir == ITER_DEST && req->flags & REQ_F_APOLL_MULTISHOT) {
259-
iomsg->namelen = msg.msg_namelen;
260-
iomsg->controllen = msg.msg_controllen;
261-
if (io_recvmsg_multishot_overflow(iomsg))
262-
return -EOVERFLOW;
263-
}
264-
265238
return 0;
266239
}
267240

268241
iomsg->free_iov = iomsg->fast_iov;
269-
ret = __import_iovec(ddir, (struct iovec __user *)uiov, msg.msg_iovlen,
242+
ret = __import_iovec(ddir, (struct iovec __user *)uiov, msg->msg_iovlen,
270243
UIO_FASTIOV, &iomsg->free_iov,
271244
&iomsg->msg.msg_iter, true);
272245
if (unlikely(ret < 0))
@@ -276,78 +249,70 @@ static int __io_compat_msg_copy_hdr(struct io_kiocb *req,
276249
}
277250
#endif
278251

279-
static int __io_msg_copy_hdr(struct io_kiocb *req, struct io_async_msghdr *iomsg,
280-
struct sockaddr __user **addr, int ddir)
252+
static int io_msg_copy_hdr(struct io_kiocb *req, struct io_async_msghdr *iomsg,
253+
struct user_msghdr *msg, int ddir)
281254
{
282255
struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);
283-
struct user_msghdr msg;
284256
int ret;
285257

286-
if (copy_from_user(&msg, sr->umsg, sizeof(*sr->umsg)))
258+
if (copy_from_user(msg, sr->umsg, sizeof(*sr->umsg)))
287259
return -EFAULT;
288260

289-
ret = __copy_msghdr(&iomsg->msg, &msg, addr);
290-
if (ret)
291-
return ret;
292-
293261
if (req->flags & REQ_F_BUFFER_SELECT) {
294-
if (msg.msg_iovlen == 0) {
262+
if (msg->msg_iovlen == 0) {
295263
sr->len = iomsg->fast_iov[0].iov_len = 0;
296264
iomsg->fast_iov[0].iov_base = NULL;
297265
iomsg->free_iov = NULL;
298-
} else if (msg.msg_iovlen > 1) {
266+
} else if (msg->msg_iovlen > 1) {
299267
return -EINVAL;
300268
} else {
301-
if (copy_from_user(iomsg->fast_iov, msg.msg_iov,
302-
sizeof(*msg.msg_iov)))
269+
if (copy_from_user(iomsg->fast_iov, msg->msg_iov,
270+
sizeof(*msg->msg_iov)))
303271
return -EFAULT;
304272
sr->len = iomsg->fast_iov[0].iov_len;
305273
iomsg->free_iov = NULL;
306274
}
307275

308-
if (ddir == ITER_DEST && req->flags & REQ_F_APOLL_MULTISHOT) {
309-
iomsg->namelen = msg.msg_namelen;
310-
iomsg->controllen = msg.msg_controllen;
311-
if (io_recvmsg_multishot_overflow(iomsg))
312-
return -EOVERFLOW;
313-
}
314-
315276
return 0;
316277
}
317278

318279
iomsg->free_iov = iomsg->fast_iov;
319-
ret = __import_iovec(ddir, msg.msg_iov, msg.msg_iovlen, UIO_FASTIOV,
280+
ret = __import_iovec(ddir, msg->msg_iov, msg->msg_iovlen, UIO_FASTIOV,
320281
&iomsg->free_iov, &iomsg->msg.msg_iter, false);
321282
if (unlikely(ret < 0))
322283
return ret;
323284

324285
return 0;
325286
}
326287

327-
static int io_msg_copy_hdr(struct io_kiocb *req, struct io_async_msghdr *iomsg,
328-
struct sockaddr __user **addr, int ddir)
288+
static int io_sendmsg_copy_hdr(struct io_kiocb *req,
289+
struct io_async_msghdr *iomsg)
329290
{
291+
struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);
292+
struct user_msghdr msg;
293+
int ret;
294+
330295
iomsg->msg.msg_name = &iomsg->addr;
331296
iomsg->msg.msg_iter.nr_segs = 0;
332297

333298
#ifdef CONFIG_COMPAT
334-
if (req->ctx->compat)
335-
return __io_compat_msg_copy_hdr(req, iomsg, addr, ddir);
336-
#endif
299+
if (unlikely(req->ctx->compat)) {
300+
struct compat_msghdr cmsg;
337301

338-
return __io_msg_copy_hdr(req, iomsg, addr, ddir);
339-
}
302+
ret = io_compat_msg_copy_hdr(req, iomsg, &cmsg, ITER_SOURCE);
303+
if (unlikely(ret))
304+
return ret;
340305

341-
static int io_sendmsg_copy_hdr(struct io_kiocb *req,
342-
struct io_async_msghdr *iomsg)
343-
{
344-
struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);
345-
int ret;
306+
return __get_compat_msghdr(&iomsg->msg, &cmsg, NULL);
307+
}
308+
#endif
346309

347-
ret = io_msg_copy_hdr(req, iomsg, NULL, ITER_SOURCE);
348-
if (ret)
310+
ret = io_msg_copy_hdr(req, iomsg, &msg, ITER_SOURCE);
311+
if (unlikely(ret))
349312
return ret;
350313

314+
ret = __copy_msghdr(&iomsg->msg, &msg, NULL);
315+
351316
/* save msg_control as sys_sendmsg() overwrites it */
352317
sr->msg_control = iomsg->msg.msg_control_user;
353318
return ret;
@@ -569,10 +534,66 @@ int io_send(struct io_kiocb *req, unsigned int issue_flags)
569534
return IOU_OK;
570535
}
571536

537+
static int io_recvmsg_mshot_prep(struct io_kiocb *req,
538+
struct io_async_msghdr *iomsg,
539+
size_t namelen, size_t controllen)
540+
{
541+
if ((req->flags & (REQ_F_APOLL_MULTISHOT|REQ_F_BUFFER_SELECT)) ==
542+
(REQ_F_APOLL_MULTISHOT|REQ_F_BUFFER_SELECT)) {
543+
int hdr;
544+
545+
if (unlikely(namelen < 0))
546+
return -EOVERFLOW;
547+
if (check_add_overflow((int)sizeof(struct io_uring_recvmsg_out),
548+
namelen, &hdr))
549+
return -EOVERFLOW;
550+
if (check_add_overflow(hdr, (int)controllen, &hdr))
551+
return -EOVERFLOW;
552+
553+
iomsg->namelen = namelen;
554+
iomsg->controllen = controllen;
555+
return 0;
556+
}
557+
558+
return 0;
559+
}
560+
572561
static int io_recvmsg_copy_hdr(struct io_kiocb *req,
573562
struct io_async_msghdr *iomsg)
574563
{
575-
return io_msg_copy_hdr(req, iomsg, &iomsg->uaddr, ITER_DEST);
564+
struct user_msghdr msg;
565+
int ret;
566+
567+
iomsg->msg.msg_name = &iomsg->addr;
568+
iomsg->msg.msg_iter.nr_segs = 0;
569+
570+
#ifdef CONFIG_COMPAT
571+
if (unlikely(req->ctx->compat)) {
572+
struct compat_msghdr cmsg;
573+
574+
ret = io_compat_msg_copy_hdr(req, iomsg, &cmsg, ITER_DEST);
575+
if (unlikely(ret))
576+
return ret;
577+
578+
ret = __get_compat_msghdr(&iomsg->msg, &cmsg, &iomsg->uaddr);
579+
if (unlikely(ret))
580+
return ret;
581+
582+
return io_recvmsg_mshot_prep(req, iomsg, cmsg.msg_namelen,
583+
cmsg.msg_controllen);
584+
}
585+
#endif
586+
587+
ret = io_msg_copy_hdr(req, iomsg, &msg, ITER_DEST);
588+
if (unlikely(ret))
589+
return ret;
590+
591+
ret = __copy_msghdr(&iomsg->msg, &msg, &iomsg->uaddr);
592+
if (unlikely(ret))
593+
return ret;
594+
595+
return io_recvmsg_mshot_prep(req, iomsg, msg.msg_namelen,
596+
msg.msg_controllen);
576597
}
577598

578599
int io_recvmsg_prep_async(struct io_kiocb *req)

0 commit comments

Comments
 (0)