All of lore.kernel.org
 help / color / mirror / Atom feed
From: James Bottomley <James.Bottomley@HansenPartnership.com>
To: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Cc: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>,
	open list <linux-kernel@vger.kernel.org>,
	linux-security-module@vger.kernel.org,
	tpmdd-devel@lists.sourceforge.net
Subject: Re: [tpmdd-devel] [PATCH RFC v2 5/5] tpm2: expose resource manager via a device link /dev/tpms<n>
Date: Fri, 13 Jan 2017 17:10:30 -0800	[thread overview]
Message-ID: <1484356230.2527.76.camel@HansenPartnership.com> (raw)
In-Reply-To: <20170113212300.GA1463@obsidianresearch.com>

On Fri, 2017-01-13 at 14:23 -0700, Jason Gunthorpe wrote:
> On Fri, Jan 13, 2017 at 12:02:36PM -0800, James Bottomley wrote:
> > > > Actually, no, the devrm is a completely lifetime managed device 
> > > > as part of the chip structure.  once you've done a device_del 
> > > > on it, it can be kfreed because it's no longer visible to
> > > > anything else.
> > > 
> > > No, that isn't enough. Anything else could have obtained a kref 
> > > on devrm outside of the sphere the device_del manages.
> > > 
> > > For instance, the cdev does exactly that, via this:
> > > 
> > > >  	chip->cdev.kobj.parent = &chip->dev.kobj;
> > > > +	chip->cdevrm.kobj.parent = &chip->devrm.kobj;
> > > 
> > > In the worst case the kref the cdev grabs is not released until 
> > > after tpm_chip_unregister() returns.
> > 
> > chip_unregister doesn't tear down either device. It's the final
> > release of the chip->dev that does that.
> 
> I don't think you are seeing the problem.
> 
> I think you are assuming cdev_del waits for userspace to close any
> open fds. It does not.
> 
> Instead cdev independently holds on to a module lock and a kref on 
> the chip, once userspace has done close() then the kref is dropped 
> and the module lock let go. This can happen after chip_unregister, 
> after devm has done the final put_device, and after the driver core 
> has completed driver detach.
> 
> This is why it is necessary for this:
> 
>  +	chip->cdevrm.kobj.parent = &chip->devrm.kobj;
> 
> To point to a working kref, such as chip->dev.kobj.
> 
> My point is this patch has two very subtle bugs caused by devrm 
> having a broken kref. Yes we can fix those two cases, but this entire 
> class of bugs is prevented if devrm has a release function that does
> put_device(chip->dev).
> 
> We have no idea what will happen down the road; most poeple assume
> krefs *work*, having a struct with 4 krefs where only 3 work is 
> pretty wild, IMHO.
> 
> > Now there is a related problem that the owner is actually the 
> > *wrong* module: it holds the tpm module in place not the actual 
> > driver module, so I can happily attach tcsd to the TPM device then 
> > rmmod tpm_tis, which causes some interesting issues.  I can fix 
> > this, but it's not a problem of the current patch.
> 
> No, it is correct as is. The cdev fops rely only on the tpm module.
> When tpm_chip_unregister returns to the driver the chips->ops is set
> to NULL with proper locking - the driver code becomes uncallable at
> that point.

So that's the nastily subtle point I was missing.  The patch below will
add the reference tracking to make sure the chip is held while the
/dev/tpms<n> is open.  I really hate the additional layer of subtlety
this adds, though ... I've tried to document the extra nasties, but I
bet they confuse someone.

Doing it the standard way, where the owner is set to the pdev driver
module and the references all track up to the pdev, meaning the actual
device could never go away while a cdev file was open would be far
easier to understand.

James

---


diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 07d7607..338592c 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -132,6 +132,14 @@ static void tpm_dev_release(struct device *dev)
 	kfree(chip);
 }
 
+static void tpm_devrm_release(struct device *dev)
+{
+	struct tpm_chip *chip = container_of(dev, struct tpm_chip, devrm);
+
+	/* release the master device reference */
+	put_device(&chip->dev);
+}
+
 /**
  * tpm_chip_alloc() - allocate a new struct tpm_chip instance
  * @pdev: device to which the chip is associated
@@ -178,6 +186,12 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
 
 	chip->devrm.parent = pdev;
 	chip->devrm.class = tpm_rm_class;
+	chip->devrm.release = tpm_devrm_release;
+	/* get extra reference on main device to hold on
+	 * behalf of devrm.  This holds the chip structure
+	 * while cdevrm is in use.  The corresponding put
+	 * is in the tpm_devrm_release */
+	get_device(&chip->dev);
 
 	if (chip->dev_num == 0)
 		chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR);
@@ -207,6 +221,7 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
 	return chip;
 
 out:
