]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
NFSv4.0: Fix a use-after-free problem in the asynchronous open()
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Fri, 8 Nov 2024 17:13:31 +0000 (12:13 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 5 Dec 2024 12:54:27 +0000 (13:54 +0100)
[ 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: Yang Erkun <yangerkun@huawei.com>
Fixes: 24ac23ab88df ("NFSv4: Convert open() into an asynchronous RPC call")
Reviewed-by: Yang Erkun <yangerkun@huawei.com>
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/nfs/nfs4proc.c

index 9d40319e063dea48bce9c94bc4ba971fc839b4ba..405f17e6e0b45b26cebae06c5bbe932895af9a56 100644 (file)
@@ -2603,12 +2603,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;