Commit b76d4fb2 authored by Olga Kornievskaia's avatar Olga Kornievskaia Committed by Greg Kroah-Hartman

NFS prevent double free in async nfs4_exchange_id

commit 63513232 upstream.

Since rpc_task is async, the release function should be called which
will free the impl_id, scope, and owner.

Trond pointed at 2 more problems:
-- use of client pointer after free in the nfs4_exchangeid_release() function
-- cl_count mismatch if rpc_run_task() isn't run

Fixes: 8d89bd70 ("NFS setup async exchange_id")
Signed-off-by: default avatarOlga Kornievskaia <kolga@netapp.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 87144ec2
...@@ -7426,11 +7426,11 @@ static void nfs4_exchange_id_release(void *data) ...@@ -7426,11 +7426,11 @@ static void nfs4_exchange_id_release(void *data)
struct nfs41_exchange_id_data *cdata = struct nfs41_exchange_id_data *cdata =
(struct nfs41_exchange_id_data *)data; (struct nfs41_exchange_id_data *)data;
nfs_put_client(cdata->args.client);
if (cdata->xprt) { if (cdata->xprt) {
xprt_put(cdata->xprt); xprt_put(cdata->xprt);
rpc_clnt_xprt_switch_put(cdata->args.client->cl_rpcclient); rpc_clnt_xprt_switch_put(cdata->args.client->cl_rpcclient);
} }
nfs_put_client(cdata->args.client);
kfree(cdata->res.impl_id); kfree(cdata->res.impl_id);
kfree(cdata->res.server_scope); kfree(cdata->res.server_scope);
kfree(cdata->res.server_owner); kfree(cdata->res.server_owner);
...@@ -7537,10 +7537,8 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred, ...@@ -7537,10 +7537,8 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
task_setup_data.callback_data = calldata; task_setup_data.callback_data = calldata;
task = rpc_run_task(&task_setup_data); task = rpc_run_task(&task_setup_data);
if (IS_ERR(task)) { if (IS_ERR(task))
status = PTR_ERR(task); return PTR_ERR(task);
goto out_impl_id;
}
if (!xprt) { if (!xprt) {
status = rpc_wait_for_completion_task(task); status = rpc_wait_for_completion_task(task);
...@@ -7568,6 +7566,7 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred, ...@@ -7568,6 +7566,7 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
kfree(calldata->res.server_owner); kfree(calldata->res.server_owner);
out_calldata: out_calldata:
kfree(calldata); kfree(calldata);
nfs_put_client(clp);
goto out; goto out;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment