• Z
    io-wq: Switch io_wqe_worker's fs before releasing request · 00bb60b9
    Zhihao Cheng 提交于
    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>
    00bb60b9
io-wq.c 30.4 KB