Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e911b815 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

NFSv4: Fix a use-after-free problem in open()



If we interrupt the nfs4_wait_for_completion_rpc_task() call in
nfs4_run_open_task(), then we don't prevent the RPC call from
completing. So freeing up the opendata->f_attr.mdsthreshold
in the error path in _nfs4_do_open() leads to a use-after-free
when the XDR decoder tries to decode the mdsthreshold information
from the server.

Fixes: 82be417a (NFSv4.1 cache mdsthreshold values on OPEN)
Tested-by: default avatarSteve Dickson <SteveD@redhat.com>
Cc: stable@vger.kernel.org # 3.5+
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
parent 494314c4
Loading
Loading
Loading
Loading
+10 −9
Original line number Diff line number Diff line
@@ -1068,6 +1068,7 @@ static void nfs4_opendata_free(struct kref *kref)
	dput(p->dentry);
	nfs_sb_deactive(sb);
	nfs_fattr_free_names(&p->f_attr);
	kfree(p->f_attr.mdsthreshold);
	kfree(p);
}

@@ -2304,10 +2305,12 @@ static int _nfs4_do_open(struct inode *dir,
		}
	}

	if (ctx_th && server->attr_bitmask[2] & FATTR4_WORD2_MDSTHRESHOLD) {
	if (server->attr_bitmask[2] & FATTR4_WORD2_MDSTHRESHOLD) {
		if (!opendata->f_attr.mdsthreshold) {
			opendata->f_attr.mdsthreshold = pnfs_mdsthreshold_alloc();
			if (!opendata->f_attr.mdsthreshold)
				goto err_free_label;
		}
		opendata->o_arg.open_bitmap = &nfs4_pnfs_open_bitmap[0];
	}
	if (dentry->d_inode != NULL)
@@ -2335,11 +2338,10 @@ static int _nfs4_do_open(struct inode *dir,
	if (opendata->file_created)
		*opened |= FILE_CREATED;

	if (pnfs_use_threshold(ctx_th, opendata->f_attr.mdsthreshold, server))
	if (pnfs_use_threshold(ctx_th, opendata->f_attr.mdsthreshold, server)) {
		*ctx_th = opendata->f_attr.mdsthreshold;
	else
		kfree(opendata->f_attr.mdsthreshold);
		opendata->f_attr.mdsthreshold = NULL;
	}

	nfs4_label_free(olabel);

@@ -2349,7 +2351,6 @@ static int _nfs4_do_open(struct inode *dir,
err_free_label:
	nfs4_label_free(olabel);
err_opendata_put:
	kfree(opendata->f_attr.mdsthreshold);
	nfs4_opendata_put(opendata);
err_put_state_owner:
	nfs4_put_state_owner(sp);