Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Olga Kornievskaia and committed by
Anna Schumaker
63513232 05fae7bb

+4 -5
+4 -5
fs/nfs/nfs4proc.c
··· 7425 7425 struct nfs41_exchange_id_data *cdata = 7426 7426 (struct nfs41_exchange_id_data *)data; 7427 7427 7428 - nfs_put_client(cdata->args.client); 7429 7428 if (cdata->xprt) { 7430 7429 xprt_put(cdata->xprt); 7431 7430 rpc_clnt_xprt_switch_put(cdata->args.client->cl_rpcclient); 7432 7431 } 7432 + nfs_put_client(cdata->args.client); 7433 7433 kfree(cdata->res.impl_id); 7434 7434 kfree(cdata->res.server_scope); 7435 7435 kfree(cdata->res.server_owner); ··· 7536 7536 task_setup_data.callback_data = calldata; 7537 7537 7538 7538 task = rpc_run_task(&task_setup_data); 7539 - if (IS_ERR(task)) { 7540 - status = PTR_ERR(task); 7541 - goto out_impl_id; 7542 - } 7539 + if (IS_ERR(task)) 7540 + return PTR_ERR(task); 7543 7541 7544 7542 if (!xprt) { 7545 7543 status = rpc_wait_for_completion_task(task); ··· 7565 7567 kfree(calldata->res.server_owner); 7566 7568 out_calldata: 7567 7569 kfree(calldata); 7570 + nfs_put_client(clp); 7568 7571 goto out; 7569 7572 } 7570 7573