Browse Source

NFSv4: Fix memory corruption in nfs4_proc_open_confirm

nfs41_wake_and_assign_slot() relies on the task->tk_msg.rpc_argp and
task->tk_msg.rpc_resp always pointing to the session sequence arguments.

nfs4_proc_open_confirm tries to pull a fast one by reusing the open
sequence structure, thus causing corruption of the NFSv4 slot table.

Cc: stable@vger.kernel.org # 3.12+
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Trond Myklebust 11 years ago
parent
commit
17ead6c85c
2 changed files with 6 additions and 4 deletions
  1. 4 4
      fs/nfs/nfs4proc.c
  2. 2 0
      include/linux/nfs_xdr.h

+ 4 - 4
fs/nfs/nfs4proc.c

@@ -1620,15 +1620,15 @@ static void nfs4_open_confirm_prepare(struct rpc_task *task, void *calldata)
 {
 {
 	struct nfs4_opendata *data = calldata;
 	struct nfs4_opendata *data = calldata;
 
 
-	nfs40_setup_sequence(data->o_arg.server, &data->o_arg.seq_args,
-				&data->o_res.seq_res, task);
+	nfs40_setup_sequence(data->o_arg.server, &data->c_arg.seq_args,
+				&data->c_res.seq_res, task);
 }
 }
 
 
 static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
 static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
 {
 {
 	struct nfs4_opendata *data = calldata;
 	struct nfs4_opendata *data = calldata;
 
 
-	nfs40_sequence_done(task, &data->o_res.seq_res);
+	nfs40_sequence_done(task, &data->c_res.seq_res);
 
 
 	data->rpc_status = task->tk_status;
 	data->rpc_status = task->tk_status;
 	if (data->rpc_status == 0) {
 	if (data->rpc_status == 0) {
@@ -1686,7 +1686,7 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
 	};
 	};
 	int status;
 	int status;
 
 
-	nfs4_init_sequence(&data->o_arg.seq_args, &data->o_res.seq_res, 1);
+	nfs4_init_sequence(&data->c_arg.seq_args, &data->c_res.seq_res, 1);
 	kref_get(&data->kref);
 	kref_get(&data->kref);
 	data->rpc_done = 0;
 	data->rpc_done = 0;
 	data->rpc_status = 0;
 	data->rpc_status = 0;

+ 2 - 0
include/linux/nfs_xdr.h

@@ -379,12 +379,14 @@ struct nfs_openres {
  * Arguments to the open_confirm call.
  * Arguments to the open_confirm call.
  */
  */
 struct nfs_open_confirmargs {
 struct nfs_open_confirmargs {
+	struct nfs4_sequence_args	seq_args;
 	const struct nfs_fh *	fh;
 	const struct nfs_fh *	fh;
 	nfs4_stateid *		stateid;
 	nfs4_stateid *		stateid;
 	struct nfs_seqid *	seqid;
 	struct nfs_seqid *	seqid;
 };
 };
 
 
 struct nfs_open_confirmres {
 struct nfs_open_confirmres {
+	struct nfs4_sequence_res	seq_res;
 	nfs4_stateid            stateid;
 	nfs4_stateid            stateid;
 	struct nfs_seqid *	seqid;
 	struct nfs_seqid *	seqid;
 };
 };