Re: [PROBLEM]: WARNING: lock held when returning to user space! (5.4.1 #16 Tainted: G )

From: Tadeusz Struk
Date: Mon Dec 09 2019 - 16:34:32 EST


On 12/9/19 12:25 PM, Jarkko Sakkinen wrote:
> On Mon, Dec 09, 2019 at 10:34:32AM +0000, Will Deacon wrote:
>> Hi,
>>
>> [expanding cc list]
>>
>> On Sat, Dec 07, 2019 at 11:04:20PM +0530, Jeffrin Jose wrote:
>>> i got the following output related from typical dmesg output from 5.4.1 kernel
>>
>> Was this during boot or during some other operation?
>>
>>> ================================================
>>> WARNING: lock held when returning to user space!
>>> 5.4.1 #16 Tainted: G E
>>> ------------------------------------------------
>>> tpm2-abrmd/691 is leaving the kernel with locks still held!
>>> 2 locks held by tpm2-abrmd/691:
>>> #0: ffff8881ee784ba8 (&chip->ops_sem){.+.+}, at: tpm_try_get_ops+0x2b/0xc0 [tpm]
>>> #1: ffff8881ee784d88 (&chip->tpm_mutex){+.+.}, at: tpm_try_get_ops+0x57/0xc0 [tpm]
>>
>> Can you reproduce this failure on v5.5-rc1?
>
> Does this appear after variable amount of time or detemitically always
> at certain point of time (e.g. when the daemon starts or perhaps always
> when doing a certain operations with TSS)?
>
> Do we have possibility to get the user code path that gets executed when
> this happens?

I think that's expected for a non-blocking operation.
To get rid of the warning it should be changed to something like this:

diff --git a/drivers/char/tpm/tpm-dev-common.c
b/drivers/char/tpm/tpm-dev-common.c
index 2ec47a69a2a6..47f1c0c5c8de 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);
}
@@ -205,6 +212,7 @@ ssize_t tpm_common_write(struct file *file, const
char __user *buf,
priv->command_enqueued = true;
queue_work(tpm_dev_wq, &priv->async_work);
mutex_unlock(&priv->buffer_mutex);
+ tpm_put_ops(priv->chip);
return size;
}



--
Tadeusz