Re: [RFC] Check if file_data is initialized

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 1/9/20 7:26 AM, Pavel Begunkov wrote:
> On 1/9/2020 4:17 PM, Dmitrii Dolgov wrote:
>> With combination of --fixedbufs and an old version of fio I've managed
>> to get a strange situation, when doing io_iopoll_complete NULL pointer
>> dereference on file_data was caused in io_free_req_many. Interesting
>> enough, the very same configuration doesn't fail on a newest version of
>> fio (the old one is fc220349e4514, the new one is 2198a6b5a9f4), but I
>> guess it still makes sense to have this check if it's possible to craft
>> such request to io_uring.
> 
> I didn't looked up why it could become NULL in the first place, but the
> problem is probably deeper.
> 
> 1. I don't see why it puts @rb->to_free @file_data->refs, even though
> there could be non-fixed reqs. It needs to count REQ_F_FIXED_FILE reqs
> and put only as much.

Agree on the fixed file refs, there's a bug there where it assumes they
are all still fixed. See below - Dmitrii, use this patch for testing
instead of the other one!

> 2. Jens, there is another line bothering me, could you take a look?
> 
> io_free_req_many()
> {
> ...
> 	if (req->flags & REQ_F_INFLIGHT) ...;
> 	else
> 		rb->reqs[i] = NULL;
> ...
> }
> 
> It zeroes rb->reqs[i], calls __io_req_aux_free(), but did not free
> memory for the request itself. Is it as intended?

We free them at the end of that function, in bulk. But we can't do that
with the aux data.


diff --git a/fs/io_uring.c b/fs/io_uring.c
index 32aee149f652..b5dcf6c800ef 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -1218,6 +1218,8 @@ struct req_batch {
 
 static void io_free_req_many(struct io_ring_ctx *ctx, struct req_batch *rb)
 {
+	int fixed_refs = 0;
+
 	if (!rb->to_free)
 		return;
 	if (rb->need_iter) {
@@ -1227,8 +1229,10 @@ static void io_free_req_many(struct io_ring_ctx *ctx, struct req_batch *rb)
 		for (i = 0; i < rb->to_free; i++) {
 			struct io_kiocb *req = rb->reqs[i];
 
-			if (req->flags & REQ_F_FIXED_FILE)
+			if (req->flags & REQ_F_FIXED_FILE) {
 				req->file = NULL;
+				fixed_refs++;
+			}
 			if (req->flags & REQ_F_INFLIGHT)
 				inflight++;
 			else
@@ -1255,8 +1259,9 @@ static void io_free_req_many(struct io_ring_ctx *ctx, struct req_batch *rb)
 	}
 do_free:
 	kmem_cache_free_bulk(req_cachep, rb->to_free, rb->reqs);
+	if (fixed_refs)
+		percpu_ref_put_many(&ctx->file_data->refs, fixed_refs);
 	percpu_ref_put_many(&ctx->refs, rb->to_free);
-	percpu_ref_put_many(&ctx->file_data->refs, rb->to_free);
 	rb->to_free = rb->need_iter = 0;
 }

-- 
Jens Axboe




[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux