From: Zhihao Cheng chengzhihao1@huawei.com
hulk inclusion category: bugfix bugzilla: 187369, https://gitee.com/openeuler/kernel/issues/I5K66O CVE: NA
--------------------------------
Following process triggers an use-after-free problem while iterating every process's fs:
main fd = setup_iouring fork => main' // task->fs->users = 1 submit(fd, STATX, async) id->fs = current->fs req->work.identity = id io_submit_sqes ... io_grab_identity id = req->work.identity id->fs->users++ // fs->users = 2
io_wqe_worker current->fs = work->identity->fs io_req_clean_work fs = req->work.identity->fs --fs->users // fs->user = 1
main' exit exit_fs --fs->users // fs->user = 0 free_fs_struct(fs) // FREE fs
pivot_root chroot_fs_refs do_each_thread(g, p) { fs = p->fs // io_wqe_worker->fs if (fs) spin_lock(&fs->lock) // UAF! }
io_wqe_worker io_worker_exit __io_worker_unuse if (current->fs != worker->restore_fs) current->fs = worker->restore_fs
Task's fs_struct is used in do_work() and destroyed in free_work(), this problem can be fixed by switching io_wqe_worker's fs before releasing request.
Signed-off-by: Zhihao Cheng chengzhihao1@huawei.com Reviewed-by: Zhang Yi yi.zhang@huawei.com Signed-off-by: Yongqiang Liu liuyongqiang13@huawei.com --- fs/io-wq.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/fs/io-wq.c b/fs/io-wq.c index b6e311e57b47..67d157bcf2fb 100644 --- a/fs/io-wq.c +++ b/fs/io-wq.c @@ -534,6 +534,8 @@ static void io_worker_handle_work(struct io_worker *worker) linked = NULL; } io_assign_current_work(worker, work); + if (current->fs != worker->restore_fs) + current->fs = worker->restore_fs; wq->free_work(old_work);
if (linked)