summary refs log tree commit diff
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2010-09-21 16:52:40 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-09-21 16:52:40 -0400
commitf7732d6573c4f29fc1ca5d384bbf82ddfa115030 (patch)
treee0f94b8406908e4e3081afa436a2aa8eed06773d
parentd3d4152a5d59af9e13a73efa9e9c24383fbe307f (diff)
downloadlinux-f7732d6573c4f29fc1ca5d384bbf82ddfa115030.tar.gz
NFS: Fix a use-after-free case in nfs_async_rename()
The call to nfs_async_rename_release() after rpc_run_task() is incorrect.
The rpc_run_task() is always guaranteed to call the ->rpc_release() method.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/unlink.c9
1 files changed, 2 insertions, 7 deletions
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 698b3e6367ff..47530aacebfd 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -426,7 +426,6 @@ nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
 		.rpc_client = NFS_CLIENT(old_dir),
 		.flags = RPC_TASK_ASYNC,
 	};
-	struct rpc_task *task;
 
 	data = kmalloc(sizeof(*data), GFP_KERNEL);
 	if (data == NULL)
@@ -435,7 +434,7 @@ nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
 
 	data->cred = rpc_lookup_cred();
 	if (IS_ERR(data->cred)) {
-		task = (struct rpc_task *)data->cred;
+		struct rpc_task *task = ERR_CAST(data->cred);
 		kfree(data);
 		return task;
 	}
@@ -468,11 +467,7 @@ nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
 
 	NFS_PROTO(data->old_dir)->rename_setup(&msg, old_dir);
 
-	task = rpc_run_task(&task_setup_data);
-	if (IS_ERR(task))
-		nfs_async_rename_release(data);
-
-	return task;
+	return rpc_run_task(&task_setup_data);
 }
 
 /**