Message ID | 155302749437.13955.651380639754310898.stgit@tstruk-mobl1.jf.intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v2] tpm: fix an invalid condition in tpm_common_poll | expand |
On Tue, 2019-03-19 at 13:31 -0700, Tadeusz Struk wrote: > The poll condition should only check response_length, > because reads should only be issued if there is data to read. > The response_read flag only prevents double writes. > The problem was that the write set the response_read to false, > enqued a tpm job, and returned. Then application called poll > which checked the response_read flag and returned EPOLLIN. > Then the application called read, but got nothing. > After all that the async_work kicked in. > Added also mutex_lock around the poll check to prevent > other possible race conditions. > > Fixes: 9488585b21bef0df12 ("tpm: add support for partial reads") > Reported-by: Mantas Mikulėnas <grawity@gmail.com> > Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com> > --- > drivers/char/tpm/tpm-dev-common.c | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) > > diff --git a/drivers/char/tpm/tpm-dev-common.c > b/drivers/char/tpm/tpm-dev-common.c > index 5eecad233ea1..7312d3214381 100644 > --- a/drivers/char/tpm/tpm-dev-common.c > +++ b/drivers/char/tpm/tpm-dev-common.c > @@ -203,12 +203,14 @@ __poll_t tpm_common_poll(struct file *file, > poll_table *wait) > __poll_t mask = 0; > > poll_wait(file, &priv->async_wait, wait); > + mutex_lock(&priv->buffer_mutex); > > - if (!priv->response_read || priv->response_length) > + if (priv->response_length) > mask = EPOLLIN | EPOLLRDNORM; > else > mask = EPOLLOUT | EPOLLWRNORM; > > + mutex_unlock(&priv->buffer_mutex); Just an observation on this: the mutex is now no-longer necessary because a read on a size_t quantity is always atomic. James
On 3/20/19 7:30 AM, James Bottomley wrote: > Just an observation on this: the mutex is now no-longer necessary > because a read on a size_t quantity is always atomic. True, that's why it wasn't there at the beginning, but then things changed and I forgot to add it, so let's put it there just in case. Thanks,
On Tue, Mar 19, 2019 at 10:31 PM Tadeusz Struk <tadeusz.struk@intel.com> wrote: > > The poll condition should only check response_length, > because reads should only be issued if there is data to read. > The response_read flag only prevents double writes. > The problem was that the write set the response_read to false, > enqued a tpm job, and returned. Then application called poll > which checked the response_read flag and returned EPOLLIN. > Then the application called read, but got nothing. > After all that the async_work kicked in. > Added also mutex_lock around the poll check to prevent > other possible race conditions. > > Fixes: 9488585b21bef0df12 ("tpm: add support for partial reads") > Reported-by: Mantas Mikulėnas <grawity@gmail.com> > Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com> > --- > drivers/char/tpm/tpm-dev-common.c | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) > > diff --git a/drivers/char/tpm/tpm-dev-common.c b/drivers/char/tpm/tpm-dev-common.c > index 5eecad233ea1..7312d3214381 100644 > --- a/drivers/char/tpm/tpm-dev-common.c > +++ b/drivers/char/tpm/tpm-dev-common.c > @@ -203,12 +203,14 @@ __poll_t tpm_common_poll(struct file *file, poll_table *wait) > __poll_t mask = 0; > > poll_wait(file, &priv->async_wait, wait); > + mutex_lock(&priv->buffer_mutex); > > - if (!priv->response_read || priv->response_length) > + if (priv->response_length) > mask = EPOLLIN | EPOLLRDNORM; > else > mask = EPOLLOUT | EPOLLWRNORM; > > + mutex_unlock(&priv->buffer_mutex); > return mask; > } Thanks, this patch seems to work, and I apologize for not responding to test the patches earlier. Any chance it'll be submitted for stable 5.0.x as well?
On 3/20/19 11:51 AM, Mantas Mikulėnas wrote: > Thanks, this patch seems to work, and I apologize for not responding > to test the patches earlier. Thanks for testing. > > Any chance it'll be submitted for stable 5.0.x as well? Yes, it's a regression. I included the "Fixes" tag so it should be applied to all affected versions. In this case it's 5.0 only. Thanks,
On Tue, Mar 19, 2019 at 01:31:34PM -0700, Tadeusz Struk wrote: > The poll condition should only check response_length, > because reads should only be issued if there is data to read. > The response_read flag only prevents double writes. > The problem was that the write set the response_read to false, > enqued a tpm job, and returned. Then application called poll > which checked the response_read flag and returned EPOLLIN. > Then the application called read, but got nothing. > After all that the async_work kicked in. > Added also mutex_lock around the poll check to prevent > other possible race conditions. > > Fixes: 9488585b21bef0df12 ("tpm: add support for partial reads") > Reported-by: Mantas Mikulėnas <grawity@gmail.com> > Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com> Can you send v3 with the comment and cc to stable? Then this should be fine. /Jarkko
On Wed, Mar 20, 2019 at 12:18:42PM -0700, Tadeusz Struk wrote: > On 3/20/19 11:51 AM, Mantas Mikulėnas wrote: > > Thanks, this patch seems to work, and I apologize for not responding > > to test the patches earlier. > > Thanks for testing. > > > > > Any chance it'll be submitted for stable 5.0.x as well? > > Yes, it's a regression. I included the "Fixes" tag so > it should be applied to all affected versions. > In this case it's 5.0 only. > Thanks, > -- > Tadeusz Add a tested-by for the next version. /Jarkko
diff --git a/drivers/char/tpm/tpm-dev-common.c b/drivers/char/tpm/tpm-dev-common.c index 5eecad233ea1..7312d3214381 100644 --- a/drivers/char/tpm/tpm-dev-common.c +++ b/drivers/char/tpm/tpm-dev-common.c @@ -203,12 +203,14 @@ __poll_t tpm_common_poll(struct file *file, poll_table *wait) __poll_t mask = 0; poll_wait(file, &priv->async_wait, wait); + mutex_lock(&priv->buffer_mutex); - if (!priv->response_read || priv->response_length) + if (priv->response_length) mask = EPOLLIN | EPOLLRDNORM; else mask = EPOLLOUT | EPOLLWRNORM; + mutex_unlock(&priv->buffer_mutex); return mask; }
The poll condition should only check response_length, because reads should only be issued if there is data to read. The response_read flag only prevents double writes. The problem was that the write set the response_read to false, enqued a tpm job, and returned. Then application called poll which checked the response_read flag and returned EPOLLIN. Then the application called read, but got nothing. After all that the async_work kicked in. Added also mutex_lock around the poll check to prevent other possible race conditions. Fixes: 9488585b21bef0df12 ("tpm: add support for partial reads") Reported-by: Mantas Mikulėnas <grawity@gmail.com> Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com> --- drivers/char/tpm/tpm-dev-common.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)