| From cafbdce0bbe75ba4f32a417bd28c26773b02598c Mon Sep 17 00:00:00 2001 |
| From: Tadeusz Struk <tadeusz.struk@intel.com> |
| Date: Thu, 12 Dec 2019 09:48:47 -0800 |
| Subject: [PATCH] tpm: fix invalid locking in NONBLOCKING mode |
| |
| commit d23d12484307b40eea549b8a858f5fffad913897 upstream. |
| |
| When an application sends TPM commands in NONBLOCKING mode |
| the driver holds chip->tpm_mutex returning from write(), |
| which triggers: "WARNING: lock held when returning to user space". |
| To fix this issue the driver needs to release the mutex before |
| returning and acquire it again in tpm_dev_async_work() before |
| sending the command. |
| |
| Cc: stable@vger.kernel.org |
| Fixes: 9e1b74a63f776 (tpm: add support for nonblocking operation) |
| Reported-by: Jeffrin Jose T <jeffrin@rajagiritech.edu.in> |
| Tested-by: Jeffrin Jose T <jeffrin@rajagiritech.edu.in> |
| Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com> |
| Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> |
| Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/char/tpm/tpm-dev-common.c b/drivers/char/tpm/tpm-dev-common.c |
| index 2ec47a69a2a6..b23b0b999232 100644 |
| --- a/drivers/char/tpm/tpm-dev-common.c |
| +++ b/drivers/char/tpm/tpm-dev-common.c |
| @@ -61,6 +61,12 @@ static void tpm_dev_async_work(struct work_struct *work) |
| |
| mutex_lock(&priv->buffer_mutex); |
| priv->command_enqueued = false; |
| + ret = tpm_try_get_ops(priv->chip); |
| + if (ret) { |
| + priv->response_length = ret; |
| + goto out; |
| + } |
| + |
| ret = tpm_dev_transmit(priv->chip, priv->space, priv->data_buffer, |
| sizeof(priv->data_buffer)); |
| tpm_put_ops(priv->chip); |
| @@ -68,6 +74,7 @@ static void tpm_dev_async_work(struct work_struct *work) |
| priv->response_length = ret; |
| mod_timer(&priv->user_read_timer, jiffies + (120 * HZ)); |
| } |
| +out: |
| mutex_unlock(&priv->buffer_mutex); |
| wake_up_interruptible(&priv->async_wait); |
| } |
| @@ -204,6 +211,7 @@ 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; |
| } |
| -- |
| 2.7.4 |
| |