From: David Fries <david@fries.net>
To: Thorsten Bschorr <thorsten@bschorr.de>
Cc: ??????? ??????? <zbr@ioremap.net>,
Jonathan ALIBERT <jonathan.alibert@gmail.com>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH] Avoid null-pointer access in w1/slaves/w1_therm
Date: Mon, 9 Mar 2015 18:09:24 -0500 [thread overview]
Message-ID: <20150309230924.GJ11991@spacedout.fries.net> (raw)
In-Reply-To: <CA+1k2cGkx91a5_bjmkg1Z72MS0muNKJL66EGvYk0vPNGDB6QGA@mail.gmail.com>
On Mon, Mar 09, 2015 at 11:47:24PM +0100, Thorsten Bschorr wrote:
> > Here's a different strategy, add a w1_therm family_data specific mutex
> > so w1_therm_remove_slave won't return while another thread is in
> > w1_slave_show. Thoughts?
> >
> > I included three patches, the first is the proposed fix, the second
> > makes it more reproducible (and since my testing doesn't have external
> > power I had to ignore that check), the third is just some debugging
> > messages. For testing I'm starting a read from w1_slave then manually
> > remove the sensor, which seems to do the trick.
>
> I'll test your patch, but keeping the original sleep-time tm.
Oops, sorry, it got lost in the shuffle, here's the first patch again
(the others were for debugging and increase that time and so wouldn't
go upstream anyway).
>From 777f5fd75f5f99a3352863e83d226c7b65ebdaa4 Mon Sep 17 00:00:00 2001
From: David Fries <David@Fries.net>
Date: Sat, 7 Mar 2015 22:25:37 -0600
Subject: [PATCH] w1_therm, don't let the slave go away while in w1_slave_show
A temperature conversion can take 750 ms to complete, if the sensor is
externally powered it releases the bus_mutex while it waits, but if
the slave device is removed sl becomes a dangling pointer.
The race condition window can be 10 * 750 ms = 7.5 seconds if the crc
check fails.
Reported-By: Thorsten Bschorr <thorsten@bschorr.de>
Signed-off-by: David Fries <David@Fries.net>
---
drivers/w1/slaves/w1_therm.c | 51 +++++++++++++++++++++++++++++++++-----------
1 file changed, 38 insertions(+), 13 deletions(-)
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
index 1f11a20..39a9e6a 100644
--- a/drivers/w1/slaves/w1_therm.c
+++ b/drivers/w1/slaves/w1_therm.c
@@ -59,9 +59,20 @@ MODULE_ALIAS("w1-family-" __stringify(W1_THERM_DS28EA00));
static int w1_strong_pullup = 1;
module_param_named(strong_pullup, w1_strong_pullup, int, 0);
+struct w1_therm_family_data {
+ uint8_t rom[9];
+ struct mutex lock;
+};
+
+/* return the address of the lock in the family data */
+#define THERM_LOCK(sl) \
+ (&((struct w1_therm_family_data*)sl->family_data)->lock)
+
static int w1_therm_add_slave(struct w1_slave *sl)
{
- sl->family_data = kzalloc(9, GFP_KERNEL);
+ sl->family_data = kzalloc(sizeof(struct w1_therm_family_data),
+ GFP_KERNEL);
+ mutex_init(THERM_LOCK(sl));
if (!sl->family_data)
return -ENOMEM;
return 0;
@@ -69,6 +80,11 @@ static int w1_therm_add_slave(struct w1_slave *sl)
static void w1_therm_remove_slave(struct w1_slave *sl)
{
+ /* Getting the lock means w1_slave_show isn't sleeping and the
+ * family_data can be freed.
+ */
+ mutex_lock(THERM_LOCK(sl));
+ mutex_unlock(THERM_LOCK(sl));
kfree(sl->family_data);
sl->family_data = NULL;
}
@@ -194,13 +210,15 @@ static ssize_t w1_slave_show(struct device *device,
struct w1_slave *sl = dev_to_w1_slave(device);
struct w1_master *dev = sl->master;
u8 rom[9], crc, verdict, external_power;
- int i, max_trying = 10;
+ int i, ret, max_trying = 10;
ssize_t c = PAGE_SIZE;
- i = mutex_lock_interruptible(&dev->bus_mutex);
- if (i != 0)
- return i;
+ ret = mutex_lock_interruptible(&dev->bus_mutex);
+ if (ret != 0)
+ goto post_unlock;
+ /* prevent the slave from going away in sleep */
+ mutex_lock(THERM_LOCK(sl));
memset(rom, 0, sizeof(rom));
while (max_trying--) {
@@ -230,17 +248,19 @@ static ssize_t w1_slave_show(struct device *device,
mutex_unlock(&dev->bus_mutex);
sleep_rem = msleep_interruptible(tm);
- if (sleep_rem != 0)
- return -EINTR;
+ if (sleep_rem != 0) {
+ ret = -EINTR;
+ goto post_unlock;
+ }
- i = mutex_lock_interruptible(&dev->bus_mutex);
- if (i != 0)
- return i;
+ ret = mutex_lock_interruptible(&dev->bus_mutex);
+ if (ret != 0)
+ goto post_unlock;
} else if (!w1_strong_pullup) {
sleep_rem = msleep_interruptible(tm);
if (sleep_rem != 0) {
- mutex_unlock(&dev->bus_mutex);
- return -EINTR;
+ ret = -EINTR;
+ goto pre_unlock;
}
}
@@ -279,9 +299,14 @@ static ssize_t w1_slave_show(struct device *device,
c -= snprintf(buf + PAGE_SIZE - c, c, "t=%d\n",
w1_convert_temp(rom, sl->family->fid));
+ ret = PAGE_SIZE - c;
+
+pre_unlock:
mutex_unlock(&dev->bus_mutex);
- return PAGE_SIZE - c;
+post_unlock:
+ mutex_unlock(THERM_LOCK(sl));
+ return ret;
}
static int __init w1_therm_init(void)
--
2.1.4
next prev parent reply other threads:[~2015-03-09 23:09 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <CA+1k2cH5Y+RngvEbgE3CW5g+bO3V1ytDJC=u6DLVDZvbEOhu5A@mail.gmail.com>
[not found] ` <CA+1k2cF1frcEUu-L_cSJxTp=GKExn6Vt2rdCeY=zrhM62FUggw@mail.gmail.com>
[not found] ` <CA+1k2cEwtY+U7TS3rpmMp5nEBokO8vwhcOiD0ExVQnuoB=XVLQ@mail.gmail.com>
2015-02-23 17:09 ` Fwd: w1/slaves/w1_therm: null-ptr access of sl->family_data Thorsten Bschorr
2015-02-24 1:37 ` David Fries
2015-02-25 9:28 ` Thorsten Bschorr
2015-02-27 8:43 ` [PATCH] Avoid null-pointer access in w1/slaves/w1_therm Thorsten.Bschorr
2015-02-28 20:17 ` David Fries
[not found] ` <369891425174502@web4m.yandex.ru>
2015-03-01 2:17 ` David Fries
2015-03-01 13:04 ` Thorsten Bschorr
2015-03-02 0:17 ` David Fries
2015-03-04 15:36 ` Евгений Поляков
2015-03-08 21:14 ` David Fries
2015-03-09 22:47 ` Thorsten Bschorr
2015-03-09 23:09 ` David Fries [this message]
2015-03-10 0:05 ` Thorsten Bschorr
2015-03-10 0:34 ` Thorsten Bschorr
2015-03-12 0:44 ` David Fries
2015-03-10 13:52 ` Evgeniy Polyakov
2015-03-12 0:54 ` David Fries
2015-03-14 20:55 ` Evgeniy Polyakov
2015-03-18 4:20 ` David Fries
2015-03-18 15:18 ` Evgeniy Polyakov
2015-03-19 0:09 ` David Fries
[not found] ` <CADq11+-tZmQEVUL=sHC64i4auC_5i=+y2yBcMTaJMdD5Z0dE6w@mail.gmail.com>
2015-04-16 3:51 ` David Fries
2015-04-16 11:57 ` Evgeniy Polyakov
[not found] ` <CA+1k2cFw+2NTOtbSaJ1S=kBAn2Mj62DTeZo68V9t1Wk-7m7GyA@mail.gmail.com>
2015-04-17 12:55 ` Evgeniy Polyakov
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=20150309230924.GJ11991@spacedout.fries.net \
--to=david@fries.net \
--cc=jonathan.alibert@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=thorsten@bschorr.de \
--cc=zbr@ioremap.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®