]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
bcache: cleaned up error handling around register_cache()
authorEric Wheeler <git@linux.ewheeler.net>
Fri, 26 Feb 2016 22:33:56 +0000 (14:33 -0800)
committerTim Gardner <tim.gardner@canonical.com>
Thu, 21 Apr 2016 12:52:59 +0000 (06:52 -0600)
BugLink: http://bugs.launchpad.net/bugs/1572722
commit 9b299728ed777428b3908ac72ace5f8f84b97789 upstream.

Fix null pointer dereference by changing register_cache() to return an int
instead of being void.  This allows it to return -ENOMEM or -ENODEV and
enables upper layers to handle the OOM case without NULL pointer issues.

See this thread:
  http://thread.gmane.org/gmane.linux.kernel.bcache.devel/3521

Fixes this error:
  gargamel:/sys/block/md5/bcache# echo /dev/sdh2 > /sys/fs/bcache/register

  bcache: register_cache() error opening sdh2: cannot allocate memory
  BUG: unable to handle kernel NULL pointer dereference at 00000000000009b8
  IP: [<ffffffffc05a7e8d>] cache_set_flush+0x102/0x15c [bcache]
  PGD 120dff067 PUD 1119a3067 PMD 0
  Oops: 0000 [#1] SMP
  Modules linked in: veth ip6table_filter ip6_tables
  (...)
  CPU: 4 PID: 3371 Comm: kworker/4:3 Not tainted 4.4.2-amd64-i915-volpreempt-20160213bc1 #3
  Hardware name: System manufacturer System Product Name/P8H67-M PRO, BIOS 3904 04/27/2013
  Workqueue: events cache_set_flush [bcache]
  task: ffff88020d5dc280 ti: ffff88020b6f8000 task.ti: ffff88020b6f8000
  RIP: 0010:[<ffffffffc05a7e8d>]  [<ffffffffc05a7e8d>] cache_set_flush+0x102/0x15c [bcache]

Signed-off-by: Eric Wheeler <bcache@linux.ewheeler.net>
Tested-by: Marc MERLIN <marc@merlins.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
drivers/md/bcache/super.c

index 759f3718c5a04ea52246e0aa1dca5ce4e17a1e03..2ed3bdaca54b89a7755e025d733b3e04ae1f6c8a 100644 (file)
@@ -1828,11 +1828,12 @@ static int cache_alloc(struct cache_sb *sb, struct cache *ca)
        return 0;
 }
 
-static void register_cache(struct cache_sb *sb, struct page *sb_page,
+static int register_cache(struct cache_sb *sb, struct page *sb_page,
                                struct block_device *bdev, struct cache *ca)
 {
        char name[BDEVNAME_SIZE];
-       const char *err = "cannot allocate memory";
+       const char *err = NULL;
+       int ret = 0;
 
        memcpy(&ca->sb, sb, sizeof(struct cache_sb));
        ca->bdev = bdev;
@@ -1847,27 +1848,35 @@ static void register_cache(struct cache_sb *sb, struct page *sb_page,
        if (blk_queue_discard(bdev_get_queue(ca->bdev)))
                ca->discard = CACHE_DISCARD(&ca->sb);
 
-       if (cache_alloc(sb, ca) != 0)
+       ret = cache_alloc(sb, ca);
+       if (ret != 0)
                goto err;
 
-       err = "error creating kobject";
-       if (kobject_add(&ca->kobj, &part_to_dev(bdev->bd_part)->kobj, "bcache"))
-               goto err;
+       if (kobject_add(&ca->kobj, &part_to_dev(bdev->bd_part)->kobj, "bcache")) {
+               err = "error calling kobject_add";
+               ret = -ENOMEM;
+               goto out;
+       }
 
        mutex_lock(&bch_register_lock);
        err = register_cache_set(ca);
        mutex_unlock(&bch_register_lock);
 
-       if (err)
-               goto err;
+       if (err) {
+               ret = -ENODEV;
+               goto out;
+       }
 
        pr_info("registered cache device %s", bdevname(bdev, name));
+
 out:
        kobject_put(&ca->kobj);
-       return;
+
 err:
-       pr_notice("error opening %s: %s", bdevname(bdev, name), err);
-       goto out;
+       if (err)
+               pr_notice("error opening %s: %s", bdevname(bdev, name), err);
+
+       return ret;
 }
 
 /* Global interfaces/init */
@@ -1965,7 +1974,8 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
                if (!ca)
                        goto err_close;
 
-               register_cache(sb, sb_page, bdev, ca);
+               if (register_cache(sb, sb_page, bdev, ca) != 0)
+                       goto err_close;
        }
 out:
        if (sb_page)