From: Tomasz Duszynski <tduszyns@gmail.com>
To: Sven Van Asbroeck <thesven73@gmail.com>
Cc: Jonathan Cameron <jic23@kernel.org>,
Jonathan Cameron <jonathan.cameron@huawei.com>,
Hartmut Knaack <knaack.h@gmx.de>,
Lars-Peter Clausen <lars@metafoo.de>,
Peter Meerwald-Stadler <pmeerw@pmeerw.net>,
linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org,
Matt Ranostay <matt.ranostay@konsulko.com>
Subject: Re: [PATCH v2] iio: proximity: as3935: fix use-after-free on device remove
Date: Fri, 8 Mar 2019 21:29:37 +0100 [thread overview]
Message-ID: <20190308202936.GA32641@arch> (raw)
In-Reply-To: <20190308175935.21904-1-TheSven73@gmail.com>
On Fri, Mar 08, 2019 at 12:59:35PM -0500, Sven Van Asbroeck wrote:
> This driver's probe() uses a mix of devm_ and non-devm_ functions. This
> means that the remove order will not be the exact opposite of the probe
> order.
>
> Remove order:
> 1. remove() executes:
> iio_device_unregister
> iio_triggered_buffer_cleanup
> iio_trigger_unregister
> (A)
> 2. core frees devm resources in reverse order:
> free_irq
> iio_trigger_free
> iio_device_free
>
> In (A) the trigger has been unregistered, but the irq handler is still
> registered and active, so the trigger may still be touched via
> interrupt -> as3935_event_work. This is a potential use-after-unregister.
>
> Given that the delayed work is never canceled explicitly, it may run even
> after iio_device_free. This is a potential use-after-free.
>
> Solution: convert all probe functions to their devm_ equivalents.
> Add a devm callback, called by the core on remove right after irq_free,
> which explicitly cancels the delayed work. This will guarantee that all
> resources are freed in the correct order.
>
> As an added bonus, some boilerplate code can be removed.
>
> Signed-off-by: Sven Van Asbroeck <TheSven73@gmail.com>
> ---
> drivers/iio/proximity/as3935.c | 49 ++++++++++++++--------------------
> 1 file changed, 20 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c
> index f130388a16a0..6e366e772164 100644
> --- a/drivers/iio/proximity/as3935.c
> +++ b/drivers/iio/proximity/as3935.c
> @@ -345,6 +345,14 @@ static SIMPLE_DEV_PM_OPS(as3935_pm_ops, as3935_suspend, as3935_resume);
> #define AS3935_PM_OPS NULL
> #endif
>
> +static void as3935_stop_work(void *data)
> +{
> + struct iio_dev *indio_dev = data;
> + struct as3935_state *st = iio_priv(indio_dev);
> +
> + cancel_delayed_work_sync(&st->work);
> +}
> +
> static int as3935_probe(struct spi_device *spi)
> {
> struct iio_dev *indio_dev;
> @@ -368,7 +376,6 @@ static int as3935_probe(struct spi_device *spi)
>
> spi_set_drvdata(spi, indio_dev);
> mutex_init(&st->lock);
> - INIT_DELAYED_WORK(&st->work, as3935_event_work);
Any specific reason for moving this elsewhere?
>
> ret = of_property_read_u32(np,
> "ams,tuning-capacitor-pf", &st->tune_cap);
> @@ -414,22 +421,27 @@ static int as3935_probe(struct spi_device *spi)
> iio_trigger_set_drvdata(trig, indio_dev);
> trig->ops = &iio_interrupt_trigger_ops;
>
> - ret = iio_trigger_register(trig);
> + ret = devm_iio_trigger_register(&spi->dev, trig);
> if (ret) {
> dev_err(&spi->dev, "failed to register trigger\n");
> return ret;
> }
>
> - ret = iio_triggered_buffer_setup(indio_dev, iio_pollfunc_store_time,
> - &as3935_trigger_handler, NULL);
> + ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,
> + iio_pollfunc_store_time, as3935_trigger_handler, NULL);
You can fix arguments alignment while you are at it.
>
> if (ret) {
> dev_err(&spi->dev, "cannot setup iio trigger\n");
> - goto unregister_trigger;
> + return ret;
> }
>
> calibrate_as3935(st);
>
> + INIT_DELAYED_WORK(&st->work, as3935_event_work);
> + ret = devm_add_action(&spi->dev, as3935_stop_work, indio_dev);
> + if (ret)
> + return ret;
> +
> ret = devm_request_irq(&spi->dev, spi->irq,
> &as3935_interrupt_handler,
> IRQF_TRIGGER_RISING,
> @@ -438,35 +450,15 @@ static int as3935_probe(struct spi_device *spi)
>
> if (ret) {
> dev_err(&spi->dev, "unable to request irq\n");
> - goto unregister_buffer;
> + return ret;
> }
>
> - ret = iio_device_register(indio_dev);
> + ret = devm_iio_device_register(&spi->dev, indio_dev);
> if (ret < 0) {
> dev_err(&spi->dev, "unable to register device\n");
> - goto unregister_buffer;
> + return ret;
> }
> return 0;
> -
> -unregister_buffer:
> - iio_triggered_buffer_cleanup(indio_dev);
> -
> -unregister_trigger:
> - iio_trigger_unregister(st->trig);
> -
> - return ret;
> -}
> -
> -static int as3935_remove(struct spi_device *spi)
> -{
> - struct iio_dev *indio_dev = spi_get_drvdata(spi);
> - struct as3935_state *st = iio_priv(indio_dev);
> -
> - iio_device_unregister(indio_dev);
> - iio_triggered_buffer_cleanup(indio_dev);
> - iio_trigger_unregister(st->trig);
> -
> - return 0;
> }
>
> static const struct of_device_id as3935_of_match[] = {
> @@ -488,7 +480,6 @@ static struct spi_driver as3935_driver = {
> .pm = AS3935_PM_OPS,
> },
> .probe = as3935_probe,
> - .remove = as3935_remove,
> .id_table = as3935_id,
> };
> module_spi_driver(as3935_driver);
> --
> 2.17.1
>
next prev parent reply other threads:[~2019-03-08 20:30 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-03-08 17:59 [PATCH v2] iio: proximity: as3935: fix use-after-free on device remove Sven Van Asbroeck
2019-03-08 20:29 ` Tomasz Duszynski [this message]
2019-03-08 20:42 ` Sven Van Asbroeck
2019-03-08 22:32 ` Tomasz Duszynski
2019-03-08 22:46 ` Sven Van Asbroeck
2019-03-09 10:24 ` Tomasz Duszynski
2019-03-09 13:03 ` Sven Van Asbroeck
2019-03-10 9:34 ` Jonathan Cameron
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=20190308202936.GA32641@arch \
--to=tduszyns@gmail.com \
--cc=jic23@kernel.org \
--cc=jonathan.cameron@huawei.com \
--cc=knaack.h@gmx.de \
--cc=lars@metafoo.de \
--cc=linux-iio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=matt.ranostay@konsulko.com \
--cc=pmeerw@pmeerw.net \
--cc=thesven73@gmail.com \
/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.