From: Pavel Herrmann <hidden> Date: 2011-05-18 15:18:38
spi_sync call uses its spi_message parameter to keep completion information,
having this structure static is not thread-safe, potentially causing one
thread having pointers to memory on or above other threads stack. use
per-call spi_message on stack to fix this
Signed-off-by: Pavel Herrmann <redacted>
Signed-off-by: Marek Vasut <redacted>
---
drivers/hwmon/max1111.c | 86 +++++++++++++----------------------------------
1 files changed, 24 insertions(+), 62 deletions(-)
From: Eric Miao <hidden> Date: 2011-05-18 15:29:09
On Wed, May 18, 2011 at 11:18 PM, Pavel Herrmann
[off-list ref] wrote:
spi_sync call uses its spi_message parameter to keep completion information,
having this structure static is not thread-safe, potentially causing one
thread having pointers to memory on or above other threads stack. use
per-call spi_message on stack to fix this
Signed-off-by: Pavel Herrmann <redacted>
Signed-off-by: Marek Vasut <redacted>
From: Russell King - ARM Linux <hidden> Date: 2011-05-18 15:29:35
On Wed, May 18, 2011 at 05:18:38PM +0200, Pavel Herrmann wrote:
spi_sync call uses its spi_message parameter to keep completion information,
having this structure static is not thread-safe, potentially causing one
thread having pointers to memory on or above other threads stack. use
per-call spi_message on stack to fix this
I assume this has not been tested with DMA debugging enabled.
The DMA API does not like mapping memory from the stack, which is what
you're potentially doing with this:
From: Marek Vasut <hidden> Date: 2011-05-18 17:36:54
On Wed, May 18, 2011 at 05:18:38PM +0200, Pavel Herrmann wrote:
quoted
spi_sync call uses its spi_message parameter to keep completion
information, having this structure static is not thread-safe,
potentially causing one thread having pointers to memory on or above
other threads stack. use per-call spi_message on stack to fix this
I assume this has not been tested with DMA debugging enabled.
The DMA API does not like mapping memory from the stack, which is what
you're potentially doing with this:
Yikes, good catch, but kmallocing this and kfreeing it again is not something I'd like to see either.
What other options do you suggest?
Btw note, this isn't the only driver doing this, maybe we have a horde of patches on the way?
From: Russell King - ARM Linux <hidden> Date: 2011-05-18 22:47:15
On Wed, May 18, 2011 at 07:36:54PM +0200, Marek Vasut wrote:
quoted
On Wed, May 18, 2011 at 05:18:38PM +0200, Pavel Herrmann wrote:
quoted
spi_sync call uses its spi_message parameter to keep completion
information, having this structure static is not thread-safe,
potentially causing one thread having pointers to memory on or above
other threads stack. use per-call spi_message on stack to fix this
I assume this has not been tested with DMA debugging enabled.
The DMA API does not like mapping memory from the stack, which is what
you're potentially doing with this:
Yikes, good catch, but kmallocing this and kfreeing it again is not
something I'd like to see either.
You could use a semaphore to protect against other threads.
However, this driver just gives us yet more problems, as it overlaps
the DMA'd data with the DMA metadata (spi message/spi transfer
structures.) And yes we do get bug reports on that too...
I think its about time driver and subsystem authors got a clue about
DMA incoherent architectures, and these things called 'cache lines'
which have a direct impact on whether code is buggy or not. Sharing
cache lines between DMA buffers and other data is Really Bad News for
data integrity - even sharing a cache line between two DMA buffers
can be a problem.
From: Pavel Machek <hidden> Date: 2011-05-19 12:35:08
Hi!
On Wed 2011-05-18 16:29:35, Russell King - ARM Linux wrote:
On Wed, May 18, 2011 at 05:18:38PM +0200, Pavel Herrmann wrote:
quoted
spi_sync call uses its spi_message parameter to keep completion information,
having this structure static is not thread-safe, potentially causing one
thread having pointers to memory on or above other threads stack. use
per-call spi_message on stack to fix this
I assume this has not been tested with DMA debugging enabled.
The DMA API does not like mapping memory from the stack, which is what
you're potentially doing with this:
In some other mail, you said "just add the locking". Pavel H.
actually produced patch doing so...
From: Pavel Herrmann <redacted>
To: Marek Vasut <redacted>
From 14063b017123233a8b56d6706a9ff046a791eaf4 Mon Sep 17 00:00:00 2001
From: Pavel Herrmann <redacted>
Date: Mon, 16 May 2011 14:18:18 +0200
Subject: [PATCH] Fix NULL pointer exception in max1111
Signed-off-by: Pavel Herrmann <redacted>
---
drivers/hwmon/max1111.c | 16 ++++++++++++++++
1 files changed, 16 insertions(+), 0 deletions(-)
@@ -48,6 +49,11 @@ static int max1111_read(struct device *dev, int channel)uint8_tv1,v2;interr;+/* spi_sync requires data not to be freed before function returns+*forstaticdata,anyaccessisdangerous,uselocks+*/+mutex_lock(&data->msg_lock_mutex);+data->tx_buf[0]=(channel<<MAX1111_CTRL_SEL_SH)|MAX1111_CTRL_PD0|MAX1111_CTRL_PD1|MAX1111_CTRL_SGL|MAX1111_CTRL_UNI|MAX1111_CTRL_STR;
@@ -55,12 +61,15 @@ static int max1111_read(struct device *dev, int channel)err=spi_sync(data->spi,&data->msg);if(err<0){dev_err(dev,"spi_sync failed with %d\n",err);+mutex_unlock(&data->msg_lock_mutex);returnerr;}v1=data->rx_buf[0];v2=data->rx_buf[1];+mutex_unlock(&data->msg_lock_mutex);+if((v1&0xc0)||(v2&0x3f))return-EINVAL;
@@ -138,6 +147,8 @@ static int setup_transfer(struct max1111_data *data)return-ENOMEM;}+mutex_lock(&data->msg_lock_mutex);+m=&data->msg;x=&data->xfer[0];
@@ -152,6 +163,8 @@ static int setup_transfer(struct max1111_data *data)x->len=2;spi_message_add_tail(x,m);+mutex_unlock(&data->msg_lock_mutex);+return0;}
@@ -172,6 +185,8 @@ static int __devinit max1111_probe(struct spi_device *spi)return-ENOMEM;}+mutex_init(&data->msg_lock_mutex);+err=setup_transfer(data);if(err)gotoerr_free_data;
@@ -213,6 +228,7 @@ static int __devexit max1111_remove(struct spi_device *spi)hwmon_device_unregister(data->hwmon_dev);sysfs_remove_group(&spi->dev.kobj,&max1111_attr_group);+mutex_destroy(data->msg_lock_mutex);kfree(data->rx_buf);kfree(data->tx_buf);kfree(data);
From: Pavel Herrmann <hidden> Date: 2011-05-19 12:51:40
Hi
On Thursday, May 19, 2011 02:35:08 PM Pavel Machek wrote:
quoted
you're potentially doing with this:
In some other mail, you said "just add the locking". Pavel H.
actually produced patch doing so...
yes, that was the original version of the patch. while I agree with Marek on
locks not being the right way, I was going send a cleaner version of the
original locking patch today (locking in probe is not really necessary), you
just beat me to it.
Pavel Herrmann
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Fix-NULL-pointer-exception-in-max1111.patch
Type: text/x-patch
Size: 2110 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110519/db197747/attachment.bin>
From: Marek Vasut <hidden> Date: 2011-05-19 13:55:10
On Thursday, May 19, 2011 02:51:40 PM Pavel Herrmann wrote:
Hi
On Thursday, May 19, 2011 02:35:08 PM Pavel Machek wrote:
quoted
quoted
you're potentially doing with this:
In some other mail, you said "just add the locking". Pavel H.
actually produced patch doing so...
yes, that was the original version of the patch. while I agree with Marek
on locks not being the right way, I was going send a cleaner version of
the original locking patch today (locking in probe is not really
necessary), you just beat me to it.
From: Russell King - ARM Linux <hidden> Date: 2011-05-19 19:31:21
On Thu, May 19, 2011 at 02:51:40PM +0200, Pavel Herrmann wrote:
quoted hunk
@@ -52,7 +53,14 @@ static int max1111_read(struct device *dev, int channel) MAX1111_CTRL_PD0 | MAX1111_CTRL_PD1 | MAX1111_CTRL_SGL | MAX1111_CTRL_UNI | MAX1111_CTRL_STR;+ /* spi_sync requires data not to be freed before function returns+ * for static data, any access is dangerous, use locks+ */+ mutex_lock(&data->msg_lock_mutex);+ err = spi_sync(data->spi, &data->msg);++ mutex_unlock(&data->msg_lock_mutex);
I'm not sure that this is right. Taking the lock around spi_sync() ensures
that two concurrent spi_sync()s can't happen in parallel, but with this you
could end up with another happening as soon as this lock is released -
before you've accessed the data which was transferred.
I think you want to hold the mutex at the point you setup the data to be
transferred, do the transfer, and then release the mutex once you've read
the results of the transfer.
From: Pavel Herrmann <hidden> Date: 2011-05-19 22:13:20
On Thursday, May 19, 2011 09:31:21 PM Russell King - ARM Linux wrote:
I'm not sure that this is right. Taking the lock around spi_sync() ensures
that two concurrent spi_sync()s can't happen in parallel, but with this you
could end up with another happening as soon as this lock is released -
before you've accessed the data which was transferred.
I think you want to hold the mutex at the point you setup the data to be
transferred, do the transfer, and then release the mutex once you've read
the results of the transfer.
oh no, not again...
this was the earliest version, not the cleaned-up one (notice the lock in
setup-transfer, which I said was unnecessary)
here is the cleaner (newest) version:
From bd55d6b18fa4fcb884980825b43b43df01767149 Mon Sep 17 00:00:00 2001
From: Pavel Herrmann <redacted>
Date: Mon, 16 May 2011 14:18:18 +0200
Subject: [PATCH] MAX1111: Fix Race condition causing NULL pointer exception
spi_sync call uses its spi_message parameter to keep completion information,
having this structure static is not thread-safe, potentially causing one
thread having pointers to memory on or above other threads stack. use mutex
to prevent multiple access
Signed-off-by: Pavel Herrmann <redacted>
---
drivers/hwmon/max1111.c | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)
@@ -48,6 +49,11 @@ static int max1111_read(struct device *dev, int channel)uint8_tv1,v2;interr;+/* spi_sync requires data not to be freed before function returns+*forstaticdata,anyaccessisdangerous,uselocks+*/+mutex_lock(&data->msg_lock_mutex);+data->tx_buf[0]=(channel<<MAX1111_CTRL_SEL_SH)|MAX1111_CTRL_PD0|MAX1111_CTRL_PD1|MAX1111_CTRL_SGL|MAX1111_CTRL_UNI|MAX1111_CTRL_STR;
@@ -55,12 +61,15 @@ static int max1111_read(struct device *dev, int channel)err=spi_sync(data->spi,&data->msg);if(err<0){dev_err(dev,"spi_sync failed with %d\n",err);+mutex_unlock(&data->msg_lock_mutex);returnerr;}v1=data->rx_buf[0];v2=data->rx_buf[1];+mutex_unlock(&data->msg_lock_mutex);+if((v1&0xc0)||(v2&0x3f))return-EINVAL;
@@ -176,6 +185,8 @@ static int __devinit max1111_probe(struct spi_device *spi)if(err)gotoerr_free_data;+mutex_init(&data->msg_lock_mutex);+data->spi=spi;spi_set_drvdata(spi,data);
@@ -213,6 +224,7 @@ static int __devexit max1111_remove(struct spi_device
From: Russell King - ARM Linux <hidden> Date: 2011-05-20 21:20:05
On Fri, May 20, 2011 at 12:13:20AM +0200, Pavel Herrmann wrote:
From bd55d6b18fa4fcb884980825b43b43df01767149 Mon Sep 17 00:00:00 2001
From: Pavel Herrmann <redacted>
Date: Mon, 16 May 2011 14:18:18 +0200
Subject: [PATCH] MAX1111: Fix Race condition causing NULL pointer exception
spi_sync call uses its spi_message parameter to keep completion information,
having this structure static is not thread-safe, potentially causing one
thread having pointers to memory on or above other threads stack. use mutex
to prevent multiple access
Signed-off-by: Pavel Herrmann <redacted>
Looks good, thanks.
Acked-by: Russell King <redacted>
@@ -48,6 +49,11 @@ static int max1111_read(struct device *dev, int channel)uint8_tv1,v2;interr;+/* spi_sync requires data not to be freed before function returns+*forstaticdata,anyaccessisdangerous,uselocks+*/+mutex_lock(&data->msg_lock_mutex);+data->tx_buf[0]=(channel<<MAX1111_CTRL_SEL_SH)|MAX1111_CTRL_PD0|MAX1111_CTRL_PD1|MAX1111_CTRL_SGL|MAX1111_CTRL_UNI|MAX1111_CTRL_STR;
@@ -55,12 +61,15 @@ static int max1111_read(struct device *dev, int channel)err=spi_sync(data->spi,&data->msg);if(err<0){dev_err(dev,"spi_sync failed with %d\n",err);+mutex_unlock(&data->msg_lock_mutex);returnerr;}v1=data->rx_buf[0];v2=data->rx_buf[1];+mutex_unlock(&data->msg_lock_mutex);+if((v1&0xc0)||(v2&0x3f))return-EINVAL;
@@ -176,6 +185,8 @@ static int __devinit max1111_probe(struct spi_device *spi)if(err)gotoerr_free_data;+mutex_init(&data->msg_lock_mutex);+data->spi=spi;spi_set_drvdata(spi,data);
@@ -213,6 +224,7 @@ static int __devexit max1111_remove(struct spi_device
From: Pavel Machek <hidden> Date: 2011-05-21 20:28:07
Hi!
quoted
I think you want to hold the mutex at the point you setup the data to be
transferred, do the transfer, and then release the mutex once you've read
the results of the transfer.
oh no, not again...
this was the earliest version, not the cleaned-up one (notice the lock in
setup-transfer, which I said was unnecessary)
here is the cleaner (newest) version:
Unfortunately that one does not apply, due to
quoted hunk
@@ -213,6 +224,7 @@ static int __devexit max1111_remove(struct spi_device
From: Pavel Herrmann <hidden> Date: 2011-05-21 20:45:02
On Saturday, May 21, 2011 10:28:07 PM Pavel Machek wrote:
Unfortunately that one does not apply, due to
quoted
@@ -213,6 +224,7 @@ static int __devexit max1111_remove(struct spi_device
*spi)
Whitespace damage. (but if you just delete this extra newline, its
fine).
sorry for that one, I followed Mareks advice on sending the pach inline, and my mail
client does automatic text reflow (defaults to 78 columns). I still have to find the
correct formating settings to send these patches.
thanks for the ACK and testing
Pavel
From: Marek Vasut <hidden> Date: 2011-05-22 15:52:57
On Saturday, May 21, 2011 10:45:02 PM Pavel Herrmann wrote:
On Saturday, May 21, 2011 10:28:07 PM Pavel Machek wrote:
quoted
Unfortunately that one does not apply, due to
quoted
@@ -213,6 +224,7 @@ static int __devexit max1111_remove(struct
spi_device *spi)
Whitespace damage. (but if you just delete this extra newline, its
fine).
sorry for that one, I followed Mareks advice on sending the pach inline,
and my mail client does automatic text reflow (defaults to 78 columns). I
still have to find the correct formating settings to send these patches.
thanks for the ACK and testing
Pavel
From: Marek Vasut <hidden> Date: 2011-06-30 12:36:25
On Wednesday, May 18, 2011 11:47:44 PM Cyril Hrubis wrote:
Hi!
I've applied this patch over 2.6.39-rc3 and did couple of suspends. After
about ten of them I've got attached trace (instead of the usuall NULL
pointer dereference in complete()).
And yes, the MMC is still broken after this change it seems that there are
more bugs in zaurus SPI drivers.
Looks like corgi-bl, I think there was a patch for this I had, dunno if it was
applied.
Eric, was that gpio_set_value_cansleep() for corgi-bl merged ?