Commit 4f97f859 authored by Li Lingfeng's avatar Li Lingfeng
Browse files

nfs: fix rpc_task use-after-free when open and close different files concurrently

hulk inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IB20ED

--------------------------------

Commit b5e9ee1ed8bb("[Huawei] NFSv4: release seqid when open failed for
nfs4.0") describes a scenario where a file system is forcibly unmounted
when different files are opened concurrently.
There is another similar issue where performing concurrent operations of
opening file B, closing file A, and unmounting while file A is open which
can trigger a UAF of rpc_task.

T1: OPEN fileB                  T2: CLOSE fileA
nfs4_do_open
...
 .rpc_call_prepare
 nfs_wait_on_sequence
   // insert to sequence list(T1)
   // This is the first entry,
   // and continue.
                           nfs4_do_close
                            .rpc_call_prepare
                            nfs_wait_on_sequence
                               // insert to sequence list(T2)
                               // This is the second entry,
                               // and wait.
                             [T3 wake up T2 here]
...
 rpc_put_task
  // finish rpc_task and free it
                            .rpc_call_done
                            nfs_release_seqid
                             list_first_entry // get T1 from list
                             rpc_wake_up_queued_task // wake up T1, UAF
 _nfs4_open_and_get_state
  _nfs4_open_and_get_state
   _nfs4_opendata_to_nfs4_state
    nfs_release_seqid
     // remove T1 from list

          T3: UMOUNT
nfs_umount_begin
 rpc_killall_tasks
  rpc_signal_task // get T2 from clnt->cl_tasks
   rpc_wake_up_queued_task_set_status
    rpc_wake_up_task_queue_set_status_locked
     rpc_wake_up_task_on_wq_queue_action_locked
      __rpc_do_wake_up_task_on_wq
       rpc_make_runnable
        wake_up_bit // wake up T2

Although the rpc_task corresponding to T1 has been freed, its seqid has
not been removed from the sequence list.
Additionally, even though T2 is the last task in the list, the current
logic of nfs_release_seqid allows T2 to access tasks inserted before it,
which can trigger UAF.

Fix it by using nfs_release_seqid_inorder instead of nfs_release_seqid in
nfs4_close_done.

Fixes: 72211dbe ("NFSv4: Release the sequence id before restarting a CLOSE rpc call")
Link: https://lore.kernel.org/all/b9924cd2-253a-6c44-3331-56310f13df0b@huawei.com/


Signed-off-by: default avatarLi Lingfeng <lilingfeng3@huawei.com>
parent 8a6f6a9d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -3612,7 +3612,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
			res_stateid, calldata->arg.fmode);
out_release:
	task->tk_status = 0;
	nfs_release_seqid(calldata->arg.seqid);
	nfs_release_seqid_inorder(calldata->arg.seqid);
	nfs_refresh_inode(calldata->inode, &calldata->fattr);
	dprintk("%s: ret = %d\n", __func__, task->tk_status);
	return;