Message ID | 1590539114.3576.5.camel@HansenPartnership.com (mailing list archive) |
---|---|
State | Rejected, archived |
Headers | show |
Series | tpm2: fix TIS locality timeout problems | expand |
> -----Original Message----- > From: James Bottomley <James.Bottomley@HansenPartnership.com> > Sent: Tuesday, May 26, 2020 7:25 PM > To: linux-integrity@vger.kernel.org > Cc: Jarkko Sakkinen; Jason Gunthorpe; Limonciello, Mario; Alex Guzman > Subject: [PATCH] tpm2: fix TIS locality timeout problems > > > [EXTERNAL EMAIL] > > It has been reported that some TIS based TPMs are giving unexpected > errors when using the O_NONBLOCK path. The problem is that some TPMs > don't like it when you get and then relinquish a locality (as the > tpm_try_get_ops/tpm_put_ops pair does) without sending a command. > This currently happens all the time in the O_NONBLOCK write path. We > can fix this by moving the tpm_try_get_ops further down the code to > after the O_NONBLOCK determination is made. This is safe because the > priv->buffer_mutex still protects the priv state being modified. > > Fixes: d23d12484307 ("tpm: fix invalid locking in NONBLOCKING mode") > Reported-by: Mario Limonciello <Mario.Limonciello@dell.com> > Tested-by: Alex Guzman <alex@guzman.io> > Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com> A few other notes for right here: * You should probably mention this buglink: BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=206275 * And add another Reported-by: For Alex probably makes sense , as he is the original reporter to the bug. I just helped to bring it here. * This should CC stable (as this regression managed to hit the stable kernels too). > --- > drivers/char/tpm/tpm-dev-common.c | 19 +++++++++---------- > 1 file changed, 9 insertions(+), 10 deletions(-) > > diff --git a/drivers/char/tpm/tpm-dev-common.c b/drivers/char/tpm/tpm-dev- > common.c > index 87f449340202..1784530b8387 100644 > --- a/drivers/char/tpm/tpm-dev-common.c > +++ b/drivers/char/tpm/tpm-dev-common.c > @@ -189,15 +189,6 @@ ssize_t tpm_common_write(struct file *file, const char > __user *buf, > goto out; > } > > - /* atomic tpm command send and result receive. We only hold the ops > - * lock during this period so that the tpm can be unregistered even if > - * the char dev is held open. > - */ > - if (tpm_try_get_ops(priv->chip)) { > - ret = -EPIPE; > - goto out; > - } > - > priv->response_length = 0; > priv->response_read = false; > *off = 0; > @@ -211,11 +202,19 @@ ssize_t tpm_common_write(struct file *file, const char > __user *buf, > if (file->f_flags & O_NONBLOCK) { > priv->command_enqueued = true; > queue_work(tpm_dev_wq, &priv->async_work); > - tpm_put_ops(priv->chip); > mutex_unlock(&priv->buffer_mutex); > return size; > } > > + /* atomic tpm command send and result receive. We only hold the ops > + * lock during this period so that the tpm can be unregistered even if > + * the char dev is held open. > + */ > + if (tpm_try_get_ops(priv->chip)) { > + ret = -EPIPE; > + goto out; > + } > + > ret = tpm_dev_transmit(priv->chip, priv->space, priv->data_buffer, > sizeof(priv->data_buffer)); > tpm_put_ops(priv->chip); > -- > 2.26.2
On Tue May 26 20, James Bottomley wrote: >It has been reported that some TIS based TPMs are giving unexpected >errors when using the O_NONBLOCK path. The problem is that some TPMs >don't like it when you get and then relinquish a locality (as the >tpm_try_get_ops/tpm_put_ops pair does) without sending a command. >This currently happens all the time in the O_NONBLOCK write path. We >can fix this by moving the tpm_try_get_ops further down the code to >after the O_NONBLOCK determination is made. This is safe because the >priv->buffer_mutex still protects the priv state being modified. > >Fixes: d23d12484307 ("tpm: fix invalid locking in NONBLOCKING mode") >Reported-by: Mario Limonciello <Mario.Limonciello@dell.com> >Tested-by: Alex Guzman <alex@guzman.io> >Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com> Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com>
On Tue, May 26, 2020 at 05:25:14PM -0700, James Bottomley wrote: > It has been reported that some TIS based TPMs are giving unexpected > errors when using the O_NONBLOCK path. The problem is that some TPMs > don't like it when you get and then relinquish a locality (as the > tpm_try_get_ops/tpm_put_ops pair does) without sending a command. > This currently happens all the time in the O_NONBLOCK write path. We > can fix this by moving the tpm_try_get_ops further down the code to > after the O_NONBLOCK determination is made. This is safe because the > priv->buffer_mutex still protects the priv state being modified. > > Fixes: d23d12484307 ("tpm: fix invalid locking in NONBLOCKING mode") > Reported-by: Mario Limonciello <Mario.Limonciello@dell.com> > Tested-by: Alex Guzman <alex@guzman.io> > Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com> Subsystem tag is wrong, function name is missing '()' after and sometimes there are spaces after ".". Please fix the commit message and I can look at the code when it is clean. /Jarkko
diff --git a/drivers/char/tpm/tpm-dev-common.c b/drivers/char/tpm/tpm-dev-common.c index 87f449340202..1784530b8387 100644 --- a/drivers/char/tpm/tpm-dev-common.c +++ b/drivers/char/tpm/tpm-dev-common.c @@ -189,15 +189,6 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf, goto out; } - /* atomic tpm command send and result receive. We only hold the ops - * lock during this period so that the tpm can be unregistered even if - * the char dev is held open. - */ - if (tpm_try_get_ops(priv->chip)) { - ret = -EPIPE; - goto out; - } - priv->response_length = 0; priv->response_read = false; *off = 0; @@ -211,11 +202,19 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf, if (file->f_flags & O_NONBLOCK) { priv->command_enqueued = true; queue_work(tpm_dev_wq, &priv->async_work); - tpm_put_ops(priv->chip); mutex_unlock(&priv->buffer_mutex); return size; } + /* atomic tpm command send and result receive. We only hold the ops + * lock during this period so that the tpm can be unregistered even if + * the char dev is held open. + */ + if (tpm_try_get_ops(priv->chip)) { + ret = -EPIPE; + goto out; + } + ret = tpm_dev_transmit(priv->chip, priv->space, priv->data_buffer, sizeof(priv->data_buffer)); tpm_put_ops(priv->chip);