@@ -108,6 +108,7 @@ bool io_kbuf_recycle_legacy(struct io_kiocb *req, unsigned issue_flags)
108108 buf = req -> kbuf ;
109109 bl = io_buffer_get_list (ctx , buf -> bgid );
110110 list_add (& buf -> list , & bl -> buf_list );
111+ bl -> nbufs ++ ;
111112 req -> flags &= ~REQ_F_BUFFER_SELECTED ;
112113
113114 io_ring_submit_unlock (ctx , issue_flags );
@@ -122,6 +123,7 @@ static void __user *io_provided_buffer_select(struct io_kiocb *req, size_t *len,
122123
123124 kbuf = list_first_entry (& bl -> buf_list , struct io_buffer , list );
124125 list_del (& kbuf -> list );
126+ bl -> nbufs -- ;
125127 if (* len == 0 || * len > kbuf -> len )
126128 * len = kbuf -> len ;
127129 if (list_empty (& bl -> buf_list ))
@@ -390,6 +392,7 @@ static int io_remove_buffers_legacy(struct io_ring_ctx *ctx,
390392 for (i = 0 ; i < nbufs && !list_empty (& bl -> buf_list ); i ++ ) {
391393 nxt = list_first_entry (& bl -> buf_list , struct io_buffer , list );
392394 list_del (& nxt -> list );
395+ bl -> nbufs -- ;
393396 kfree (nxt );
394397 cond_resched ();
395398 }
@@ -491,14 +494,24 @@ static int io_add_buffers(struct io_ring_ctx *ctx, struct io_provide_buf *pbuf,
491494{
492495 struct io_buffer * buf ;
493496 u64 addr = pbuf -> addr ;
494- int i , bid = pbuf -> bid ;
497+ int ret = - ENOMEM , i , bid = pbuf -> bid ;
495498
496499 for (i = 0 ; i < pbuf -> nbufs ; i ++ ) {
500+ /*
501+ * Nonsensical to have more than sizeof(bid) buffers in a
502+ * buffer list, as the application then has no way of knowing
503+ * which duplicate bid refers to what buffer.
504+ */
505+ if (bl -> nbufs == USHRT_MAX ) {
506+ ret = - EOVERFLOW ;
507+ break ;
508+ }
497509 buf = kmalloc (sizeof (* buf ), GFP_KERNEL_ACCOUNT );
498510 if (!buf )
499511 break ;
500512
501513 list_add_tail (& buf -> list , & bl -> buf_list );
514+ bl -> nbufs ++ ;
502515 buf -> addr = addr ;
503516 buf -> len = min_t (__u32 , pbuf -> len , MAX_RW_COUNT );
504517 buf -> bid = bid ;
@@ -508,7 +521,7 @@ static int io_add_buffers(struct io_ring_ctx *ctx, struct io_provide_buf *pbuf,
508521 cond_resched ();
509522 }
510523
511- return i ? 0 : - ENOMEM ;
524+ return i ? 0 : ret ;
512525}
513526
514527static int __io_manage_buffers_legacy (struct io_kiocb * req ,
0 commit comments