summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSlava Pestov <sp@daterainc.com>2014-06-19 15:05:59 -0700
committerJiri Slaby <jslaby@suse.cz>2014-10-31 12:14:35 +0100
commit2c30554fdfb22f41d66d6c5f4114147bc60a5fd9 (patch)
tree10d1a1d66f6ee67ff2aed5b6e7df18318024bf04 /drivers
parent64521124425139ca5a5420660d2408b4f1c4770a (diff)
bcache: fix memory corruption in init error path
commit c9a78332b42cbdcdd386a95192a716b67d1711a4 upstream. If register_cache_set() failed, we would touch ca->set after it had already been freed. Also, fix an assertion to catch this. Change-Id: I748e5f5b223e2d9b2602075dec2f997cced2394d Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/md/bcache/super.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 547c4c57b052..3a2ccf9b624b 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -1300,8 +1300,11 @@ static void cache_set_free(struct closure *cl)
bch_journal_free(c);
for_each_cache(ca, c, i)
- if (ca)
+ if (ca) {
+ ca->set = NULL;
+ c->cache[ca->sb.nr_this_dev] = NULL;
kobject_put(&ca->kobj);
+ }
free_pages((unsigned long) c->uuids, ilog2(bucket_pages(c)));
free_pages((unsigned long) c->sort, ilog2(bucket_pages(c)));
@@ -1722,8 +1725,10 @@ void bch_cache_release(struct kobject *kobj)
{
struct cache *ca = container_of(kobj, struct cache, kobj);
- if (ca->set)
+ if (ca->set) {
+ BUG_ON(ca->set->cache[ca->sb.nr_this_dev] != ca);
ca->set->cache[ca->sb.nr_this_dev] = NULL;
+ }
bch_cache_allocator_exit(ca);
@@ -1794,7 +1799,7 @@ err:
}
static void register_cache(struct cache_sb *sb, struct page *sb_page,
- struct block_device *bdev, struct cache *ca)
+ struct block_device *bdev, struct cache *ca)
{
char name[BDEVNAME_SIZE];
const char *err = "cannot allocate memory";