Skip to content

Commit 18d6b17

Browse files
committed
io_uring/rw: check for NULL io_br_sel when putting a buffer
Both the read and write side use kiocb_done() to finish a request, and kiocb_done() will call io_put_kbuf() in case a provided buffer was used for the request. Provided buffers are not supported for writes, hence NULL is being passed in. This normally works fine, as io_put_kbuf() won't actually use the value unless REQ_F_BUFFER_RING or REQ_F_BUFFER_SELECTED is set in the request flags. But depending on compiler (or whether or not CONFIG_CC_OPTIMIZE_FOR_SIZE is set), that may be done even though the value is never used. This will then cause a NULL pointer dereference. Make it a bit more obvious and check for a NULL io_br_sel, and don't even bother calling io_put_kbuf() for that case. Fixes: 5fda512 ("io_uring/kbuf: switch to storing struct io_buffer_list locally") Reported-by: David Howells <dhowells@redhat.com> Tested-by: David Howells <dhowells@redhat.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 437c233 commit 18d6b17

File tree

1 file changed

+5
-1
lines changed

1 file changed

+5
-1
lines changed

io_uring/rw.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -655,13 +655,17 @@ static int kiocb_done(struct io_kiocb *req, ssize_t ret,
655655
if (ret >= 0 && req->flags & REQ_F_CUR_POS)
656656
req->file->f_pos = rw->kiocb.ki_pos;
657657
if (ret >= 0 && !(req->ctx->flags & IORING_SETUP_IOPOLL)) {
658+
u32 cflags = 0;
659+
658660
__io_complete_rw_common(req, ret);
659661
/*
660662
* Safe to call io_end from here as we're inline
661663
* from the submission path.
662664
*/
663665
io_req_io_end(req);
664-
io_req_set_res(req, final_ret, io_put_kbuf(req, ret, sel->buf_list));
666+
if (sel)
667+
cflags = io_put_kbuf(req, ret, sel->buf_list);
668+
io_req_set_res(req, final_ret, cflags);
665669
io_req_rw_cleanup(req, issue_flags);
666670
return IOU_COMPLETE;
667671
} else {

0 commit comments

Comments
 (0)