diff options
author | Olga Kornievskaia <kolga@netapp.com> | 2017-03-13 10:36:19 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-03-26 07:05:57 -0400 |
commit | b76d4fb2d9445e29f003308607c65b882b117b26 (patch) | |
tree | a280e8b1890ec4f353a83f23e6e19567bbf36956 | |
parent | 87144ec25091a516c1674494bd95f8966a480eec (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.c | 9 |
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); |
7569 | out_calldata: | 7567 | out_calldata: |
7570 | kfree(calldata); | 7568 | kfree(calldata); |
7569 | nfs_put_client(clp); | ||
7571 | goto out; | 7570 | goto out; |
7572 | } | 7571 | } |
7573 | 7572 | ||