io_uring: NULL-deref for IOSQE_{ASYNC,DRAIN}

Processing links, io_submit_sqe() prepares requests, drops sqes, and
passes them with sqe=NULL to io_queue_sqe(). There IOSQE_DRAIN and/or
IOSQE_ASYNC requests will go through the same prep, which doesn't expect
sqe=NULL and fail with NULL pointer deference.

Always do full prepare including io_alloc_async_ctx() for linked
requests, and then it can skip the second preparation.

Cc: stable@vger.kernel.org # 5.5
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by Pavel Begunkov and committed by Jens Axboe f1d96a8f 805b13ad

+8
+8
fs/io_uring.c
··· 4131 { 4132 ssize_t ret = 0; 4133 4134 if (io_op_defs[req->opcode].file_table) { 4135 ret = io_grab_files(req); 4136 if (unlikely(ret)) ··· 4910 if (sqe_flags & (IOSQE_IO_LINK|IOSQE_IO_HARDLINK)) { 4911 req->flags |= REQ_F_LINK; 4912 INIT_LIST_HEAD(&req->link_list); 4913 ret = io_req_defer_prep(req, sqe); 4914 if (ret) 4915 req->flags |= REQ_F_FAIL_LINK;
··· 4131 { 4132 ssize_t ret = 0; 4133 4134 + if (!sqe) 4135 + return 0; 4136 + 4137 if (io_op_defs[req->opcode].file_table) { 4138 ret = io_grab_files(req); 4139 if (unlikely(ret)) ··· 4907 if (sqe_flags & (IOSQE_IO_LINK|IOSQE_IO_HARDLINK)) { 4908 req->flags |= REQ_F_LINK; 4909 INIT_LIST_HEAD(&req->link_list); 4910 + 4911 + if (io_alloc_async_ctx(req)) { 4912 + ret = -EAGAIN; 4913 + goto err_req; 4914 + } 4915 ret = io_req_defer_prep(req, sqe); 4916 if (ret) 4917 req->flags |= REQ_F_FAIL_LINK;