From: Greg Kroah-Hartman Date: Mon, 4 Dec 2017 14:02:15 +0000 (+0100) Subject: 4.4-stable patches X-Git-Tag: v3.18.86~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c66c3e3e32314fefe7283f96f2fa16b36308c68f;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: drm-i915-don-t-try-indexed-reads-to-alternate-slave-addresses.patch drm-i915-prevent-zero-length-index-write.patch nfsd-fix-another-open-stateid-race.patch nfsd-fix-stateid-races-between-open-and-close.patch nfsd-make-init_open_stateid-a-bit-more-whole.patch --- diff --git a/queue-4.4/drm-i915-don-t-try-indexed-reads-to-alternate-slave-addresses.patch b/queue-4.4/drm-i915-don-t-try-indexed-reads-to-alternate-slave-addresses.patch new file mode 100644 index 00000000000..8f911042f0b --- /dev/null +++ b/queue-4.4/drm-i915-don-t-try-indexed-reads-to-alternate-slave-addresses.patch @@ -0,0 +1,42 @@ +From ae5c631e605a452a5a0e73205a92810c01ed954b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= +Date: Thu, 23 Nov 2017 21:41:56 +0200 +Subject: drm/i915: Don't try indexed reads to alternate slave addresses +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ville Syrjälä + +commit ae5c631e605a452a5a0e73205a92810c01ed954b upstream. + +We can only specify the one slave address to indexed reads/writes. +Make sure the messages we check are destined to the same slave +address before deciding to do an indexed transfer. + +Cc: Daniel Kurtz +Cc: Chris Wilson +Cc: Daniel Vetter +Cc: Sean Paul +Fixes: 56f9eac05489 ("drm/i915/intel_i2c: use INDEX cycles for i2c read transactions") +Signed-off-by: Ville Syrjälä +Link: https://patchwork.freedesktop.org/patch/msgid/20171123194157.25367-2-ville.syrjala@linux.intel.com +Reviewed-by: Chris Wilson +(cherry picked from commit c4deb62d7821672265b87952bcd1c808f3bf3e8f) +Signed-off-by: Joonas Lahtinen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/intel_i2c.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/gpu/drm/i915/intel_i2c.c ++++ b/drivers/gpu/drm/i915/intel_i2c.c +@@ -440,6 +440,7 @@ static bool + gmbus_is_index_read(struct i2c_msg *msgs, int i, int num) + { + return (i + 1 < num && ++ msgs[i].addr == msgs[i + 1].addr && + !(msgs[i].flags & I2C_M_RD) && msgs[i].len <= 2 && + (msgs[i + 1].flags & I2C_M_RD)); + } diff --git a/queue-4.4/drm-i915-prevent-zero-length-index-write.patch b/queue-4.4/drm-i915-prevent-zero-length-index-write.patch new file mode 100644 index 00000000000..8917e61651e --- /dev/null +++ b/queue-4.4/drm-i915-prevent-zero-length-index-write.patch @@ -0,0 +1,44 @@ +From 56350fb8978bbf4aafe08f21234e161dd128b417 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= +Date: Thu, 23 Nov 2017 21:41:57 +0200 +Subject: drm/i915: Prevent zero length "index" write +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ville Syrjälä + +commit 56350fb8978bbf4aafe08f21234e161dd128b417 upstream. + +The hardware always writes one or two bytes in the index portion of +an indexed transfer. Make sure the message we send as the index +doesn't have a zero length. + +Cc: Daniel Kurtz +Cc: Chris Wilson +Cc: Daniel Vetter +Cc: Sean Paul +Fixes: 56f9eac05489 ("drm/i915/intel_i2c: use INDEX cycles for i2c read transactions") +Signed-off-by: Ville Syrjälä +Link: https://patchwork.freedesktop.org/patch/msgid/20171123194157.25367-3-ville.syrjala@linux.intel.com +Reviewed-by: Chris Wilson +(cherry picked from commit bb9e0d4bca50f429152e74a459160b41f3d60fb2) +Signed-off-by: Joonas Lahtinen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/intel_i2c.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/i915/intel_i2c.c ++++ b/drivers/gpu/drm/i915/intel_i2c.c +@@ -441,7 +441,8 @@ gmbus_is_index_read(struct i2c_msg *msgs + { + return (i + 1 < num && + msgs[i].addr == msgs[i + 1].addr && +- !(msgs[i].flags & I2C_M_RD) && msgs[i].len <= 2 && ++ !(msgs[i].flags & I2C_M_RD) && ++ (msgs[i].len == 1 || msgs[i].len == 2) && + (msgs[i + 1].flags & I2C_M_RD)); + } + diff --git a/queue-4.4/nfsd-fix-another-open-stateid-race.patch b/queue-4.4/nfsd-fix-another-open-stateid-race.patch new file mode 100644 index 00000000000..97d4ab4d5c3 --- /dev/null +++ b/queue-4.4/nfsd-fix-another-open-stateid-race.patch @@ -0,0 +1,91 @@ +From d8a1a000555ecd1b824ac1ed6df8fe364dfbbbb0 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Fri, 3 Nov 2017 08:00:11 -0400 +Subject: nfsd: Fix another OPEN stateid race + +From: Trond Myklebust + +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. + +Reported-by: Andrew W Elble +Signed-off-by: Trond Myklebust +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfsd/nfs4state.c | 28 +++++++++++++--------------- + 1 file changed, 13 insertions(+), 15 deletions(-) + +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -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); + diff --git a/queue-4.4/nfsd-fix-stateid-races-between-open-and-close.patch b/queue-4.4/nfsd-fix-stateid-races-between-open-and-close.patch new file mode 100644 index 00000000000..fd7174c2d69 --- /dev/null +++ b/queue-4.4/nfsd-fix-stateid-races-between-open-and-close.patch @@ -0,0 +1,153 @@ +From 15ca08d3299682dc49bad73251677b2c5017ef08 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Fri, 3 Nov 2017 08:00:10 -0400 +Subject: nfsd: Fix stateid races between OPEN and CLOSE + +From: Trond Myklebust + +commit 15ca08d3299682dc49bad73251677b2c5017ef08 upstream. + +Open file stateids can linger on the nfs4_file list of stateids even +after they have been closed. In order to avoid reusing such a +stateid, and confusing the client, we need to recheck the +nfs4_stid's type after taking the mutex. +Otherwise, we risk reusing an old stateid that was already closed, +which will confuse clients that expect new stateids to conform to +RFC7530 Sections 9.1.4.2 and 16.2.5 or RFC5661 Sections 8.2.2 and 18.2.4. + +Signed-off-by: Trond Myklebust +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfsd/nfs4state.c | 67 +++++++++++++++++++++++++++++++++++++++++++++------- + 1 file changed, 59 insertions(+), 8 deletions(-) + +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -3379,7 +3379,9 @@ nfsd4_find_existing_open(struct nfs4_fil + /* ignore lock owners */ + if (local->st_stateowner->so_is_open_owner == 0) + continue; +- if (local->st_stateowner == &oo->oo_owner) { ++ if (local->st_stateowner != &oo->oo_owner) ++ continue; ++ if (local->st_stid.sc_type == NFS4_OPEN_STID) { + ret = local; + atomic_inc(&ret->st_stid.sc_count); + break; +@@ -3388,6 +3390,52 @@ nfsd4_find_existing_open(struct nfs4_fil + return ret; + } + ++static __be32 ++nfsd4_verify_open_stid(struct nfs4_stid *s) ++{ ++ __be32 ret = nfs_ok; ++ ++ switch (s->sc_type) { ++ default: ++ break; ++ case NFS4_CLOSED_STID: ++ case NFS4_CLOSED_DELEG_STID: ++ ret = nfserr_bad_stateid; ++ break; ++ case NFS4_REVOKED_DELEG_STID: ++ ret = nfserr_deleg_revoked; ++ } ++ return ret; ++} ++ ++/* Lock the stateid st_mutex, and deal with races with CLOSE */ ++static __be32 ++nfsd4_lock_ol_stateid(struct nfs4_ol_stateid *stp) ++{ ++ __be32 ret; ++ ++ mutex_lock(&stp->st_mutex); ++ ret = nfsd4_verify_open_stid(&stp->st_stid); ++ if (ret != nfs_ok) ++ mutex_unlock(&stp->st_mutex); ++ return ret; ++} ++ ++static struct nfs4_ol_stateid * ++nfsd4_find_and_lock_existing_open(struct nfs4_file *fp, struct nfsd4_open *open) ++{ ++ struct nfs4_ol_stateid *stp; ++ for (;;) { ++ spin_lock(&fp->fi_lock); ++ stp = nfsd4_find_existing_open(fp, open); ++ spin_unlock(&fp->fi_lock); ++ if (!stp || nfsd4_lock_ol_stateid(stp) == nfs_ok) ++ break; ++ nfs4_put_stid(&stp->st_stid); ++ } ++ return stp; ++} ++ + static struct nfs4_openowner * + alloc_init_open_stateowner(unsigned int strhashval, struct nfsd4_open *open, + struct nfsd4_compound_state *cstate) +@@ -3432,6 +3480,7 @@ init_open_stateid(struct nfs4_file *fp, + mutex_init(&stp->st_mutex); + mutex_lock(&stp->st_mutex); + ++retry: + spin_lock(&oo->oo_owner.so_client->cl_lock); + spin_lock(&fp->fi_lock); + +@@ -3456,7 +3505,11 @@ out_unlock: + spin_unlock(&fp->fi_lock); + spin_unlock(&oo->oo_owner.so_client->cl_lock); + if (retstp) { +- mutex_lock(&retstp->st_mutex); ++ /* Handle races with CLOSE */ ++ if (nfsd4_lock_ol_stateid(retstp) != nfs_ok) { ++ nfs4_put_stid(&retstp->st_stid); ++ goto retry; ++ } + /* To keep mutex tracking happy */ + mutex_unlock(&stp->st_mutex); + stp = retstp; +@@ -4277,9 +4330,7 @@ nfsd4_process_open2(struct svc_rqst *rqs + status = nfs4_check_deleg(cl, open, &dp); + if (status) + goto out; +- spin_lock(&fp->fi_lock); +- stp = nfsd4_find_existing_open(fp, open); +- spin_unlock(&fp->fi_lock); ++ stp = nfsd4_find_and_lock_existing_open(fp, open); + } else { + open->op_file = NULL; + status = nfserr_bad_stateid; +@@ -4293,7 +4344,6 @@ nfsd4_process_open2(struct svc_rqst *rqs + */ + if (stp) { + /* Stateid was found, this is an OPEN upgrade */ +- mutex_lock(&stp->st_mutex); + status = nfs4_upgrade_open(rqstp, fp, current_fh, stp, open); + if (status) { + mutex_unlock(&stp->st_mutex); +@@ -5150,7 +5200,6 @@ static void nfsd4_close_open_stateid(str + bool unhashed; + LIST_HEAD(reaplist); + +- s->st_stid.sc_type = NFS4_CLOSED_STID; + spin_lock(&clp->cl_lock); + unhashed = unhash_open_stateid(s, &reaplist); + +@@ -5189,10 +5238,12 @@ nfsd4_close(struct svc_rqst *rqstp, stru + nfsd4_bump_seqid(cstate, status); + if (status) + goto out; ++ ++ stp->st_stid.sc_type = NFS4_CLOSED_STID; + nfs4_inc_and_copy_stateid(&close->cl_stateid, &stp->st_stid); +- mutex_unlock(&stp->st_mutex); + + nfsd4_close_open_stateid(stp); ++ mutex_unlock(&stp->st_mutex); + + /* put reference from nfs4_preprocess_seqid_op */ + nfs4_put_stid(&stp->st_stid); diff --git a/queue-4.4/nfsd-make-init_open_stateid-a-bit-more-whole.patch b/queue-4.4/nfsd-make-init_open_stateid-a-bit-more-whole.patch new file mode 100644 index 00000000000..18047b9e3e2 --- /dev/null +++ b/queue-4.4/nfsd-make-init_open_stateid-a-bit-more-whole.patch @@ -0,0 +1,92 @@ +From 8c7245abda877d4689b3371db8ae2a4400d7d9ce Mon Sep 17 00:00:00 2001 +From: Oleg Drokin +Date: Tue, 14 Jun 2016 23:28:06 -0400 +Subject: nfsd: Make init_open_stateid() a bit more whole + +From: Oleg Drokin + +commit 8c7245abda877d4689b3371db8ae2a4400d7d9ce upstream. + +Move the state selection logic inside from the caller, +always making it return correct stp to use. + +Signed-off-by: J . Bruce Fields +Signed-off-by: Oleg Drokin +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfsd/nfs4state.c | 27 ++++++++++++--------------- + 1 file changed, 12 insertions(+), 15 deletions(-) + +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -3420,13 +3420,14 @@ alloc_init_open_stateowner(unsigned int + } + + static struct nfs4_ol_stateid * +-init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp, +- struct nfsd4_open *open) ++init_open_stateid(struct nfs4_file *fp, struct nfsd4_open *open) + { + + struct nfs4_openowner *oo = open->op_openowner; + struct nfs4_ol_stateid *retstp = NULL; ++ struct nfs4_ol_stateid *stp; + ++ stp = open->op_stp; + /* We are moving these outside of the spinlocks to avoid the warnings */ + mutex_init(&stp->st_mutex); + mutex_lock(&stp->st_mutex); +@@ -3437,6 +3438,8 @@ init_open_stateid(struct nfs4_ol_stateid + retstp = nfsd4_find_existing_open(fp, open); + if (retstp) + goto out_unlock; ++ ++ open->op_stp = NULL; + atomic_inc(&stp->st_stid.sc_count); + stp->st_stid.sc_type = NFS4_OPEN_STID; + INIT_LIST_HEAD(&stp->st_locks); +@@ -3454,10 +3457,11 @@ out_unlock: + spin_unlock(&oo->oo_owner.so_client->cl_lock); + if (retstp) { + mutex_lock(&retstp->st_mutex); +- /* Not that we need to, just for neatness */ ++ /* To keep mutex tracking happy */ + mutex_unlock(&stp->st_mutex); ++ stp = retstp; + } +- return retstp; ++ return stp; + } + + /* +@@ -4260,7 +4264,6 @@ nfsd4_process_open2(struct svc_rqst *rqs + struct nfs4_client *cl = open->op_openowner->oo_owner.so_client; + struct nfs4_file *fp = NULL; + struct nfs4_ol_stateid *stp = NULL; +- struct nfs4_ol_stateid *swapstp = NULL; + struct nfs4_delegation *dp = NULL; + __be32 status; + +@@ -4297,16 +4300,10 @@ nfsd4_process_open2(struct svc_rqst *rqs + goto out; + } + } else { +- stp = open->op_stp; +- open->op_stp = NULL; +- /* +- * init_open_stateid() either returns a locked stateid +- * it found, or initializes and locks the new one we passed in +- */ +- swapstp = init_open_stateid(stp, fp, open); +- if (swapstp) { +- nfs4_put_stid(&stp->st_stid); +- stp = swapstp; ++ /* 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) { diff --git a/queue-4.4/series b/queue-4.4/series index be27457e1da..e4924214f13 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -20,3 +20,8 @@ drm-radeon-fix-atombios-on-big-endian.patch drm-panel-simple-add-missing-panel_simple_unprepare-calls.patch mtd-nand-fix-writing-mtdoops-to-nand-flash.patch nfs-revalidate-.-etc-correctly-on-open.patch +drm-i915-don-t-try-indexed-reads-to-alternate-slave-addresses.patch +drm-i915-prevent-zero-length-index-write.patch +nfsd-make-init_open_stateid-a-bit-more-whole.patch +nfsd-fix-stateid-races-between-open-and-close.patch +nfsd-fix-another-open-stateid-race.patch