aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlga Kornievskaia <kolga@netapp.com>2017-03-13 10:36:19 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-03-26 07:05:57 -0400
commitb76d4fb2d9445e29f003308607c65b882b117b26 (patch)
treea280e8b1890ec4f353a83f23e6e19567bbf36956
parent87144ec25091a516c1674494bd95f8966a480eec (diff)
NFS prevent double free in async nfs4_exchange_id
commit 63513232f8cd219dcaa5eafae028740ed3067d83 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: 8d89bd70bc9 ("NFS setup async exchange_id") Signed-off-by: Olga Kornievskaia <kolga@netapp.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/nfs/nfs4proc.c9
1 files changed, 4 insertions, 5 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 609840de31d3..1536aeb0abab 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -7426,11 +7426,11 @@ static void nfs4_exchange_id_release(void *data)
7426 struct nfs41_exchange_id_data *cdata = 7426 struct nfs41_exchange_id_data *cdata =
7427 (struct nfs41_exchange_id_data *)data; 7427 (struct nfs41_exchange_id_data *)data;
7428 7428
7429 nfs_put_client(cdata->args.client);
7430 if (cdata->xprt) { 7429 if (cdata->xprt) {
7431 xprt_put(cdata->xprt); 7430 xprt_put(cdata->xprt);
7432 rpc_clnt_xprt_switch_put(cdata->args.client->cl_rpcclient); 7431 rpc_clnt_xprt_switch_put(cdata->args.client->cl_rpcclient);
7433 } 7432 }
7433 nfs_put_client(cdata->args.client);
7434 kfree(cdata->res.impl_id); 7434 kfree(cdata->res.impl_id);
7435 kfree(cdata->res.server_scope); 7435 kfree(cdata->res.server_scope);
7436 kfree(cdata->res.server_owner); 7436 kfree(cdata->res.server_owner);
@@ -7537,10 +7537,8 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
7537 task_setup_data.callback_data = calldata; 7537 task_setup_data.callback_data = calldata;
7538 7538
7539 task = rpc_run_task(&task_setup_data); 7539 task = rpc_run_task(&task_setup_data);
7540 if (IS_ERR(task)) { 7540 if (IS_ERR(task))
7541 status = PTR_ERR(task); 7541 return PTR_ERR(task);
7542 goto out_impl_id;
7543 }
7544 7542
7545 if (!xprt) { 7543 if (!xprt) {
7546 status = rpc_wait_for_completion_task(task); 7544 status = rpc_wait_for_completion_task(task);
@@ -7568,6 +7566,7 @@ out_server_owner:
7568 kfree(calldata->res.server_owner); 7566 kfree(calldata->res.server_owner);
7569out_calldata: 7567out_calldata:
7570 kfree(calldata); 7568 kfree(calldata);
7569 nfs_put_client(clp);
7571 goto out; 7570 goto out;
7572} 7571}
7573 7572