mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-10 15:19:51 +00:00
io_uring: fix files grab/cancel race
When one task is in io_uring_cancel_files() and another is doing io_prep_async_work() a race may happen. That's because after accounting a request inflight in first call to io_grab_identity() it still may fail and go to io_identity_cow(), which migh briefly keep dangling work.identity and not only. Grab files last, so io_prep_async_work() won't fail if it did get into ->inflight_list. note: the bug shouldn't exist after making io_uring_cancel_files() not poking into other tasks' requests. Signed-off-by: Pavel Begunkov <asml.silence@gmail.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
9c3a205c5f
commit
af60470347
@ -1313,22 +1313,6 @@ static bool io_grab_identity(struct io_kiocb *req)
|
|||||||
return false;
|
return false;
|
||||||
req->work.flags |= IO_WQ_WORK_FSIZE;
|
req->work.flags |= IO_WQ_WORK_FSIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(req->work.flags & IO_WQ_WORK_FILES) &&
|
|
||||||
(def->work_flags & IO_WQ_WORK_FILES) &&
|
|
||||||
!(req->flags & REQ_F_NO_FILE_TABLE)) {
|
|
||||||
if (id->files != current->files ||
|
|
||||||
id->nsproxy != current->nsproxy)
|
|
||||||
return false;
|
|
||||||
atomic_inc(&id->files->count);
|
|
||||||
get_nsproxy(id->nsproxy);
|
|
||||||
req->flags |= REQ_F_INFLIGHT;
|
|
||||||
|
|
||||||
spin_lock_irq(&ctx->inflight_lock);
|
|
||||||
list_add(&req->inflight_entry, &ctx->inflight_list);
|
|
||||||
spin_unlock_irq(&ctx->inflight_lock);
|
|
||||||
req->work.flags |= IO_WQ_WORK_FILES;
|
|
||||||
}
|
|
||||||
#ifdef CONFIG_BLK_CGROUP
|
#ifdef CONFIG_BLK_CGROUP
|
||||||
if (!(req->work.flags & IO_WQ_WORK_BLKCG) &&
|
if (!(req->work.flags & IO_WQ_WORK_BLKCG) &&
|
||||||
(def->work_flags & IO_WQ_WORK_BLKCG)) {
|
(def->work_flags & IO_WQ_WORK_BLKCG)) {
|
||||||
@ -1370,6 +1354,21 @@ static bool io_grab_identity(struct io_kiocb *req)
|
|||||||
}
|
}
|
||||||
spin_unlock(¤t->fs->lock);
|
spin_unlock(¤t->fs->lock);
|
||||||
}
|
}
|
||||||
|
if (!(req->work.flags & IO_WQ_WORK_FILES) &&
|
||||||
|
(def->work_flags & IO_WQ_WORK_FILES) &&
|
||||||
|
!(req->flags & REQ_F_NO_FILE_TABLE)) {
|
||||||
|
if (id->files != current->files ||
|
||||||
|
id->nsproxy != current->nsproxy)
|
||||||
|
return false;
|
||||||
|
atomic_inc(&id->files->count);
|
||||||
|
get_nsproxy(id->nsproxy);
|
||||||
|
req->flags |= REQ_F_INFLIGHT;
|
||||||
|
|
||||||
|
spin_lock_irq(&ctx->inflight_lock);
|
||||||
|
list_add(&req->inflight_entry, &ctx->inflight_list);
|
||||||
|
spin_unlock_irq(&ctx->inflight_lock);
|
||||||
|
req->work.flags |= IO_WQ_WORK_FILES;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user