* [PATCH] touchscreen: ads7846: please don't touch free'd memory @ 2010-05-18 23:46 Kevin Hilman 2010-05-19 0:00 ` Dmitry Torokhov 0 siblings, 1 reply; 9+ messages in thread From: Kevin Hilman @ 2010-05-18 23:46 UTC (permalink / raw) To: linux-input Cc: linux-omap, Dmitry Torokhov, Michael Roth, Pavel Machek, Andrew Morton, Mike Frysinger, linux-kernel If the _probe() method fails, the 'ts' struct is freed, yet it is still used as the drvdata passed to suspend/resume/remove methods. Even though the input device does not get registerd, the driver's suspend/resume methods still get called as it's a registered SPI device. This patch adds sanity checks to these methods to ensure that drvdata is valid before using it. Problem discovered when using lockdep since the ts->lock taken in suspend & resume methods was left pointing into free'd memory if _probe() fails. Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> --- drivers/input/touchscreen/ads7846.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 532279c..1da2369 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -815,6 +815,9 @@ static int ads7846_suspend(struct spi_device *spi, pm_message_t message) { struct ads7846 *ts = dev_get_drvdata(&spi->dev); + if (WARN_ON_ONCE(!ts)) + return 0; + spin_lock_irq(&ts->lock); ts->is_suspended = 1; @@ -833,6 +836,9 @@ static int ads7846_resume(struct spi_device *spi) { struct ads7846 *ts = dev_get_drvdata(&spi->dev); + if (WARN_ON_ONCE(!ts)) + return 0; + if (device_may_wakeup(&ts->spi->dev)) disable_irq_wake(ts->spi->irq); @@ -1231,6 +1237,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) input_free_device(input_dev); kfree(packet); kfree(ts); + dev_set_drvdata(&spi->dev, NULL); return err; } @@ -1240,6 +1247,9 @@ static int __devexit ads7846_remove(struct spi_device *spi) device_init_wakeup(&spi->dev, false); + if (WARN_ON_ONCE(!ts)) + return 0; + ads784x_hwmon_unregister(spi, ts); input_unregister_device(ts->input); -- 1.7.0.2 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH] touchscreen: ads7846: please don't touch free'd memory 2010-05-18 23:46 [PATCH] touchscreen: ads7846: please don't touch free'd memory Kevin Hilman @ 2010-05-19 0:00 ` Dmitry Torokhov 2010-05-25 19:52 ` Kevin Hilman 0 siblings, 1 reply; 9+ messages in thread From: Dmitry Torokhov @ 2010-05-19 0:00 UTC (permalink / raw) To: Kevin Hilman Cc: linux-input, linux-omap, Michael Roth, Pavel Machek, Andrew Morton, Mike Frysinger, linux-kernel On Tue, May 18, 2010 at 04:46:53PM -0700, Kevin Hilman wrote: > If the _probe() method fails, the 'ts' struct is freed, yet it is > still used as the drvdata passed to suspend/resume/remove methods. > Even though the input device does not get registerd, the driver's > suspend/resume methods still get called as it's a registered SPI > device. This patch adds sanity checks to these methods to ensure that > drvdata is valid before using it. > This is a load of crap. If probe() fails that means that driver does not manage the device and thus ads7846_suspend() and ads7846_resume() should not be called _at all_. If SPI core manages to call random methods from the drivers that failed to bind to a device that should be fixed in SPI core. Thanks. -- Dmitry ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] touchscreen: ads7846: please don't touch free'd memory 2010-05-19 0:00 ` Dmitry Torokhov @ 2010-05-25 19:52 ` Kevin Hilman 2010-05-25 20:21 ` Dmitry Torokhov 0 siblings, 1 reply; 9+ messages in thread From: Kevin Hilman @ 2010-05-25 19:52 UTC (permalink / raw) To: Dmitry Torokhov Cc: linux-input, linux-omap, Michael Roth, Pavel Machek, Andrew Morton, Mike Frysinger, linux-kernel Dmitry Torokhov <dmitry.torokhov@gmail.com> writes: > On Tue, May 18, 2010 at 04:46:53PM -0700, Kevin Hilman wrote: >> If the _probe() method fails, the 'ts' struct is freed, yet it is >> still used as the drvdata passed to suspend/resume/remove methods. >> Even though the input device does not get registerd, the driver's >> suspend/resume methods still get called as it's a registered SPI >> device. This patch adds sanity checks to these methods to ensure that >> drvdata is valid before using it. >> > > This is a load of crap. If probe() fails that means that driver does not > manage the device and thus ads7846_suspend() and ads7846_resume() should > not be called _at all_. If SPI core manages to call random methods from > the drivers that failed to bind to a device that should be fixed in SPI > core. Agreed, this is indeed a bug in the SPI driver core. However, by fixing the SPI core to unregister the driver on failure (patch below), we prevent the suspend & resume methods from being called, but the driver's ->remove() method will still be called due to the driver_unregister(). So at least the remove() method needs fixing to prevent accessing free'd memory. Unless there are objections, I'll post the below along with an updated version of ads7846 patch. Kevin diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index b3a1f92..42d4d26 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -175,6 +175,8 @@ static void spi_drv_shutdown(struct device *dev) */ int spi_register_driver(struct spi_driver *sdrv) { + int ret; + sdrv->driver.bus = &spi_bus_type; if (sdrv->probe) sdrv->driver.probe = spi_drv_probe; @@ -182,7 +184,12 @@ int spi_register_driver(struct spi_driver *sdrv) sdrv->driver.remove = spi_drv_remove; if (sdrv->shutdown) sdrv->driver.shutdown = spi_drv_shutdown; - return driver_register(&sdrv->driver); + + ret = driver_register(&sdrv->driver); + if (!ret) + driver_unregister(&sdrv->driver); + + return ret; } EXPORT_SYMBOL_GPL(spi_register_driver); ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH] touchscreen: ads7846: please don't touch free'd memory 2010-05-25 19:52 ` Kevin Hilman @ 2010-05-25 20:21 ` Dmitry Torokhov 2010-05-25 21:46 ` Kevin Hilman 0 siblings, 1 reply; 9+ messages in thread From: Dmitry Torokhov @ 2010-05-25 20:21 UTC (permalink / raw) To: Kevin Hilman Cc: linux-input, linux-omap, Michael Roth, Pavel Machek, Andrew Morton, Mike Frysinger, linux-kernel On Tue, May 25, 2010 at 12:52:12PM -0700, Kevin Hilman wrote: > Dmitry Torokhov <dmitry.torokhov@gmail.com> writes: > > > On Tue, May 18, 2010 at 04:46:53PM -0700, Kevin Hilman wrote: > >> If the _probe() method fails, the 'ts' struct is freed, yet it is > >> still used as the drvdata passed to suspend/resume/remove methods. > >> Even though the input device does not get registerd, the driver's > >> suspend/resume methods still get called as it's a registered SPI > >> device. This patch adds sanity checks to these methods to ensure that > >> drvdata is valid before using it. > >> > > > > This is a load of crap. If probe() fails that means that driver does not > > manage the device and thus ads7846_suspend() and ads7846_resume() should > > not be called _at all_. If SPI core manages to call random methods from > > the drivers that failed to bind to a device that should be fixed in SPI > > core. > > Agreed, this is indeed a bug in the SPI driver core. > > However, by fixing the SPI core to unregister the driver on failure > (patch below), we prevent the suspend & resume methods from being > called, but the driver's ->remove() method will still be called due to > the driver_unregister(). So at least the remove() method needs fixing > to prevent accessing free'd memory. > > Unless there are objections, I'll post the below along with an updated > version of ads7846 patch. > > Kevin > > diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c > index b3a1f92..42d4d26 100644 > --- a/drivers/spi/spi.c > +++ b/drivers/spi/spi.c > @@ -175,6 +175,8 @@ static void spi_drv_shutdown(struct device *dev) > */ > int spi_register_driver(struct spi_driver *sdrv) > { > + int ret; > + > sdrv->driver.bus = &spi_bus_type; > if (sdrv->probe) > sdrv->driver.probe = spi_drv_probe; > @@ -182,7 +184,12 @@ int spi_register_driver(struct spi_driver *sdrv) > sdrv->driver.remove = spi_drv_remove; > if (sdrv->shutdown) > sdrv->driver.shutdown = spi_drv_shutdown; > - return driver_register(&sdrv->driver); > + > + ret = driver_register(&sdrv->driver); > + if (!ret) > + driver_unregister(&sdrv->driver); This is still wrong. driver_register() should properly clean up after itself and not require calls to driver_unregister() (and I believe it does). Besides, I do not see how this patch changes anything with regard to binding devices and drivers. Even if driver_register() succeeds, binding may still fail and we should not be calling neither ->remove(), nor ->suspend()/->resume() for the devices that failed to be bound. Still NAK, sorry. -- Dmitry ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] touchscreen: ads7846: please don't touch free'd memory 2010-05-25 20:21 ` Dmitry Torokhov @ 2010-05-25 21:46 ` Kevin Hilman 2010-05-25 21:56 ` Mike Frysinger 2010-05-26 0:09 ` David Brownell 0 siblings, 2 replies; 9+ messages in thread From: Kevin Hilman @ 2010-05-25 21:46 UTC (permalink / raw) To: Dmitry Torokhov Cc: linux-input, linux-omap, Michael Roth, Pavel Machek, Andrew Morton, Mike Frysinger, linux-kernel Dmitry Torokhov <dmitry.torokhov@gmail.com> writes: > On Tue, May 25, 2010 at 12:52:12PM -0700, Kevin Hilman wrote: >> Dmitry Torokhov <dmitry.torokhov@gmail.com> writes: >> >> > On Tue, May 18, 2010 at 04:46:53PM -0700, Kevin Hilman wrote: >> >> If the _probe() method fails, the 'ts' struct is freed, yet it is >> >> still used as the drvdata passed to suspend/resume/remove methods. >> >> Even though the input device does not get registerd, the driver's >> >> suspend/resume methods still get called as it's a registered SPI >> >> device. This patch adds sanity checks to these methods to ensure that >> >> drvdata is valid before using it. >> >> >> > >> > This is a load of crap. If probe() fails that means that driver does not >> > manage the device and thus ads7846_suspend() and ads7846_resume() should >> > not be called _at all_. If SPI core manages to call random methods from >> > the drivers that failed to bind to a device that should be fixed in SPI >> > core. >> >> Agreed, this is indeed a bug in the SPI driver core. >> >> However, by fixing the SPI core to unregister the driver on failure >> (patch below), we prevent the suspend & resume methods from being >> called, but the driver's ->remove() method will still be called due to >> the driver_unregister(). So at least the remove() method needs fixing >> to prevent accessing free'd memory. >> >> Unless there are objections, I'll post the below along with an updated >> version of ads7846 patch. >> >> Kevin >> >> diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c >> index b3a1f92..42d4d26 100644 >> --- a/drivers/spi/spi.c >> +++ b/drivers/spi/spi.c >> @@ -175,6 +175,8 @@ static void spi_drv_shutdown(struct device *dev) >> */ >> int spi_register_driver(struct spi_driver *sdrv) >> { >> + int ret; >> + >> sdrv->driver.bus = &spi_bus_type; >> if (sdrv->probe) >> sdrv->driver.probe = spi_drv_probe; >> @@ -182,7 +184,12 @@ int spi_register_driver(struct spi_driver *sdrv) >> sdrv->driver.remove = spi_drv_remove; >> if (sdrv->shutdown) >> sdrv->driver.shutdown = spi_drv_shutdown; >> - return driver_register(&sdrv->driver); >> + >> + ret = driver_register(&sdrv->driver); >> + if (!ret) >> + driver_unregister(&sdrv->driver); > > This is still wrong. driver_register() should properly clean up after > itself and not require calls to driver_unregister() (and I believe it > does). > > Besides, I do not see how this patch changes anything with regard to > binding devices and drivers. Even if driver_register() succeeds, binding > may still fail and we should not be calling neither ->remove(), nor > ->suspend()/->resume() for the devices that failed to be bound. Hmm, good point. After digging into the driver core and realizing that it seemed to have sane error handling itself, I took a closer look at ads7846_probe() and discovered it doesn't actually return an error code for certain failure cases! That was the root cause. The patch below fixes the problem. Thanks, Kevin >From 3588494cf6e51754f7089bb8089b99abd765c493 Mon Sep 17 00:00:00 2001 From: Kevin Hilman <khilman@deeprootsystems.com> Date: Tue, 25 May 2010 14:38:04 -0700 Subject: [PATCH] input: touchscreen: ads7846: return error on probe failure In probe(), if regulator_get() failed, an error code was not being returned causing the driver to be successfully bound, even though probe failed. This in turn caused the suspend, resume and remove methods to be registered and accessed via the SPI core. Since these functions all access private driver data using pointers that had been freed during the failed probe, this would lead to unpredictable behavior. This patch ensures that probe() returns an error code in this failure case so the driver is not bound. Found using lockdep and noticing the lock used in the suspend/resum path pointed to a bogus lock due to the freed memory. Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> --- drivers/input/touchscreen/ads7846.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 532279c..634f6f6 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -1163,8 +1163,8 @@ static int __devinit ads7846_probe(struct spi_device *spi) ts->reg = regulator_get(&spi->dev, "vcc"); if (IS_ERR(ts->reg)) { - dev_err(&spi->dev, "unable to get regulator: %ld\n", - PTR_ERR(ts->reg)); + err = PTR_ERR(ts->reg); + dev_err(&spi->dev, "unable to get regulator: %ld\n", err); goto err_free_gpio; } -- 1.7.0.2 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH] touchscreen: ads7846: please don't touch free'd memory 2010-05-25 21:46 ` Kevin Hilman @ 2010-05-25 21:56 ` Mike Frysinger 2010-05-25 22:18 ` Kevin Hilman 2010-05-26 0:09 ` David Brownell 1 sibling, 1 reply; 9+ messages in thread From: Mike Frysinger @ 2010-05-25 21:56 UTC (permalink / raw) To: Kevin Hilman Cc: Dmitry Torokhov, linux-input, linux-omap, Michael Roth, Pavel Machek, Andrew Morton, linux-kernel On Tue, May 25, 2010 at 17:46, Kevin Hilman wrote: > After digging into the driver core and realizing that it seemed to > have sane error handling itself, I took a closer look at > ads7846_probe() and discovered it doesn't actually return an error > code for certain failure cases! That was the root cause. that is crappy > Subject: [PATCH] input: touchscreen: ads7846: return error on probe failure i'd refer to the specific probe issue rather than just "probe". maybe: input: touchscreen: ads7846: return error on regulator_get() failure otherwise: Acked-by: Mike Frysinger <vapier@gentoo.org> -mike -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] touchscreen: ads7846: please don't touch free'd memory 2010-05-25 21:56 ` Mike Frysinger @ 2010-05-25 22:18 ` Kevin Hilman 2010-05-25 22:25 ` Dmitry Torokhov 0 siblings, 1 reply; 9+ messages in thread From: Kevin Hilman @ 2010-05-25 22:18 UTC (permalink / raw) To: Mike Frysinger Cc: Dmitry Torokhov, linux-input, linux-omap, Michael Roth, Pavel Machek, Andrew Morton, linux-kernel Mike Frysinger <vapier.adi@gmail.com> writes: > On Tue, May 25, 2010 at 17:46, Kevin Hilman wrote: >> After digging into the driver core and realizing that it seemed to >> have sane error handling itself, I took a closer look at >> ads7846_probe() and discovered it doesn't actually return an error >> code for certain failure cases! That was the root cause. > > that is crappy > >> Subject: [PATCH] input: touchscreen: ads7846: return error on probe failure > > i'd refer to the specific probe issue rather than just "probe". maybe: > input: touchscreen: ads7846: return error on regulator_get() failure Thanks for the review, here's one with updated subject and ack added. Kevin From 8ce49a91341d8713f870d2a931969f227a82b8ad Mon Sep 17 00:00:00 2001 From: Kevin Hilman <khilman@deeprootsystems.com> Date: Tue, 25 May 2010 14:38:04 -0700 Subject: [PATCH] input: touchscreen: ads7846: return error on regulator_get() failure In probe(), if regulator_get() failed, an error code was not being returned causing the driver to be successfully bound, even though probe failed. This in turn caused the suspend, resume and remove methods to be registered and accessed via the SPI core. Since these functions all access private driver data using pointers that had been freed during the failed probe, this would lead to unpredictable behavior. This patch ensures that probe() returns an error code in this failure case so the driver is not bound. Found using lockdep and noticing the lock used in the suspend/resum path pointed to a bogus lock due to the freed memory. Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> Acked-by: Mike Frysinger <vapier@gentoo.org> --- drivers/input/touchscreen/ads7846.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 532279c..634f6f6 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -1163,8 +1163,8 @@ static int __devinit ads7846_probe(struct spi_device *spi) ts->reg = regulator_get(&spi->dev, "vcc"); if (IS_ERR(ts->reg)) { - dev_err(&spi->dev, "unable to get regulator: %ld\n", - PTR_ERR(ts->reg)); + err = PTR_ERR(ts->reg); + dev_err(&spi->dev, "unable to get regulator: %ld\n", err); goto err_free_gpio; } -- 1.7.0.2 -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH] touchscreen: ads7846: please don't touch free'd memory 2010-05-25 22:18 ` Kevin Hilman @ 2010-05-25 22:25 ` Dmitry Torokhov 0 siblings, 0 replies; 9+ messages in thread From: Dmitry Torokhov @ 2010-05-25 22:25 UTC (permalink / raw) To: Kevin Hilman Cc: Mike Frysinger, linux-input, linux-omap, Michael Roth, Pavel Machek, Andrew Morton, linux-kernel On Tue, May 25, 2010 at 03:18:13PM -0700, Kevin Hilman wrote: > Mike Frysinger <vapier.adi@gmail.com> writes: > > > On Tue, May 25, 2010 at 17:46, Kevin Hilman wrote: > >> After digging into the driver core and realizing that it seemed to > >> have sane error handling itself, I took a closer look at > >> ads7846_probe() and discovered it doesn't actually return an error > >> code for certain failure cases! That was the root cause. > > > > that is crappy > > > >> Subject: [PATCH] input: touchscreen: ads7846: return error on probe failure > > > > i'd refer to the specific probe issue rather than just "probe". maybe: > > input: touchscreen: ads7846: return error on regulator_get() failure > > Thanks for the review, here's one with updated subject and ack added. > > Kevin > > From 8ce49a91341d8713f870d2a931969f227a82b8ad Mon Sep 17 00:00:00 2001 > From: Kevin Hilman <khilman@deeprootsystems.com> > Date: Tue, 25 May 2010 14:38:04 -0700 > Subject: [PATCH] input: touchscreen: ads7846: return error on regulator_get() failure > > In probe(), if regulator_get() failed, an error code was not being > returned causing the driver to be successfully bound, even though > probe failed. This in turn caused the suspend, resume and remove > methods to be registered and accessed via the SPI core. Since these > functions all access private driver data using pointers that had been > freed during the failed probe, this would lead to unpredictable > behavior. > > This patch ensures that probe() returns an error code in this failure > case so the driver is not bound. > > Found using lockdep and noticing the lock used in the suspend/resum > path pointed to a bogus lock due to the freed memory. > > Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> > Acked-by: Mike Frysinger <vapier@gentoo.org> OK, this makes much better sense. Will aplly, thank you Kevin. > --- > drivers/input/touchscreen/ads7846.c | 4 ++-- > 1 files changed, 2 insertions(+), 2 deletions(-) > > diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c > index 532279c..634f6f6 100644 > --- a/drivers/input/touchscreen/ads7846.c > +++ b/drivers/input/touchscreen/ads7846.c > @@ -1163,8 +1163,8 @@ static int __devinit ads7846_probe(struct spi_device *spi) > > ts->reg = regulator_get(&spi->dev, "vcc"); > if (IS_ERR(ts->reg)) { > - dev_err(&spi->dev, "unable to get regulator: %ld\n", > - PTR_ERR(ts->reg)); > + err = PTR_ERR(ts->reg); > + dev_err(&spi->dev, "unable to get regulator: %ld\n", err); > goto err_free_gpio; > } > > -- > 1.7.0.2 > -- Dmitry -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] touchscreen: ads7846: please don't touch free'd memory 2010-05-25 21:46 ` Kevin Hilman 2010-05-25 21:56 ` Mike Frysinger @ 2010-05-26 0:09 ` David Brownell 1 sibling, 0 replies; 9+ messages in thread From: David Brownell @ 2010-05-26 0:09 UTC (permalink / raw) To: Dmitry Torokhov, Kevin Hilman Cc: linux-input, linux-omap, Michael Roth, Pavel Machek, Andrew Morton, Mike Frysinger, linux-kernel, Grant Likely --- On Tue, 5/25/10, Kevin Hilman <khilman@deeprootsystems.com> wrote: > >> > This is a load of crap. If probe() fails that > means that driver does not > >> > manage the device And thus, dev->driver shouldn't be assigned ... That probe() looks very odd, lately, yes. It seems to have changed a lot over the past few years, and grown a few fault paths that don't behave right (that is, they don't clean up properly on failure, or don't report their faults)... > >> > and thus ads7846_suspend() > and ads7846_resume() should > >> > not be called _at all_. Those being called is an indication that the probe() succeeded so the driver is bound to that device... If SPI core manages > to call random methods from > >> > the drivers that failed to bind to a device > that should be fixed in SPI > >> > core. Not random methods. The appropriate ones ... for the case where probe() succeeded and the device has been properly set up. I suspect a bug was added when the driver binding got rewritten, whereby dev->driver was wrongly assigned on fault paths (where it should have been cleared). Of course that goes through slightly convoluted bits of driver model code... maybe there's no such bug, and everything is explained by probe() misbehaving. > >> Agreed, this is indeed a bug in the SPI driver > core. That's not at all clear to me. > >> However, by fixing the SPI core to unregister the > driver on failure > >> (patch below), ... as you noted, not a good patch "below". The issue seems to be on probe() paths, NOT as part of driver registration. > we prevent the suspend & resume > methods from being > >> called, but the driver's ->remove() method will > still be called due to > >> the driver_unregister(). So at least the > remove() method needs fixing > >> to prevent accessing free'd memory. That doesn't seem right; if the issue is probe() misbehavior, fixing that makes that access issue go away. Don't change remove() etc. I see two issues. One is flakey ads7846 probe() behavior. Another is the response of the current SPI core code to that flakiness ... the report here seems to indicate that the driver is bound to the device even though it's not been properly set up ... unclear whether probe() is reporting a clean failure, I suspect not. (If it were reporting a clean failure, the device should end up with no driver bound.) It's very possible the probe() errors explain all the problems. > >> Unless there are objections, I'll post the below > along with an updated > >> version of ads7846 patch. > >> > >> Kevin > >> > >> diff --git a/drivers/spi/spi.c > b/drivers/spi/spi.c > >> index b3a1f92..42d4d26 100644 > >> --- a/drivers/spi/spi.c > >> +++ b/drivers/spi/spi.c > >> @@ -175,6 +175,8 @@ static void > spi_drv_shutdown(struct device *dev) > >> */ > >> int spi_register_driver(struct spi_driver > *sdrv) > >> { > >> + int ret; > >> + > >> sdrv->driver.bus = > &spi_bus_type; > >> if (sdrv->probe) > >> > sdrv->driver.probe = spi_drv_probe; > >> @@ -182,7 +184,12 @@ int > spi_register_driver(struct spi_driver *sdrv) > >> > sdrv->driver.remove = spi_drv_remove; > >> if (sdrv->shutdown) > >> > sdrv->driver.shutdown = spi_drv_shutdown; > >> - return > driver_register(&sdrv->driver); > >> + > >> + ret = > driver_register(&sdrv->driver); > >> + if (!ret) > >> + > driver_unregister(&sdrv->driver); > > > > This is still wrong. driver_register() should properly > clean up after > > itself and not require calls to driver_unregister() > (and I believe it > > does). Right ... driver registration should always be safe. The tricky bit would be a side effect: probing any devices which match that driver. Don't unregister drivers on error; just make sure they don't get wrongly bound to devices if probe() misbehaves. > > > > Besides, I do not see how this patch changes anything > with regard to > > binding devices and drivers. Even if driver_register() > succeeds, binding > > may still fail and we should not be calling neither > ->remove(), nor > > ->suspend()/->resume() for the devices that > failed to be bound. > > Hmm, good point. > > After digging into the driver core and realizing that it > seemed to > have sane error handling itself, Sane but somewhat convoluted. It can be tricky to figure out. > I took a closer look at > ads7846_probe() and discovered it doesn't actually return > an error > code for certain failure cases! That was the root > cause. My conclusion too... > The patch below fixes the problem. Did you do much of an audit, or just work to fix this specific problem? I thought the code was looking fairly goofy. Regulator additions were pretty recent, but it wasn't clear to me that it'd be the *only* source of such problems... > > Thanks, > > Kevin > > > > From 3588494cf6e51754f7089bb8089b99abd765c493 Mon Sep 17 > 00:00:00 2001 > From: Kevin Hilman <khilman@deeprootsystems.com> > Date: Tue, 25 May 2010 14:38:04 -0700 > Subject: [PATCH] input: touchscreen: ads7846: return error > on probe failure > > In probe(), if regulator_get() failed, an error code was > not being > returned causing the driver to be successfully bound, even > though > probe failed. This in turn caused the suspend, resume > and remove > methods to be registered and accessed via the SPI > core. Or more simply: this was a nasty violation of the driver model, which lead to breakage. (The SPI core is just inheriting driver model/core behavior.) A driver that fails to properly bind to the device must report a probe() failure, ensuring that the driver is not recorded as being bound to the device... > Since these > functions all access private driver data using pointers > that had been > freed during the failed probe, this would lead to > unpredictable > behavior. > > This patch ensures that probe() returns an error code in > this failure > case so the driver is not bound. > > Found using lockdep and noticing the lock used in the > suspend/resum > path pointed to a bogus lock due to the freed memory. > > Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> > --- > drivers/input/touchscreen/ads7846.c | 4 ++-- > 1 files changed, 2 insertions(+), 2 deletions(-) > > diff --git a/drivers/input/touchscreen/ads7846.c > b/drivers/input/touchscreen/ads7846.c > index 532279c..634f6f6 100644 > --- a/drivers/input/touchscreen/ads7846.c > +++ b/drivers/input/touchscreen/ads7846.c > @@ -1163,8 +1163,8 @@ static int __devinit > ads7846_probe(struct spi_device *spi) > > ts->reg = > regulator_get(&spi->dev, "vcc"); > if (IS_ERR(ts->reg)) { > - > dev_err(&spi->dev, "unable to get regulator: %ld\n", Adding a requirement for a Vcc regulator seems likely to have broken lots of boards, FWIW ... > - > PTR_ERR(ts->reg)); > + err = > PTR_ERR(ts->reg); That error should be returned, yes. (one line not two; maybe the patch got wrapped somewhere.) I didn't check to make sure that was sufficient cleanup though. - Dave > + > dev_err(&spi->dev, "unable to get regulator: %ld\n", > err); > goto err_free_gpio; > } > > ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2010-05-26 0:09 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2010-05-18 23:46 [PATCH] touchscreen: ads7846: please don't touch free'd memory Kevin Hilman 2010-05-19 0:00 ` Dmitry Torokhov 2010-05-25 19:52 ` Kevin Hilman 2010-05-25 20:21 ` Dmitry Torokhov 2010-05-25 21:46 ` Kevin Hilman 2010-05-25 21:56 ` Mike Frysinger 2010-05-25 22:18 ` Kevin Hilman 2010-05-25 22:25 ` Dmitry Torokhov 2010-05-26 0:09 ` David Brownell
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).