Skip to contentSkip to conversation

Patch "nfsd: Fix another OPEN stateid race" has been added to the 4.4-stable tree

PATCH [email protected] 1 participant 1 message Dec 4, 2017

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

nfsd: Fix another OPEN stateid race

to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
nfsd-fix-another-open-stateid-race.patch
and it can be found in the queue-4.4 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

Quoted 1 line

From d8a1a000555ecd1b824ac1ed6df8fe364dfbbbb0 Mon Sep 17 00:00:00 2001

From: Trond Myklebust <[email protected]>
Date: Fri, 3 Nov 2017 08:00:11 -0400
Subject: nfsd: Fix another OPEN stateid race

From: Trond Myklebust <[email protected]>

commit d8a1a000555ecd1b824ac1ed6df8fe364dfbbbb0 upstream.

If nfsd4_process_open2() is initialising a new stateid, and yet the call to nfs4_get_vfs_file() fails for some reason, then we must declare the stateid closed, and unhash it before dropping the mutex.

Right now, we unhash the stateid after dropping the mutex, and without changing the stateid type, meaning that another OPEN could theoretically look it up and attempt to use it.

---
 fs/nfsd/nfs4state.c |   28 +++++++++++++---------------
 1 file changed, 13 insertions(+), 15 deletions(-)
fs/nfsd/nfs4state.c +13 -15
@@ -4319,6 +4319,7 @@ nfsd4_process_open2(struct svc_rqst *rqs
 	struct nfs4_ol_stateid *stp = NULL;
 	struct nfs4_delegation *dp = NULL;
 	__be32 status;
+	bool new_stp = false;
 
 	/*
 	 * Lookup file; if found, lookup stateid and check open request,
@@ -4338,11 +4339,19 @@ nfsd4_process_open2(struct svc_rqst *rqs
 			goto out;
 	}
 
+	if (!stp) {
+		stp = init_open_stateid(fp, open);
+		if (!open->op_stp)
+			new_stp = true;
+	}
+
 	/*
 	 * OPEN the file, or upgrade an existing OPEN.
 	 * If truncate fails, the OPEN fails.
+	 *
+	 * stp is already locked.
 	 */
-	if (stp) {
+	if (!new_stp) {
 		/* Stateid was found, this is an OPEN upgrade */
 		status = nfs4_upgrade_open(rqstp, fp, current_fh, stp, open);
 		if (status) {
@@ -4350,22 +4359,11 @@ nfsd4_process_open2(struct svc_rqst *rqs
 			goto out;
 		}
 	} else {
-		/* stp is returned locked. */
-		stp = init_open_stateid(fp, open);
-		/* See if we lost the race to some other thread */
-		if (stp->st_access_bmap != 0) {
-			status = nfs4_upgrade_open(rqstp, fp, current_fh,
-						stp, open);
-			if (status) {
-				mutex_unlock(&stp->st_mutex);
-				goto out;
-			}
-			goto upgrade_out;
-		}
 		status = nfs4_get_vfs_file(rqstp, fp, current_fh, stp, open);
 		if (status) {
-			mutex_unlock(&stp->st_mutex);
+			stp->st_stid.sc_type = NFS4_CLOSED_STID;
 			release_open_stateid(stp);
+			mutex_unlock(&stp->st_mutex);
 			goto out;
 		}
 
@@ -4374,7 +4372,7 @@ nfsd4_process_open2(struct svc_rqst *rqs
 		if (stp->st_clnt_odstate == open->op_odstate)
 			open->op_odstate = NULL;
 	}
-upgrade_out:
+
 	nfs4_inc_and_copy_stateid(&open->op_stateid, &stp->st_stid);
 	mutex_unlock(&stp->st_mutex);
 

Patches currently in stable-queue which might be from [email protected] are

queue-4.4/nfsd-fix-stateid-races-between-open-and-close.patch queue-4.4/nfsd-fix-another-open-stateid-race.patch