summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorOlga Kornievskaia <kolga@netapp.com>2017-03-13 10:36:19 -0400
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2017-03-17 16:06:27 -0400
commit63513232f8cd219dcaa5eafae028740ed3067d83 (patch)
treefda9dadd14db7d82029fd036a8a97d223aea3755 /fs
parent05fae7bbc237bc7de0ee9c3dcf85b2572a80e3b5 (diff)
downloadlinux-63513232f8cd219dcaa5eafae028740ed3067d83.tar.gz
linux-63513232f8cd219dcaa5eafae028740ed3067d83.tar.bz2
linux-63513232f8cd219dcaa5eafae028740ed3067d83.zip
NFS prevent double free in async nfs4_exchange_id
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> Cc: stable@vger.kernel.org # 4.9 Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Diffstat (limited to 'fs')
-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 c1f5369cd339..c780d98035cc 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -7425,11 +7425,11 @@ static void nfs4_exchange_id_release(void *data)
struct nfs41_exchange_id_data *cdata =
(struct nfs41_exchange_id_data *)data;
- nfs_put_client(cdata->args.client);
if (cdata->xprt) {
xprt_put(cdata->xprt);
rpc_clnt_xprt_switch_put(cdata->args.client->cl_rpcclient);
}
+ nfs_put_client(cdata->args.client);
kfree(cdata->res.impl_id);
kfree(cdata->res.server_scope);
kfree(cdata->res.server_owner);
@@ -7536,10 +7536,8 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
task_setup_data.callback_data = calldata;
task = rpc_run_task(&task_setup_data);
- if (IS_ERR(task)) {
- status = PTR_ERR(task);
- goto out_impl_id;
- }
+ if (IS_ERR(task))
+ return PTR_ERR(task);
if (!xprt) {
status = rpc_wait_for_completion_task(task);
@@ -7567,6 +7565,7 @@ out_server_owner:
kfree(calldata->res.server_owner);
out_calldata:
kfree(calldata);
+ nfs_put_client(clp);
goto out;
}