<gregkh@xxxxxxxxxxxxxxxxxxx> writes: > The patch below does not apply to the 4.4-stable tree. > If someone wants it applied there, or to any other stable or longterm > tree, then please email the backport, including the original git commit > id to <stable@xxxxxxxxxxxxxxx>. > > thanks, > > greg k-h Greg, These backport cleanly if you cherry-pick 8c7245abda first: commit 8c7245abda877d4689b3371db8ae2a4400d7d9ce then commit 15ca08d3299682dc49bad73251677b2c5017ef08 then commit d8a1a000555ecd1b824ac1ed6df8fe364dfbbbb0 Thanks, Andy > > ------------------ original commit in Linus's tree ------------------ > >>From d8a1a000555ecd1b824ac1ed6df8fe364dfbbbb0 Mon Sep 17 00:00:00 2001 > From: Trond Myklebust <trond.myklebust@xxxxxxxxxxxxxxx> > Date: Fri, 3 Nov 2017 08:00:11 -0400 > Subject: [PATCH] nfsd: Fix another OPEN stateid race > > 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. > > Reported-by: Andrew W Elble <aweits@xxxxxxx> > Signed-off-by: Trond Myklebust <trond.myklebust@xxxxxxxxxxxxxxx> > Cc: stable@xxxxxxxxxxxxxxx > Signed-off-by: J. Bruce Fields <bfields@xxxxxxxxxx> > > diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c > index ee8fde2dfa92..457f0e7ece74 100644 > --- a/fs/nfsd/nfs4state.c > +++ b/fs/nfsd/nfs4state.c > @@ -4502,6 +4502,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf > 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, > @@ -4521,11 +4522,19 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf > 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) { > @@ -4533,22 +4542,11 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf > 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; > } > > @@ -4557,7 +4555,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf > 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); > > -- Andrew W. Elble aweits@xxxxxxxxxxxxxxxxxx Infrastructure Engineer, Communications Technical Lead Rochester Institute of Technology PGP: BFAD 8461 4CCF DC95 DA2C B0EB 965B 082E 863E C912