@@ -204,16 +204,150 @@ static int io_setup_async_msg(struct io_kiocb *req,
204
204
return - EAGAIN ;
205
205
}
206
206
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
+
222
+ #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 )
226
+ {
227
+ struct io_sr_msg * sr = io_kiocb_to_cmd (req , struct io_sr_msg );
228
+ struct compat_msghdr msg ;
229
+ struct compat_iovec __user * uiov ;
230
+ int ret ;
231
+
232
+ if (copy_from_user (& msg , sr -> umsg_compat , sizeof (msg )))
233
+ return - EFAULT ;
234
+
235
+ ret = __get_compat_msghdr (& iomsg -> msg , & msg , addr );
236
+ if (ret )
237
+ return ret ;
238
+
239
+ uiov = compat_ptr (msg .msg_iov );
240
+ if (req -> flags & REQ_F_BUFFER_SELECT ) {
241
+ compat_ssize_t clen ;
242
+
243
+ iomsg -> free_iov = NULL ;
244
+ if (msg .msg_iovlen == 0 ) {
245
+ sr -> len = 0 ;
246
+ } else if (msg .msg_iovlen > 1 ) {
247
+ return - EINVAL ;
248
+ } else {
249
+ if (!access_ok (uiov , sizeof (* uiov )))
250
+ return - EFAULT ;
251
+ if (__get_user (clen , & uiov -> iov_len ))
252
+ return - EFAULT ;
253
+ if (clen < 0 )
254
+ return - EINVAL ;
255
+ sr -> len = clen ;
256
+ }
257
+
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
+
265
+ return 0 ;
266
+ }
267
+
268
+ iomsg -> free_iov = iomsg -> fast_iov ;
269
+ ret = __import_iovec (ddir , (struct iovec __user * )uiov , msg .msg_iovlen ,
270
+ UIO_FASTIOV , & iomsg -> free_iov ,
271
+ & iomsg -> msg .msg_iter , true);
272
+ if (unlikely (ret < 0 ))
273
+ return ret ;
274
+
275
+ return 0 ;
276
+ }
277
+ #endif
278
+
279
+ static int __io_msg_copy_hdr (struct io_kiocb * req , struct io_async_msghdr * iomsg ,
280
+ struct sockaddr __user * * addr , int ddir )
281
+ {
282
+ struct io_sr_msg * sr = io_kiocb_to_cmd (req , struct io_sr_msg );
283
+ struct user_msghdr msg ;
284
+ int ret ;
285
+
286
+ if (copy_from_user (& msg , sr -> umsg , sizeof (* sr -> umsg )))
287
+ return - EFAULT ;
288
+
289
+ ret = __copy_msghdr (& iomsg -> msg , & msg , addr );
290
+ if (ret )
291
+ return ret ;
292
+
293
+ if (req -> flags & REQ_F_BUFFER_SELECT ) {
294
+ if (msg .msg_iovlen == 0 ) {
295
+ sr -> len = iomsg -> fast_iov [0 ].iov_len = 0 ;
296
+ iomsg -> fast_iov [0 ].iov_base = NULL ;
297
+ iomsg -> free_iov = NULL ;
298
+ } else if (msg .msg_iovlen > 1 ) {
299
+ return - EINVAL ;
300
+ } else {
301
+ if (copy_from_user (iomsg -> fast_iov , msg .msg_iov ,
302
+ sizeof (* msg .msg_iov )))
303
+ return - EFAULT ;
304
+ sr -> len = iomsg -> fast_iov [0 ].iov_len ;
305
+ iomsg -> free_iov = NULL ;
306
+ }
307
+
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
+
315
+ return 0 ;
316
+ }
317
+
318
+ iomsg -> free_iov = iomsg -> fast_iov ;
319
+ ret = __import_iovec (ddir , msg .msg_iov , msg .msg_iovlen , UIO_FASTIOV ,
320
+ & iomsg -> free_iov , & iomsg -> msg .msg_iter , false);
321
+ if (unlikely (ret < 0 ))
322
+ return ret ;
323
+
324
+ return 0 ;
325
+ }
326
+
327
+ static int io_msg_copy_hdr (struct io_kiocb * req , struct io_async_msghdr * iomsg ,
328
+ struct sockaddr __user * * addr , int ddir )
329
+ {
330
+ iomsg -> msg .msg_name = & iomsg -> addr ;
331
+ iomsg -> msg .msg_iter .nr_segs = 0 ;
332
+
333
+ #ifdef CONFIG_COMPAT
334
+ if (req -> ctx -> compat )
335
+ return __io_compat_msg_copy_hdr (req , iomsg , addr , ddir );
336
+ #endif
337
+
338
+ return __io_msg_copy_hdr (req , iomsg , addr , ddir );
339
+ }
340
+
207
341
static int io_sendmsg_copy_hdr (struct io_kiocb * req ,
208
342
struct io_async_msghdr * iomsg )
209
343
{
210
344
struct io_sr_msg * sr = io_kiocb_to_cmd (req , struct io_sr_msg );
211
345
int ret ;
212
346
213
- iomsg -> msg . msg_name = & iomsg -> addr ;
214
- iomsg -> free_iov = iomsg -> fast_iov ;
215
- ret = sendmsg_copy_msghdr ( & iomsg -> msg , sr -> umsg , sr -> msg_flags ,
216
- & iomsg -> free_iov );
347
+ ret = io_msg_copy_hdr ( req , iomsg , NULL , ITER_SOURCE ) ;
348
+ if ( ret )
349
+ return ret ;
350
+
217
351
/* save msg_control as sys_sendmsg() overwrites it */
218
352
sr -> msg_control = iomsg -> msg .msg_control_user ;
219
353
return ret ;
@@ -435,142 +569,21 @@ int io_send(struct io_kiocb *req, unsigned int issue_flags)
435
569
return IOU_OK ;
436
570
}
437
571
438
- static bool io_recvmsg_multishot_overflow (struct io_async_msghdr * iomsg )
439
- {
440
- int hdr ;
441
-
442
- if (iomsg -> namelen < 0 )
443
- return true;
444
- if (check_add_overflow ((int )sizeof (struct io_uring_recvmsg_out ),
445
- iomsg -> namelen , & hdr ))
446
- return true;
447
- if (check_add_overflow (hdr , (int )iomsg -> controllen , & hdr ))
448
- return true;
449
-
450
- return false;
451
- }
452
-
453
- static int __io_recvmsg_copy_hdr (struct io_kiocb * req ,
454
- struct io_async_msghdr * iomsg )
455
- {
456
- struct io_sr_msg * sr = io_kiocb_to_cmd (req , struct io_sr_msg );
457
- struct user_msghdr msg ;
458
- int ret ;
459
-
460
- if (copy_from_user (& msg , sr -> umsg , sizeof (* sr -> umsg )))
461
- return - EFAULT ;
462
-
463
- ret = __copy_msghdr (& iomsg -> msg , & msg , & iomsg -> uaddr );
464
- if (ret )
465
- return ret ;
466
-
467
- if (req -> flags & REQ_F_BUFFER_SELECT ) {
468
- if (msg .msg_iovlen == 0 ) {
469
- sr -> len = iomsg -> fast_iov [0 ].iov_len = 0 ;
470
- iomsg -> fast_iov [0 ].iov_base = NULL ;
471
- iomsg -> free_iov = NULL ;
472
- } else if (msg .msg_iovlen > 1 ) {
473
- return - EINVAL ;
474
- } else {
475
- if (copy_from_user (iomsg -> fast_iov , msg .msg_iov , sizeof (* msg .msg_iov )))
476
- return - EFAULT ;
477
- sr -> len = iomsg -> fast_iov [0 ].iov_len ;
478
- iomsg -> free_iov = NULL ;
479
- }
480
-
481
- if (req -> flags & REQ_F_APOLL_MULTISHOT ) {
482
- iomsg -> namelen = msg .msg_namelen ;
483
- iomsg -> controllen = msg .msg_controllen ;
484
- if (io_recvmsg_multishot_overflow (iomsg ))
485
- return - EOVERFLOW ;
486
- }
487
- } else {
488
- iomsg -> free_iov = iomsg -> fast_iov ;
489
- ret = __import_iovec (ITER_DEST , msg .msg_iov , msg .msg_iovlen , UIO_FASTIOV ,
490
- & iomsg -> free_iov , & iomsg -> msg .msg_iter ,
491
- false);
492
- if (ret > 0 )
493
- ret = 0 ;
494
- }
495
-
496
- return ret ;
497
- }
498
-
499
- #ifdef CONFIG_COMPAT
500
- static int __io_compat_recvmsg_copy_hdr (struct io_kiocb * req ,
501
- struct io_async_msghdr * iomsg )
502
- {
503
- struct io_sr_msg * sr = io_kiocb_to_cmd (req , struct io_sr_msg );
504
- struct compat_msghdr msg ;
505
- struct compat_iovec __user * uiov ;
506
- int ret ;
507
-
508
- if (copy_from_user (& msg , sr -> umsg_compat , sizeof (msg )))
509
- return - EFAULT ;
510
-
511
- ret = __get_compat_msghdr (& iomsg -> msg , & msg , & iomsg -> uaddr );
512
- if (ret )
513
- return ret ;
514
-
515
- uiov = compat_ptr (msg .msg_iov );
516
- if (req -> flags & REQ_F_BUFFER_SELECT ) {
517
- compat_ssize_t clen ;
518
-
519
- iomsg -> free_iov = NULL ;
520
- if (msg .msg_iovlen == 0 ) {
521
- sr -> len = 0 ;
522
- } else if (msg .msg_iovlen > 1 ) {
523
- return - EINVAL ;
524
- } else {
525
- if (!access_ok (uiov , sizeof (* uiov )))
526
- return - EFAULT ;
527
- if (__get_user (clen , & uiov -> iov_len ))
528
- return - EFAULT ;
529
- if (clen < 0 )
530
- return - EINVAL ;
531
- sr -> len = clen ;
532
- }
533
-
534
- if (req -> flags & REQ_F_APOLL_MULTISHOT ) {
535
- iomsg -> namelen = msg .msg_namelen ;
536
- iomsg -> controllen = msg .msg_controllen ;
537
- if (io_recvmsg_multishot_overflow (iomsg ))
538
- return - EOVERFLOW ;
539
- }
540
- } else {
541
- iomsg -> free_iov = iomsg -> fast_iov ;
542
- ret = __import_iovec (ITER_DEST , (struct iovec __user * )uiov , msg .msg_iovlen ,
543
- UIO_FASTIOV , & iomsg -> free_iov ,
544
- & iomsg -> msg .msg_iter , true);
545
- if (ret < 0 )
546
- return ret ;
547
- }
548
-
549
- return 0 ;
550
- }
551
- #endif
552
-
553
572
static int io_recvmsg_copy_hdr (struct io_kiocb * req ,
554
573
struct io_async_msghdr * iomsg )
555
574
{
556
- iomsg -> msg .msg_name = & iomsg -> addr ;
557
- iomsg -> msg .msg_iter .nr_segs = 0 ;
558
-
559
- #ifdef CONFIG_COMPAT
560
- if (req -> ctx -> compat )
561
- return __io_compat_recvmsg_copy_hdr (req , iomsg );
562
- #endif
563
-
564
- return __io_recvmsg_copy_hdr (req , iomsg );
575
+ return io_msg_copy_hdr (req , iomsg , & iomsg -> uaddr , ITER_DEST );
565
576
}
566
577
567
578
int io_recvmsg_prep_async (struct io_kiocb * req )
568
579
{
580
+ struct io_async_msghdr * iomsg ;
569
581
int ret ;
570
582
571
583
if (!io_msg_alloc_async_prep (req ))
572
584
return - ENOMEM ;
573
- ret = io_recvmsg_copy_hdr (req , req -> async_data );
585
+ iomsg = req -> async_data ;
586
+ ret = io_recvmsg_copy_hdr (req , iomsg );
574
587
if (!ret )
575
588
req -> flags |= REQ_F_NEED_CLEANUP ;
576
589
return ret ;
0 commit comments