@@ -204,16 +204,150 @@ 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+
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+
207341static int io_sendmsg_copy_hdr (struct io_kiocb * req ,
208342 struct io_async_msghdr * iomsg )
209343{
210344 struct io_sr_msg * sr = io_kiocb_to_cmd (req , struct io_sr_msg );
211345 int ret ;
212346
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+
217351 /* save msg_control as sys_sendmsg() overwrites it */
218352 sr -> msg_control = iomsg -> msg .msg_control_user ;
219353 return ret ;
@@ -435,142 +569,21 @@ int io_send(struct io_kiocb *req, unsigned int issue_flags)
435569 return IOU_OK ;
436570}
437571
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-
553572static int io_recvmsg_copy_hdr (struct io_kiocb * req ,
554573 struct io_async_msghdr * iomsg )
555574{
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 );
565576}
566577
567578int io_recvmsg_prep_async (struct io_kiocb * req )
568579{
580+ struct io_async_msghdr * iomsg ;
569581 int ret ;
570582
571583 if (!io_msg_alloc_async_prep (req ))
572584 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 );
574587 if (!ret )
575588 req -> flags |= REQ_F_NEED_CLEANUP ;
576589 return ret ;
0 commit comments