From: Neil Brown <neilb@suse.de>
To: Al Viro <viro@ZenIV.linux.org.uk>
Cc: Andrew Morton <akpm@linux-foundation.org>,
linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 002 of 6] md: Fix use-after-free bug when dropping an rdev from an md array.
Date: Mon, 14 Jan 2008 17:28:44 +1100 [thread overview]
Message-ID: <18315.284.774998.348672@notabene.brown> (raw)
In-Reply-To: message from Neil Brown on Monday January 14
On Monday January 14, neilb@suse.de wrote:
>
> Thanks. I'll see what I can some up with.
How about this, against current -mm
On both the read and write path for an rdev attribute, we
call mddev_lock, first checking that mddev is not NULL.
Once we get the lock, we check again.
If rdev->mddev is not NULL, we know it will stay that way as it only
gets cleared under the same lock.
While in the rdev show/store routines, we know that the mddev cannot
get freed, do to the kobject relationships.
rdev_size_store is awkward because it has to drop the lock. So we
take a copy of rdev->mddev before the drop, and we are safe...
Comments?
NeilBrown
Signed-off-by: Neil Brown <neilb@suse.de>
### Diffstat output
./drivers/md/md.c | 35 ++++++++++++++++++++++++++---------
1 file changed, 26 insertions(+), 9 deletions(-)
diff .prev/drivers/md/md.c ./drivers/md/md.c
--- .prev/drivers/md/md.c 2008-01-14 12:26:15.000000000 +1100
+++ ./drivers/md/md.c 2008-01-14 17:05:53.000000000 +1100
@@ -1998,9 +1998,11 @@ rdev_size_store(mdk_rdev_t *rdev, const
char *e;
unsigned long long size = simple_strtoull(buf, &e, 10);
unsigned long long oldsize = rdev->size;
+ mddev_t *my_mddev = rdev->mddev;
+
if (e==buf || (*e && *e != '\n'))
return -EINVAL;
- if (rdev->mddev->pers)
+ if (my_mddev->pers)
return -EBUSY;
rdev->size = size;
if (size > oldsize && rdev->mddev->external) {
@@ -2013,7 +2015,7 @@ rdev_size_store(mdk_rdev_t *rdev, const
int overlap = 0;
struct list_head *tmp, *tmp2;
- mddev_unlock(rdev->mddev);
+ mddev_unlock(my_mddev);
for_each_mddev(mddev, tmp) {
mdk_rdev_t *rdev2;
@@ -2033,7 +2035,7 @@ rdev_size_store(mdk_rdev_t *rdev, const
break;
}
}
- mddev_lock(rdev->mddev);
+ mddev_lock(my_mddev);
if (overlap) {
/* Someone else could have slipped in a size
* change here, but doing so is just silly.
@@ -2045,8 +2047,8 @@ rdev_size_store(mdk_rdev_t *rdev, const
return -EBUSY;
}
}
- if (size < rdev->mddev->size || rdev->mddev->size == 0)
- rdev->mddev->size = size;
+ if (size < my_mddev->size || my_mddev->size == 0)
+ my_mddev->size = size;
return len;
}
@@ -2067,10 +2069,21 @@ rdev_attr_show(struct kobject *kobj, str
{
struct rdev_sysfs_entry *entry = container_of(attr, struct rdev_sysfs_entry, attr);
mdk_rdev_t *rdev = container_of(kobj, mdk_rdev_t, kobj);
+ mddev_t *mddev = rdev->mddev;
+ ssize_t rv;
if (!entry->show)
return -EIO;
- return entry->show(rdev, page);
+
+ rv = mddev ? mddev_lock(mddev) : -EBUSY;
+ if (!rv) {
+ if (rdev->mddev == NULL)
+ rv = -EBUSY;
+ else
+ rv = entry->show(rdev, page);
+ mddev_unlock(mddev);
+ }
+ return rv;
}
static ssize_t
@@ -2079,15 +2092,19 @@ rdev_attr_store(struct kobject *kobj, st
{
struct rdev_sysfs_entry *entry = container_of(attr, struct rdev_sysfs_entry, attr);
mdk_rdev_t *rdev = container_of(kobj, mdk_rdev_t, kobj);
- int rv;
+ ssize_t rv;
+ mddev_t *mddev = rdev->mddev;
if (!entry->store)
return -EIO;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- rv = mddev_lock(rdev->mddev);
+ rv = mddev ? mddev_lock(mddev): -EBUSY;
if (!rv) {
- rv = entry->store(rdev, page, length);
+ if (rdev->mddev == NULL)
+ rv = -EBUSY;
+ else
+ rv = entry->store(rdev, page, length);
mddev_unlock(rdev->mddev);
}
return rv;
next prev parent reply other threads:[~2008-01-14 6:28 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-01-14 1:45 [PATCH 000 of 6] md: various fixes for md NeilBrown
2008-01-14 1:45 ` NeilBrown
2008-01-14 1:45 ` [PATCH 001 of 6] md: Fix an occasional deadlock in raid5 NeilBrown
2008-01-14 1:45 ` NeilBrown
2008-01-16 5:01 ` dean gaudet
2008-01-16 5:54 ` Andrew Morton
2008-01-16 6:13 ` dean gaudet
2008-01-16 7:09 ` Dan Williams
2008-01-16 7:15 ` Andrew Morton
2008-01-16 21:54 ` Neil Brown
2008-01-14 1:45 ` [PATCH 002 of 6] md: Fix use-after-free bug when dropping an rdev from an md array NeilBrown
2008-01-14 1:45 ` NeilBrown
2008-01-14 2:04 ` Al Viro
2008-01-14 3:21 ` Neil Brown
2008-01-14 3:43 ` Al Viro
2008-01-14 4:48 ` Neil Brown
2008-01-14 6:28 ` Neil Brown [this message]
2008-01-14 12:59 ` Al Viro
2008-01-14 13:56 ` Al Viro
2008-01-14 1:45 ` [PATCH 003 of 6] md: Change a few 'int' to 'size_t' in md NeilBrown
2008-01-14 1:45 ` [PATCH 004 of 6] md: Change INTERATE_MDDEV to for_each_mddev NeilBrown
2008-01-14 1:45 ` [PATCH 005 of 6] md: Change ITERATE_RDEV to rdev_for_each NeilBrown
2008-01-14 1:45 ` [PATCH 006 of 6] md: Change ITERATE_RDEV_GENERIC to rdev_for_each_list, and remove ITERATE_RDEV_PENDING NeilBrown
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=18315.284.774998.348672@notabene.brown \
--to=neilb@suse.de \
--cc=akpm@linux-foundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-raid@vger.kernel.org \
--cc=viro@ZenIV.linux.org.uk \
/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.