@@ -3448,29 +3448,41 @@ static int io_buffer_add_list(struct io_ring_ctx *ctx,
34483448 return xa_err (xa_store (& ctx -> io_bl_xa , bgid , bl , GFP_KERNEL ));
34493449}
34503450
3451+ static void __user * io_provided_buffer_select (struct io_kiocb * req , size_t * len ,
3452+ struct io_buffer_list * bl ,
3453+ unsigned int issue_flags )
3454+ {
3455+ struct io_buffer * kbuf ;
3456+
3457+ if (list_empty (& bl -> buf_list ))
3458+ return ERR_PTR (- ENOBUFS );
3459+
3460+ kbuf = list_first_entry (& bl -> buf_list , struct io_buffer , list );
3461+ list_del (& kbuf -> list );
3462+ if (* len > kbuf -> len )
3463+ * len = kbuf -> len ;
3464+ req -> flags |= REQ_F_BUFFER_SELECTED ;
3465+ req -> kbuf = kbuf ;
3466+ io_ring_submit_unlock (req -> ctx , issue_flags );
3467+ return u64_to_user_ptr (kbuf -> addr );
3468+ }
3469+
34513470static void __user * io_buffer_select (struct io_kiocb * req , size_t * len ,
34523471 unsigned int issue_flags )
34533472{
3454- struct io_buffer * kbuf = req -> kbuf ;
34553473 struct io_ring_ctx * ctx = req -> ctx ;
34563474 struct io_buffer_list * bl ;
34573475
34583476 io_ring_submit_lock (req -> ctx , issue_flags );
34593477
34603478 bl = io_buffer_get_list (ctx , req -> buf_index );
3461- if (bl && !list_empty (& bl -> buf_list )) {
3462- kbuf = list_first_entry (& bl -> buf_list , struct io_buffer , list );
3463- list_del (& kbuf -> list );
3464- if (* len > kbuf -> len )
3465- * len = kbuf -> len ;
3466- req -> flags |= REQ_F_BUFFER_SELECTED ;
3467- req -> kbuf = kbuf ;
3479+ if (unlikely (!bl )) {
34683480 io_ring_submit_unlock (req -> ctx , issue_flags );
3469- return u64_to_user_ptr ( kbuf -> addr );
3481+ return ERR_PTR ( - ENOBUFS );
34703482 }
34713483
3472- io_ring_submit_unlock ( req -> ctx , issue_flags );
3473- return ERR_PTR ( - ENOBUFS );
3484+ /* selection helpers drop the submit lock again, if needed */
3485+ return io_provided_buffer_select ( req , len , bl , issue_flags );
34743486}
34753487
34763488#ifdef CONFIG_COMPAT
0 commit comments