diff options
author | Xiaoguang Wang <xiaoguang.wang@linux.alibaba.com> | 2020-06-18 09:01:56 +0200 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2020-06-18 16:32:44 +0200 |
commit | 6f2cc1664db20676069cff27a461ccc97dbfd114 (patch) | |
tree | 03f8e94c146b804f87b40ffa3f84b08d13f065d8 /fs/io_uring.c | |
parent | io_uring: reap poll completions while waiting for refs to drop on exit (diff) | |
download | linux-6f2cc1664db20676069cff27a461ccc97dbfd114.tar.xz linux-6f2cc1664db20676069cff27a461ccc97dbfd114.zip |
io_uring: fix possible race condition against REQ_F_NEED_CLEANUP
In io_read() or io_write(), when io request is submitted successfully,
it'll go through the below sequence:
kfree(iovec);
req->flags &= ~REQ_F_NEED_CLEANUP;
return ret;
But clearing REQ_F_NEED_CLEANUP might be unsafe. The io request may
already have been completed, and then io_complete_rw_iopoll()
and io_complete_rw() will be called, both of which will also modify
req->flags if needed. This causes a race condition, with concurrent
non-atomic modification of req->flags.
To eliminate this race, in io_read() or io_write(), if io request is
submitted successfully, we don't remove REQ_F_NEED_CLEANUP flag. If
REQ_F_NEED_CLEANUP is set, we'll leave __io_req_aux_free() to the
iovec cleanup work correspondingly.
Cc: stable@vger.kernel.org
Signed-off-by: Xiaoguang Wang <xiaoguang.wang@linux.alibaba.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to '')
-rw-r--r-- | fs/io_uring.c | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/fs/io_uring.c b/fs/io_uring.c index 2038d52c5450..a78201b96179 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -2670,8 +2670,8 @@ copy_iov: } } out_free: - kfree(iovec); - req->flags &= ~REQ_F_NEED_CLEANUP; + if (!(req->flags & REQ_F_NEED_CLEANUP)) + kfree(iovec); return ret; } @@ -2793,8 +2793,8 @@ copy_iov: } } out_free: - req->flags &= ~REQ_F_NEED_CLEANUP; - kfree(iovec); + if (!(req->flags & REQ_F_NEED_CLEANUP)) + kfree(iovec); return ret; } |