All of lore.kernel.org
 help / color / mirror / Atom feed
From: jgunthorpe@obsidianresearch.com (Jason Gunthorpe)
To: linux-arm-kernel@lists.infradead.org
Subject: [tpmdd-devel] [RFC PATCH 1/2] tee: generic TEE subsystem
Date: Sat, 18 Apr 2015 11:29:23 -0600	[thread overview]
Message-ID: <20150418172923.GA10605@obsidianresearch.com> (raw)
In-Reply-To: <20150418090147.GF12732@n2100.arm.linux.org.uk>

On Sat, Apr 18, 2015 at 10:01:47AM +0100, Russell King - ARM Linux wrote:
> On Fri, Apr 17, 2015 at 10:30:54AM -0600, Jason Gunthorpe wrote:
> > On Fri, Apr 17, 2015 at 09:50:56AM +0200, Jens Wiklander wrote:
> > > +	teedev = devm_kzalloc(dev, sizeof(*teedev), GFP_KERNEL);
> > [..]
> > > +	rc = misc_register(&teedev->miscdev);
> > [..]
> > > +void tee_unregister(struct tee_device *teedev)
> > > +{
> > [..]
> > > +	misc_deregister(&teedev->miscdev);
> > > +}
> > [..]
> > >+static int optee_remove(struct platform_device *pdev)
> > >+{
> > >+       tee_unregister(optee->teedev);
> > 
> > Isn't that a potential use after free? AFAIK misc_deregister does not
> > guarentee the miscdev will no longer be accessed after it returns, and
> > the devm will free it after optee_remove returns.
> > 
> > Memory backing a stuct device needs to be freed via the release
> > function.
> 
> Out of interest, which struct device are you talking about here?

Sorry, I was imprecise. In the first paragraph I ment 'miscdev' to
refer to the entire thing, struct tee_device, struct misc_device, the
driver allocations, etc.

So, the first issue is the use-after-free via ioctl() touching struct
tee_device that you described.

But then we trundle down to:

+ ctx->teedev->desc->ops->get_version(ctx, &vers.spec_version,
+   vers.uuid);

If we kref teedev so it is valid then calling a driver call back after
(or during) it's remove function is very likely to blow up.

Also, in TPM we discovered that adding a sysfs file was very ugly
(impossible?) because without the misc_mtx protection that open has,
getting a locked tee_device in the sysfs callback is difficult.

With TPM, we ended up trying lots of options for fixing struct
misc_device in the tpm core, which is handling multiple sub drivers,
and basically gave up. Gave each struct tpm_device an embedded struct
device like Greg suggested here. Then the tpm core is working with the
APIs, not struggling against them.

But this is not a user-space invisible change, so better to do it right
from day 1 ..

We followed rtc as an example of how to create a mid-layer that
exports it's own register function, with char dev and sysfs
components. It seems properly implemented, and has elegant solutions
to these problems (like ops):
 - Don't mess with modules, use 'ops' and set 'ops' to null when the
   driver removes. The driver core will keep the driver module around
   for you bettwen the probe/remove calls. Setting ops = NULL ensures driver
   module code cannot be called after remove.
 - Use locking for 'ops' to serialize driver callbacks with driver removal
 - Embed a struct device/etc in the struct tee_device and use the release
   function to deallocate struct tee_device. All callbacks from the
   driver/char/sysfs core can now use container_of on something that
   is already holds the right kref.
 - Consider an alloc/register pattern as we use now in TPM. This has proven
   smart for TPM as it allows:
       alloc tee_device + init struct device, etc
       driver setup
       core library helper calls for setup/etc
       driver register + char dev publish

It appeared to me this driver was copying TPM's old architecture,
which is very much known to be broken.

Jason

WARNING: multiple messages have this Message-ID (diff)
From: Jason Gunthorpe <jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
To: Russell King - ARM Linux <linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org>
Cc: Jens Wiklander
	<jens.wiklander-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>,
	valentin.manea-hv44wF8Li93QT0dZR+AlfA@public.gmane.org,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	javier-5MUHepqpBA1BDgjK7y7TUQ@public.gmane.org,
	emmanuel.michel-qxv4g6HH51o@public.gmane.org,
	Herbert Xu
	<herbert-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q@public.gmane.org>,
	Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>,
	Greg Kroah-Hartman
	<gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	jean-michel.delorme-qxv4g6HH51o@public.gmane.org,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
Subject: Re: [tpmdd-devel] [RFC PATCH 1/2] tee: generic TEE subsystem
Date: Sat, 18 Apr 2015 11:29:23 -0600	[thread overview]
Message-ID: <20150418172923.GA10605@obsidianresearch.com> (raw)
In-Reply-To: <20150418090147.GF12732-l+eeeJia6m9vn6HldHNs0ANdhmdF6hFW@public.gmane.org>

On Sat, Apr 18, 2015 at 10:01:47AM +0100, Russell King - ARM Linux wrote:
> On Fri, Apr 17, 2015 at 10:30:54AM -0600, Jason Gunthorpe wrote:
> > On Fri, Apr 17, 2015 at 09:50:56AM +0200, Jens Wiklander wrote:
> > > +	teedev = devm_kzalloc(dev, sizeof(*teedev), GFP_KERNEL);
> > [..]
> > > +	rc = misc_register(&teedev->miscdev);
> > [..]
> > > +void tee_unregister(struct tee_device *teedev)
> > > +{
> > [..]
> > > +	misc_deregister(&teedev->miscdev);
> > > +}
> > [..]
> > >+static int optee_remove(struct platform_device *pdev)
> > >+{
> > >+       tee_unregister(optee->teedev);
> > 
> > Isn't that a potential use after free? AFAIK misc_deregister does not
> > guarentee the miscdev will no longer be accessed after it returns, and
> > the devm will free it after optee_remove returns.
> > 
> > Memory backing a stuct device needs to be freed via the release
> > function.
> 
> Out of interest, which struct device are you talking about here?

Sorry, I was imprecise. In the first paragraph I ment 'miscdev' to
refer to the entire thing, struct tee_device, struct misc_device, the
driver allocations, etc.

So, the first issue is the use-after-free via ioctl() touching struct
tee_device that you described.

But then we trundle down to:

+ ctx->teedev->desc->ops->get_version(ctx, &vers.spec_version,
+   vers.uuid);

If we kref teedev so it is valid then calling a driver call back after
(or during) it's remove function is very likely to blow up.

Also, in TPM we discovered that adding a sysfs file was very ugly
(impossible?) because without the misc_mtx protection that open has,
getting a locked tee_device in the sysfs callback is difficult.

With TPM, we ended up trying lots of options for fixing struct
misc_device in the tpm core, which is handling multiple sub drivers,
and basically gave up. Gave each struct tpm_device an embedded struct
device like Greg suggested here. Then the tpm core is working with the
APIs, not struggling against them.

But this is not a user-space invisible change, so better to do it right
from day 1 ..

We followed rtc as an example of how to create a mid-layer that
exports it's own register function, with char dev and sysfs
components. It seems properly implemented, and has elegant solutions
to these problems (like ops):
 - Don't mess with modules, use 'ops' and set 'ops' to null when the
   driver removes. The driver core will keep the driver module around
   for you bettwen the probe/remove calls. Setting ops = NULL ensures driver
   module code cannot be called after remove.
 - Use locking for 'ops' to serialize driver callbacks with driver removal
 - Embed a struct device/etc in the struct tee_device and use the release
   function to deallocate struct tee_device. All callbacks from the
   driver/char/sysfs core can now use container_of on something that
   is already holds the right kref.
 - Consider an alloc/register pattern as we use now in TPM. This has proven
   smart for TPM as it allows:
       alloc tee_device + init struct device, etc
       driver setup
       core library helper calls for setup/etc
       driver register + char dev publish

It appeared to me this driver was copying TPM's old architecture,
which is very much known to be broken.

Jason
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

WARNING: multiple messages have this Message-ID (diff)
From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
To: Russell King - ARM Linux <linux@arm.linux.org.uk>
Cc: Jens Wiklander <jens.wiklander@linaro.org>,
	valentin.manea@huawei.com, devicetree@vger.kernel.org,
	javier@javigon.com, emmanuel.michel@st.com,
	Herbert Xu <herbert@gondor.apana.org.au>,
	Arnd Bergmann <arnd@arndb.de>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	linux-kernel@vger.kernel.org, jean-michel.delorme@st.com,
	tpmdd-devel@lists.sourceforge.net,
	linux-arm-kernel@lists.infradead.org
Subject: Re: [tpmdd-devel] [RFC PATCH 1/2] tee: generic TEE subsystem
Date: Sat, 18 Apr 2015 11:29:23 -0600	[thread overview]
Message-ID: <20150418172923.GA10605@obsidianresearch.com> (raw)
In-Reply-To: <20150418090147.GF12732@n2100.arm.linux.org.uk>

On Sat, Apr 18, 2015 at 10:01:47AM +0100, Russell King - ARM Linux wrote:
> On Fri, Apr 17, 2015 at 10:30:54AM -0600, Jason Gunthorpe wrote:
> > On Fri, Apr 17, 2015 at 09:50:56AM +0200, Jens Wiklander wrote:
> > > +	teedev = devm_kzalloc(dev, sizeof(*teedev), GFP_KERNEL);
> > [..]
> > > +	rc = misc_register(&teedev->miscdev);
> > [..]
> > > +void tee_unregister(struct tee_device *teedev)
> > > +{
> > [..]
> > > +	misc_deregister(&teedev->miscdev);
> > > +}
> > [..]
> > >+static int optee_remove(struct platform_device *pdev)
> > >+{
> > >+       tee_unregister(optee->teedev);
> > 
> > Isn't that a potential use after free? AFAIK misc_deregister does not
> > guarentee the miscdev will no longer be accessed after it returns, and
> > the devm will free it after optee_remove returns.
> > 
> > Memory backing a stuct device needs to be freed via the release
> > function.
> 
> Out of interest, which struct device are you talking about here?

Sorry, I was imprecise. In the first paragraph I ment 'miscdev' to
refer to the entire thing, struct tee_device, struct misc_device, the
driver allocations, etc.

So, the first issue is the use-after-free via ioctl() touching struct
tee_device that you described.

But then we trundle down to:

+ ctx->teedev->desc->ops->get_version(ctx, &vers.spec_version,
+   vers.uuid);

If we kref teedev so it is valid then calling a driver call back after
(or during) it's remove function is very likely to blow up.

Also, in TPM we discovered that adding a sysfs file was very ugly
(impossible?) because without the misc_mtx protection that open has,
getting a locked tee_device in the sysfs callback is difficult.

With TPM, we ended up trying lots of options for fixing struct
misc_device in the tpm core, which is handling multiple sub drivers,
and basically gave up. Gave each struct tpm_device an embedded struct
device like Greg suggested here. Then the tpm core is working with the
APIs, not struggling against them.

But this is not a user-space invisible change, so better to do it right
from day 1 ..

We followed rtc as an example of how to create a mid-layer that
exports it's own register function, with char dev and sysfs
components. It seems properly implemented, and has elegant solutions
to these problems (like ops):
 - Don't mess with modules, use 'ops' and set 'ops' to null when the
   driver removes. The driver core will keep the driver module around
   for you bettwen the probe/remove calls. Setting ops = NULL ensures driver
   module code cannot be called after remove.
 - Use locking for 'ops' to serialize driver callbacks with driver removal
 - Embed a struct device/etc in the struct tee_device and use the release
   function to deallocate struct tee_device. All callbacks from the
   driver/char/sysfs core can now use container_of on something that
   is already holds the right kref.
 - Consider an alloc/register pattern as we use now in TPM. This has proven
   smart for TPM as it allows:
       alloc tee_device + init struct device, etc
       driver setup
       core library helper calls for setup/etc
       driver register + char dev publish

It appeared to me this driver was copying TPM's old architecture,
which is very much known to be broken.

Jason

  reply	other threads:[~2015-04-18 17:29 UTC|newest]

Thread overview: 85+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-04-17  7:50 [RFC PATCH 0/2] generic TEE subsystem Jens Wiklander
2015-04-17  7:50 ` Jens Wiklander
2015-04-17  7:50 ` Jens Wiklander
2015-04-17  7:50 ` [RFC PATCH 1/2] tee: " Jens Wiklander
2015-04-17  7:50   ` Jens Wiklander
2015-04-17  7:50   ` Jens Wiklander
2015-04-17 16:30   ` [tpmdd-devel] " Jason Gunthorpe
2015-04-17 16:30     ` Jason Gunthorpe
2015-04-18  9:01     ` Russell King - ARM Linux
2015-04-18  9:01       ` Russell King - ARM Linux
2015-04-18  9:01       ` Russell King - ARM Linux
2015-04-18 17:29       ` Jason Gunthorpe [this message]
2015-04-18 17:29         ` Jason Gunthorpe
2015-04-18 17:29         ` Jason Gunthorpe
2015-04-18 21:57         ` Russell King - ARM Linux
2015-04-18 21:57           ` Russell King - ARM Linux
2015-04-18 21:57           ` Russell King - ARM Linux
2015-04-20  5:08           ` Jason Gunthorpe
2015-04-20  5:08             ` Jason Gunthorpe
2015-04-20 14:54             ` Greg Kroah-Hartman
2015-04-20 14:54               ` Greg Kroah-Hartman
2015-04-20 15:56               ` Jason Gunthorpe
2015-04-20 15:56                 ` Jason Gunthorpe
2015-04-20 15:56                 ` Jason Gunthorpe
2015-04-20 16:05                 ` Greg Kroah-Hartman
2015-04-20 16:05                   ` Greg Kroah-Hartman
2015-04-20 16:05                   ` Greg Kroah-Hartman
2015-04-20 13:02         ` Jens Wiklander
2015-04-20 13:02           ` Jens Wiklander
2015-04-20 13:02           ` Jens Wiklander
2015-04-20 17:55           ` Jason Gunthorpe
2015-04-20 17:55             ` Jason Gunthorpe
2015-04-20 17:55             ` Jason Gunthorpe
2015-04-21  5:59             ` Jens Wiklander
2015-04-21  5:59               ` Jens Wiklander
2015-04-17 20:07   ` Arnd Bergmann
2015-04-17 20:07     ` Arnd Bergmann
2015-04-18  7:20     ` Paul Bolle
2015-04-18  7:20       ` Paul Bolle
2015-04-18  7:20       ` Paul Bolle
2015-04-20  6:20     ` Jens Wiklander
2015-04-20  6:20       ` Jens Wiklander
2015-04-20 18:20       ` [tpmdd-devel] " Jason Gunthorpe
2015-04-20 18:20         ` Jason Gunthorpe
2015-04-21 10:45         ` Jens Wiklander
2015-04-21 10:45           ` Jens Wiklander
2015-04-18  8:55   ` Greg Kroah-Hartman
2015-04-18  8:55     ` Greg Kroah-Hartman
2015-04-18  8:57   ` Greg Kroah-Hartman
2015-04-18  8:57     ` Greg Kroah-Hartman
2015-04-18  9:04     ` Russell King - ARM Linux
2015-04-18  9:04       ` Russell King - ARM Linux
2015-04-18  9:04       ` Russell King - ARM Linux
2015-04-18 18:47       ` Greg Kroah-Hartman
2015-04-18 18:47         ` Greg Kroah-Hartman
2015-04-18 19:02         ` Russell King - ARM Linux
2015-04-18 19:02           ` Russell King - ARM Linux
2015-04-18 20:37           ` Greg Kroah-Hartman
2015-04-18 20:37             ` Greg Kroah-Hartman
2015-04-18 20:50             ` Russell King - ARM Linux
2015-04-18 20:50               ` Russell King - ARM Linux
2015-04-19  7:00               ` Greg Kroah-Hartman
2015-04-19  7:00                 ` Greg Kroah-Hartman
2015-04-17  7:50 ` [RFC PATCH 2/2] tee: add OP-TEE driver Jens Wiklander
2015-04-17  7:50   ` Jens Wiklander
2015-04-17  7:50   ` Jens Wiklander
2015-04-18  8:57   ` Greg Kroah-Hartman
2015-04-18  8:57     ` Greg Kroah-Hartman
2015-04-18  9:36     ` Javier González
2015-04-18  9:36       ` Javier González
2015-04-18  9:36       ` Javier González
2015-04-18 18:49       ` Greg Kroah-Hartman
2015-04-18 18:49         ` Greg Kroah-Hartman
2015-04-18 19:01         ` Arnd Bergmann
2015-04-18 19:01           ` Arnd Bergmann
2015-04-19 11:17           ` Javier González
2015-04-19 11:17             ` Javier González
2015-04-19 19:47             ` Arnd Bergmann
2015-04-19 19:47               ` Arnd Bergmann
2015-04-20  7:05               ` Javier González
2015-04-20  7:05                 ` Javier González
2015-04-20  7:05                 ` Javier González
2015-04-20  6:42     ` Jens Wiklander
2015-04-20  6:42       ` Jens Wiklander
2015-04-20  6:42       ` Jens Wiklander

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=20150418172923.GA10605@obsidianresearch.com \
    --to=jgunthorpe@obsidianresearch.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    /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.