+	put_device(&chip->devrm);
 	put_device(&chip->dev);
 	return ERR_PTR(rc);
 }
@@ -323,6 +338,9 @@ static void tpm_del_char_device(struct tpm_chip *chip)
 		tpm2_shutdown(chip, TPM2_SU_CLEAR);
 	chip->ops = NULL;
 	up_write(&chip->ops_sem);
+	/* will release the devrm reference to the chip->dev unless
+	 * something has cdevrm open */
+	put_device(&chip->devrm);
 }
 
 static void tpm_del_legacy_sysfs(struct tpm_chip *chip)

  reply	other threads:[~2017-01-14  1:10 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-12 17:46 [PATCH RFC v2 0/5] RFC: in-kernel resource manager Jarkko Sakkinen
2017-01-12 17:46 ` Jarkko Sakkinen
2017-01-12 17:46 ` [PATCH RFC v2 1/5] tpm: validate TPM 2.0 commands Jarkko Sakkinen
2017-01-12 17:46   ` Jarkko Sakkinen
2017-01-12 20:34   ` Jarkko Sakkinen
2017-01-12 17:46 ` [PATCH RFC v2 2/5] tpm: export tpm2_flush_context_cmd Jarkko Sakkinen
2017-01-12 17:46   ` Jarkko Sakkinen
2017-01-12 17:46 ` [PATCH RFC v2 3/5] tpm: infrastructure for TPM spaces Jarkko Sakkinen
2017-01-12 17:46   ` Jarkko Sakkinen
2017-01-12 18:38   ` [tpmdd-devel] " James Bottomley
2017-01-12 18:38     ` James Bottomley
2017-01-12 20:31     ` [tpmdd-devel] " Jarkko Sakkinen
2017-01-12 20:31       ` Jarkko Sakkinen
2017-01-12 20:38   ` [tpmdd-devel] " James Bottomley
2017-01-13 16:28     ` Jarkko Sakkinen
2017-01-14 17:53       ` Ken Goldman
2017-01-16  9:52         ` Jarkko Sakkinen
2017-01-16  9:52           ` Jarkko Sakkinen
2017-01-12 20:50   ` Jarkko Sakkinen
2017-01-12 20:50     ` Jarkko Sakkinen
2017-01-13  1:17   ` [tpmdd-devel] " James Bottomley
2017-01-13 16:31     ` Jarkko Sakkinen
2017-01-16  9:09     ` Jarkko Sakkinen
2017-01-16 14:24       ` James Bottomley
2017-01-16 14:48         ` Jarkko Sakkinen
2017-01-16 14:58           ` James Bottomley
2017-01-16 16:52             ` Jarkko Sakkinen
2017-01-12 17:46 ` [PATCH RFC v2 4/5] tpm: split out tpm-dev.c into tpm-dev.c and tpm-common-dev.c Jarkko Sakkinen
2017-01-12 17:46   ` Jarkko Sakkinen
2017-01-13 19:18   ` [tpmdd-devel] " James Bottomley
2017-01-12 17:46 ` [PATCH RFC v2 5/5] tpm2: expose resource manager via a device link /dev/tpms<n> Jarkko Sakkinen
2017-01-12 17:46   ` Jarkko Sakkinen
2017-01-12 18:39   ` Jason Gunthorpe
2017-01-12 18:39     ` Jason Gunthorpe
2017-01-13 19:20     ` [tpmdd-devel] " James Bottomley
2017-01-13 19:47       ` Jason Gunthorpe
2017-01-13 19:47         ` Jason Gunthorpe
2017-01-13 20:02         ` [tpmdd-devel] " James Bottomley
2017-01-13 20:02           ` James Bottomley
2017-01-13 21:23           ` [tpmdd-devel] " Jason Gunthorpe
2017-01-14  1:10             ` James Bottomley [this message]
2017-01-16 16:54               ` Jason Gunthorpe
2017-01-12 19:46   ` James Bottomley
2017-01-12 19:46     ` James Bottomley
2017-01-12 20:56   ` Jarkko Sakkinen
2017-01-13 17:25     ` Jason Gunthorpe
2017-01-13 17:40       ` [tpmdd-devel] " James Bottomley
2017-01-13 17:40         ` James Bottomley
2017-01-13 18:01         ` [tpmdd-devel] " Jason Gunthorpe
2017-01-13 18:11           ` James Bottomley
2017-01-16  9:45         ` Jarkko Sakkinen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1484356230.2527.76.camel@HansenPartnership.com \
    --to=james.bottomley@hansenpartnership.com \
    --cc=jarkko.sakkinen@linux.intel.com \
    --cc=jgunthorpe@obsidianresearch.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=tpmdd-devel@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.