Commit e0540864 authored by Trond Myklebust's avatar Trond Myklebust Committed by Li Lingfeng
Browse files

NFSv4.0: Fix a use-after-free problem in the asynchronous open()

stable inclusion
from stable-v6.6.64
commit 229a30ed42bb87bcb044c5523fabd9e4f0e75648
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IBBR8I
CVE: CVE-2024-53173

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=229a30ed42bb87bcb044c5523fabd9e4f0e75648



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

[ Upstream commit 2fdb05dc0931250574f0cb0ebeb5ed8e20f4a889 ]

Yang Erkun reports that when two threads are opening files at the same
time, and are forced to abort before a reply is seen, then the call to
nfs_release_seqid() in nfs4_opendata_free() can result in a
use-after-free of the pointer to the defunct rpc task of the other
thread.
The fix is to ensure that if the RPC call is aborted before the call to
nfs_wait_on_sequence() is complete, then we must call nfs_release_seqid()
in nfs4_open_release() before the rpc_task is freed.

Reported-by: default avatarYang Erkun <yangerkun@huawei.com>
Fixes: 24ac23ab ("NFSv4: Convert open() into an asynchronous RPC call")
Reviewed-by: default avatarYang Erkun <yangerkun@huawei.com>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
Signed-off-by: default avatarLi Lingfeng <lilingfeng3@huawei.com>
parent 19b015b5
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -2528,12 +2528,14 @@ static void nfs4_open_release(void *calldata)
	struct nfs4_opendata *data = calldata;
	struct nfs4_state *state = NULL;

	/* In case of error, no cleanup! */
	if (data->rpc_status != 0 || !data->rpc_done) {
		nfs_release_seqid(data->o_arg.seqid);
		goto out_free;
	}
	/* If this request hasn't been cancelled, do nothing */
	if (!data->cancelled)
		goto out_free;
	/* In case of error, no cleanup! */
	if (data->rpc_status != 0 || !data->rpc_done)
		goto out_free;
	/* In case we need an open_confirm, no cleanup! */
	if (data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM)
		goto out_free;