diff mbox

[v2,1/4] tpm: Implement tpm_chip_find() and tpm_chip_put() for other subsystems

Message ID 20180620204236.1572523-2-stefanb@linux.vnet.ibm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Stefan Berger June 20, 2018, 8:42 p.m. UTC
Implement tpm_chip_find() for other subsystems to find a TPM chip and
get a reference to that chip. Once done with using the chip, the reference
is released using tpm_chip_put().

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
---
 drivers/char/tpm/tpm-chip.c | 37 +++++++++++++++++++++++++++++++++++++
 include/linux/tpm.h         |  9 +++++++++
 2 files changed, 46 insertions(+)

Comments

Jason Gunthorpe June 20, 2018, 8:50 p.m. UTC | #1
On Wed, Jun 20, 2018 at 04:42:33PM -0400, Stefan Berger wrote:
> Implement tpm_chip_find() for other subsystems to find a TPM chip and
> get a reference to that chip. Once done with using the chip, the reference
> is released using tpm_chip_put().
> 
> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
>  drivers/char/tpm/tpm-chip.c | 37 +++++++++++++++++++++++++++++++++++++
>  include/linux/tpm.h         |  9 +++++++++
>  2 files changed, 46 insertions(+)
> 
> diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
> index 0a62c19937b6..eaaf41ce73d8 100644
> +++ b/drivers/char/tpm/tpm-chip.c
> @@ -81,6 +81,43 @@ void tpm_put_ops(struct tpm_chip *chip)
>  EXPORT_SYMBOL_GPL(tpm_put_ops);
>  
>  /**
> + * tpm_chip_put() - Release a ref to the tpm_chip
> + * @chip: Chip to put
> + */
> +void tpm_chip_put(struct tpm_chip *chip)
> +{
> +	if (chip)
> +		put_device(&chip->dev);

Rarely like to see those if's inside a put function.. Does it actually
help anything?

Jason
Stefan Berger June 20, 2018, 9:13 p.m. UTC | #2
On 06/20/2018 04:50 PM, Jason Gunthorpe wrote:
> On Wed, Jun 20, 2018 at 04:42:33PM -0400, Stefan Berger wrote:
>> Implement tpm_chip_find() for other subsystems to find a TPM chip and
>> get a reference to that chip. Once done with using the chip, the reference
>> is released using tpm_chip_put().
>>
>> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
>>   drivers/char/tpm/tpm-chip.c | 37 +++++++++++++++++++++++++++++++++++++
>>   include/linux/tpm.h         |  9 +++++++++
>>   2 files changed, 46 insertions(+)
>>
>> diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
>> index 0a62c19937b6..eaaf41ce73d8 100644
>> +++ b/drivers/char/tpm/tpm-chip.c
>> @@ -81,6 +81,43 @@ void tpm_put_ops(struct tpm_chip *chip)
>>   EXPORT_SYMBOL_GPL(tpm_put_ops);
>>   
>>   /**
>> + * tpm_chip_put() - Release a ref to the tpm_chip
>> + * @chip: Chip to put
>> + */
>> +void tpm_chip_put(struct tpm_chip *chip)
>> +{
>> +	if (chip)
>> +		put_device(&chip->dev);
> Rarely like to see those if's inside a put function.. Does it actually
> help anything?
Following put_device() 'pattern' here which also checks using 'if (dev)'.

     Stefan
Jarkko Sakkinen June 21, 2018, 5:13 p.m. UTC | #3
On Wed, Jun 20, 2018 at 02:50:04PM -0600, Jason Gunthorpe wrote:
> On Wed, Jun 20, 2018 at 04:42:33PM -0400, Stefan Berger wrote:
> > Implement tpm_chip_find() for other subsystems to find a TPM chip and
> > get a reference to that chip. Once done with using the chip, the reference
> > is released using tpm_chip_put().
> > 
> > Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
> >  drivers/char/tpm/tpm-chip.c | 37 +++++++++++++++++++++++++++++++++++++
> >  include/linux/tpm.h         |  9 +++++++++
> >  2 files changed, 46 insertions(+)
> > 
> > diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
> > index 0a62c19937b6..eaaf41ce73d8 100644
> > +++ b/drivers/char/tpm/tpm-chip.c
> > @@ -81,6 +81,43 @@ void tpm_put_ops(struct tpm_chip *chip)
> >  EXPORT_SYMBOL_GPL(tpm_put_ops);
> >  
> >  /**
> > + * tpm_chip_put() - Release a ref to the tpm_chip
> > + * @chip: Chip to put
> > + */
> > +void tpm_chip_put(struct tpm_chip *chip)
> > +{
> > +	if (chip)
> > +		put_device(&chip->dev);
> 
> Rarely like to see those if's inside a put function.. Does it actually
> help anything?
> 
> Jason

The check only helps to hidden regressions here...

/Jarkko
Jarkko Sakkinen June 21, 2018, 5:15 p.m. UTC | #4
On Wed, Jun 20, 2018 at 04:42:33PM -0400, Stefan Berger wrote:
> Implement tpm_chip_find() for other subsystems to find a TPM chip and
> get a reference to that chip. Once done with using the chip, the reference
> is released using tpm_chip_put().
> 
> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>

You should sort this out in a way that we don't end up with duplicate
functions.

/Jarkko
Stefan Berger June 21, 2018, 5:27 p.m. UTC | #5
On 06/21/2018 01:15 PM, Jarkko Sakkinen wrote:
> On Wed, Jun 20, 2018 at 04:42:33PM -0400, Stefan Berger wrote:
>> Implement tpm_chip_find() for other subsystems to find a TPM chip and
>> get a reference to that chip. Once done with using the chip, the reference
>> is released using tpm_chip_put().
>>
>> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
> You should sort this out in a way that we don't end up with duplicate
> functions.

We cannot hold the ops_sem semaphore for a long time. So we need a 
function that gets us a reference and doesn't hold the ops semaphore and 
that's where this tpm_chip_find() comes from.

    Stefan

> /Jarkko
>
Stefan Berger June 21, 2018, 5:45 p.m. UTC | #6
On 06/21/2018 01:15 PM, Jarkko Sakkinen wrote:
> On Wed, Jun 20, 2018 at 04:42:33PM -0400, Stefan Berger wrote:
>> Implement tpm_chip_find() for other subsystems to find a TPM chip and
>> get a reference to that chip. Once done with using the chip, the reference
>> is released using tpm_chip_put().
>>
>> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
> You should sort this out in a way that we don't end up with duplicate
> functions.

Do you want me to create a function *like* tpm_chip_find_get() that 
takes an additional parameter whether to get the ops semaphore and have 
that function called by the existing tpm_chip_find_get() and the new 
tpm_chip_find(). The latter would then not get the ops semphore. I 
didn't want to do this since one time the function returns with a lock 
held and the other time not.

   Stefan

>
> /Jarkko
>
Jason Gunthorpe June 21, 2018, 5:56 p.m. UTC | #7
On Thu, Jun 21, 2018 at 01:45:03PM -0400, Stefan Berger wrote:
> On 06/21/2018 01:15 PM, Jarkko Sakkinen wrote:
> >On Wed, Jun 20, 2018 at 04:42:33PM -0400, Stefan Berger wrote:
> >>Implement tpm_chip_find() for other subsystems to find a TPM chip and
> >>get a reference to that chip. Once done with using the chip, the reference
> >>is released using tpm_chip_put().
> >>
> >>Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
> >You should sort this out in a way that we don't end up with duplicate
> >functions.
> 
> Do you want me to create a function *like* tpm_chip_find_get() that takes an
> additional parameter whether to get the ops semaphore and have that function
> called by the existing tpm_chip_find_get() and the new tpm_chip_find(). The
> latter would then not get the ops semphore. I didn't want to do this since
> one time the function returns with a lock held and the other time not.

Another option, and I haven't looked, is to revise the callers of
tpm_chip_find_get to not require it to hold the ops semaphore for
them.

Either by giving them an API to do it, or revising the TPM entry
points to do it.

I didn't look, but how did the ops semaphore get grabbed in your
revised patches? They do grab it, right?

Jason
Stefan Berger June 21, 2018, 6:19 p.m. UTC | #8
On 06/21/2018 01:56 PM, Jason Gunthorpe wrote:
> On Thu, Jun 21, 2018 at 01:45:03PM -0400, Stefan Berger wrote:
>> On 06/21/2018 01:15 PM, Jarkko Sakkinen wrote:
>>> On Wed, Jun 20, 2018 at 04:42:33PM -0400, Stefan Berger wrote:
>>>> Implement tpm_chip_find() for other subsystems to find a TPM chip and
>>>> get a reference to that chip. Once done with using the chip, the reference
>>>> is released using tpm_chip_put().
>>>>
>>>> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
>>> You should sort this out in a way that we don't end up with duplicate
>>> functions.
>> Do you want me to create a function *like* tpm_chip_find_get() that takes an
>> additional parameter whether to get the ops semaphore and have that function
>> called by the existing tpm_chip_find_get() and the new tpm_chip_find(). The
>> latter would then not get the ops semphore. I didn't want to do this since
>> one time the function returns with a lock held and the other time not.
> Another option, and I haven't looked, is to revise the callers of
> tpm_chip_find_get to not require it to hold the ops semaphore for
> them.

We have tpm_chip_unregister calling tpm_del_char_device to set the ops 
to NULL once a chip is unregistered. All existing callers, if they pass 
in a tpm_chip != NULL, currently fail if the ops are NULL. (If they pass 
in tpm_chip = NULL, they shouldn't find a chip once ops are null and it 
has been removed from the IDR). I wouldn't change that since IMA will 
call in with a tpm_chip != NULL and we want to protect the ops. All 
existing code within the tpm subsystem does seem to call 
tpm_chip_find_get() with a NULL pointer, though. Also trusted keys seems 
to pass in a NULL pointer every time.

>
> Either by giving them an API to do it, or revising the TPM entry
> points to do it.
>
> I didn't look, but how did the ops semaphore get grabbed in your
> revised patches? They do grab it, right?

The revised patches do not touch the existing code much but will call 
tpm_chip_find_get() and get that semaphore every time before the ops are 
used. IMA is the only caller of tpm_chip_find() that now gets an 
additional reference to the tpm_chip and these APIs get called like this 
from IMA:

ima init: chip = tpm_chip_find()

ima::tpm: tpm_chip_find_get(chip) ... tpm_put_ops(chip)

ima::tpm: tpm_chip_find_get(chip) ... tpm_put_ops(chip)

[repeat]

ima shutdown: tpm_chip_put(chip)

     Stefan

>
> Jason
>
Jason Gunthorpe June 21, 2018, 7:06 p.m. UTC | #9
On Thu, Jun 21, 2018 at 02:19:44PM -0400, Stefan Berger wrote:
> On 06/21/2018 01:56 PM, Jason Gunthorpe wrote:
> >On Thu, Jun 21, 2018 at 01:45:03PM -0400, Stefan Berger wrote:
> >>On 06/21/2018 01:15 PM, Jarkko Sakkinen wrote:
> >>>On Wed, Jun 20, 2018 at 04:42:33PM -0400, Stefan Berger wrote:
> >>>>Implement tpm_chip_find() for other subsystems to find a TPM chip and
> >>>>get a reference to that chip. Once done with using the chip, the reference
> >>>>is released using tpm_chip_put().
> >>>>
> >>>>Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
> >>>You should sort this out in a way that we don't end up with duplicate
> >>>functions.
> >>Do you want me to create a function *like* tpm_chip_find_get() that takes an
> >>additional parameter whether to get the ops semaphore and have that function
> >>called by the existing tpm_chip_find_get() and the new tpm_chip_find(). The
> >>latter would then not get the ops semphore. I didn't want to do this since
> >>one time the function returns with a lock held and the other time not.
> >Another option, and I haven't looked, is to revise the callers of
> >tpm_chip_find_get to not require it to hold the ops semaphore for
> >them.
> 
> We have tpm_chip_unregister calling tpm_del_char_device to set the ops to
> NULL once a chip is unregistered. All existing callers, if they pass in a
> tpm_chip != NULL, currently fail if the ops are NULL. (If they pass in
> tpm_chip = NULL, they shouldn't find a chip once ops are null and it has
> been removed from the IDR). I wouldn't change that since IMA will call in
> with a tpm_chip != NULL and we want to protect the ops. All existing code
> within the tpm subsystem does seem to call tpm_chip_find_get() with a NULL
> pointer, though. Also trusted keys seems to pass in a NULL pointer every
> time.
> 
> >
> >Either by giving them an API to do it, or revising the TPM entry
> >points to do it.
> >
> >I didn't look, but how did the ops semaphore get grabbed in your
> >revised patches? They do grab it, right?
> 
> The revised patches do not touch the existing code much but will call
> tpm_chip_find_get() and get that semaphore every time before the ops are
> used. IMA is the only caller of tpm_chip_find() that now gets an additional
> reference to the tpm_chip and these APIs get called like this from IMA:
> 
> ima init: chip = tpm_chip_find()
> 
> ima::tpm: tpm_chip_find_get(chip) ... tpm_put_ops(chip)
> 
> ima::tpm: tpm_chip_find_get(chip) ... tpm_put_ops(chip)
> 
> [repeat]
> 
> ima shutdown: tpm_chip_put(chip)

Maybe just change tpm_chip_find_get() into tpm_get_ops(chip) and
convert all callers?

Jason
Stefan Berger June 21, 2018, 8:14 p.m. UTC | #10
On 06/21/2018 03:06 PM, Jason Gunthorpe wrote:
> On Thu, Jun 21, 2018 at 02:19:44PM -0400, Stefan Berger wrote:
>> On 06/21/2018 01:56 PM, Jason Gunthorpe wrote:
>>> On Thu, Jun 21, 2018 at 01:45:03PM -0400, Stefan Berger wrote:
>>>> On 06/21/2018 01:15 PM, Jarkko Sakkinen wrote:
>>>>> On Wed, Jun 20, 2018 at 04:42:33PM -0400, Stefan Berger wrote:
>>>>>> Implement tpm_chip_find() for other subsystems to find a TPM chip and
>>>>>> get a reference to that chip. Once done with using the chip, the reference
>>>>>> is released using tpm_chip_put().
>>>>>>
>>>>>> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
>>>>> You should sort this out in a way that we don't end up with duplicate
>>>>> functions.
>>>> Do you want me to create a function *like* tpm_chip_find_get() that takes an
>>>> additional parameter whether to get the ops semaphore and have that function
>>>> called by the existing tpm_chip_find_get() and the new tpm_chip_find(). The
>>>> latter would then not get the ops semphore. I didn't want to do this since
>>>> one time the function returns with a lock held and the other time not.
>>> Another option, and I haven't looked, is to revise the callers of
>>> tpm_chip_find_get to not require it to hold the ops semaphore for
>>> them.
>> We have tpm_chip_unregister calling tpm_del_char_device to set the ops to
>> NULL once a chip is unregistered. All existing callers, if they pass in a
>> tpm_chip != NULL, currently fail if the ops are NULL. (If they pass in
>> tpm_chip = NULL, they shouldn't find a chip once ops are null and it has
>> been removed from the IDR). I wouldn't change that since IMA will call in
>> with a tpm_chip != NULL and we want to protect the ops. All existing code
>> within the tpm subsystem does seem to call tpm_chip_find_get() with a NULL
>> pointer, though. Also trusted keys seems to pass in a NULL pointer every
>> time.
>>
>>> Either by giving them an API to do it, or revising the TPM entry
>>> points to do it.
>>>
>>> I didn't look, but how did the ops semaphore get grabbed in your
>>> revised patches? They do grab it, right?
>> The revised patches do not touch the existing code much but will call
>> tpm_chip_find_get() and get that semaphore every time before the ops are
>> used. IMA is the only caller of tpm_chip_find() that now gets an additional
>> reference to the tpm_chip and these APIs get called like this from IMA:
>>
>> ima init: chip = tpm_chip_find()
>>
>> ima::tpm: tpm_chip_find_get(chip) ... tpm_put_ops(chip)
>>
>> ima::tpm: tpm_chip_find_get(chip) ... tpm_put_ops(chip)
>>
>> [repeat]
>>
>> ima shutdown: tpm_chip_put(chip)
> Maybe just change tpm_chip_find_get() into tpm_get_ops(chip) and
> convert all callers?

And then re-introduce tpm_chip_find_get() for IMA to call ?
Jason Gunthorpe June 21, 2018, 8:51 p.m. UTC | #11
On Thu, Jun 21, 2018 at 04:14:46PM -0400, Stefan Berger wrote:
> On 06/21/2018 03:06 PM, Jason Gunthorpe wrote:
> >On Thu, Jun 21, 2018 at 02:19:44PM -0400, Stefan Berger wrote:
> >>On 06/21/2018 01:56 PM, Jason Gunthorpe wrote:
> >>>On Thu, Jun 21, 2018 at 01:45:03PM -0400, Stefan Berger wrote:
> >>>>On 06/21/2018 01:15 PM, Jarkko Sakkinen wrote:
> >>>>>On Wed, Jun 20, 2018 at 04:42:33PM -0400, Stefan Berger wrote:
> >>>>>>Implement tpm_chip_find() for other subsystems to find a TPM chip and
> >>>>>>get a reference to that chip. Once done with using the chip, the reference
> >>>>>>is released using tpm_chip_put().
> >>>>>>
> >>>>>>Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
> >>>>>You should sort this out in a way that we don't end up with duplicate
> >>>>>functions.
> >>>>Do you want me to create a function *like* tpm_chip_find_get() that takes an
> >>>>additional parameter whether to get the ops semaphore and have that function
> >>>>called by the existing tpm_chip_find_get() and the new tpm_chip_find(). The
> >>>>latter would then not get the ops semphore. I didn't want to do this since
> >>>>one time the function returns with a lock held and the other time not.
> >>>Another option, and I haven't looked, is to revise the callers of
> >>>tpm_chip_find_get to not require it to hold the ops semaphore for
> >>>them.
> >>We have tpm_chip_unregister calling tpm_del_char_device to set the ops to
> >>NULL once a chip is unregistered. All existing callers, if they pass in a
> >>tpm_chip != NULL, currently fail if the ops are NULL. (If they pass in
> >>tpm_chip = NULL, they shouldn't find a chip once ops are null and it has
> >>been removed from the IDR). I wouldn't change that since IMA will call in
> >>with a tpm_chip != NULL and we want to protect the ops. All existing code
> >>within the tpm subsystem does seem to call tpm_chip_find_get() with a NULL
> >>pointer, though. Also trusted keys seems to pass in a NULL pointer every
> >>time.
> >>
> >>>Either by giving them an API to do it, or revising the TPM entry
> >>>points to do it.
> >>>
> >>>I didn't look, but how did the ops semaphore get grabbed in your
> >>>revised patches? They do grab it, right?
> >>The revised patches do not touch the existing code much but will call
> >>tpm_chip_find_get() and get that semaphore every time before the ops are
> >>used. IMA is the only caller of tpm_chip_find() that now gets an additional
> >>reference to the tpm_chip and these APIs get called like this from IMA:
> >>
> >>ima init: chip = tpm_chip_find()
> >>
> >>ima::tpm: tpm_chip_find_get(chip) ... tpm_put_ops(chip)
> >>
> >>ima::tpm: tpm_chip_find_get(chip) ... tpm_put_ops(chip)
> >>
> >>[repeat]
> >>
> >>ima shutdown: tpm_chip_put(chip)
> >Maybe just change tpm_chip_find_get() into tpm_get_ops(chip) and
> >convert all callers?
> 
> And then re-introduce tpm_chip_find_get() for IMA to call ?

You could keep it as 'tpm_chip_find', that seems like a fine name to
me

Jason
diff mbox

Patch

diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 0a62c19937b6..eaaf41ce73d8 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -81,6 +81,43 @@  void tpm_put_ops(struct tpm_chip *chip)
 EXPORT_SYMBOL_GPL(tpm_put_ops);
 
 /**
+ * tpm_chip_put() - Release a ref to the tpm_chip
+ * @chip: Chip to put
+ */
+void tpm_chip_put(struct tpm_chip *chip)
+{
+	if (chip)
+		put_device(&chip->dev);
+}
+
+/**
+ * tpm_chip_find() - find a TPM chip and get a reference to it
+ */
+struct tpm_chip *tpm_chip_find(void)
+{
+	struct tpm_chip *chip, *res = NULL;
+	int chip_num = 0;
+	int chip_prev;
+
+	mutex_lock(&idr_lock);
+
+	do {
+		chip_prev = chip_num;
+		chip = idr_get_next(&dev_nums_idr, &chip_num);
+		if (chip) {
+			get_device(&chip->dev);
+			res = chip;
+			break;
+		}
+	} while (chip_prev != chip_num);
+
+	mutex_unlock(&idr_lock);
+
+	return res;
+}
+EXPORT_SYMBOL_GPL(tpm_chip_find);
+
+/**
  * tpm_chip_find_get() - find and reserve a TPM chip
  * @chip:	a &struct tpm_chip instance, %NULL for the default chip
  *
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index 06639fb6ab85..f0d1abcaf4af 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -61,6 +61,8 @@  extern int tpm_seal_trusted(struct tpm_chip *chip,
 extern int tpm_unseal_trusted(struct tpm_chip *chip,
 			      struct trusted_key_payload *payload,
 			      struct trusted_key_options *options);
+extern struct tpm_chip *tpm_chip_find(void);
+extern void tpm_chip_put(struct tpm_chip *chip);
 #else
 static inline int tpm_is_tpm2(struct tpm_chip *chip)
 {
@@ -96,5 +98,12 @@  static inline int tpm_unseal_trusted(struct tpm_chip *chip,
 {
 	return -ENODEV;
 }
+static inline struct tpm_chip *tpm_chip_find(void)
+{
+	return NULL;
+}
+static inline void tpm_chip_put(struct tpm_chip *chip)
+{
+}
 #endif
 #endif