提交 00bb60b9 编写于 作者: Z Zhihao Cheng 提交者: Zheng Zengkai

io-wq: Switch io_wqe_worker's fs before releasing request

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: NZhihao Cheng <chengzhihao1@huawei.com>
Reviewed-by: NZhang Yi <yi.zhang@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 425154ed
......@@ -578,6 +578,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)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册