diff options
author | Eric Wheeler <git@linux.ewheeler.net> | 2016-02-26 17:33:56 -0500 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2016-03-08 11:19:08 -0500 |
commit | 9b299728ed777428b3908ac72ace5f8f84b97789 (patch) | |
tree | 5320279c9809787d11a8c735b4173b2c19374292 | |
parent | 07cc6ef8edc47f8b4fc1e276d31127a0a5863d4d (diff) |
bcache: cleaned up error handling around register_cache()
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>
Cc: <stable@vger.kernel.org>
-rw-r--r-- | drivers/md/bcache/super.c | 34 |
1 files changed, 22 insertions, 12 deletions
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index b411c73bfeb3..6b07a0c8c729 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c | |||
@@ -1835,11 +1835,12 @@ static int cache_alloc(struct cache_sb *sb, struct cache *ca) | |||
1835 | return 0; | 1835 | return 0; |
1836 | } | 1836 | } |
1837 | 1837 | ||
1838 | static void register_cache(struct cache_sb *sb, struct page *sb_page, | 1838 | static int register_cache(struct cache_sb *sb, struct page *sb_page, |
1839 | struct block_device *bdev, struct cache *ca) | 1839 | struct block_device *bdev, struct cache *ca) |
1840 | { | 1840 | { |
1841 | char name[BDEVNAME_SIZE]; | 1841 | char name[BDEVNAME_SIZE]; |
1842 | const char *err = "cannot allocate memory"; | 1842 | const char *err = NULL; |
1843 | int ret = 0; | ||
1843 | 1844 | ||
1844 | memcpy(&ca->sb, sb, sizeof(struct cache_sb)); | 1845 | memcpy(&ca->sb, sb, sizeof(struct cache_sb)); |
1845 | ca->bdev = bdev; | 1846 | ca->bdev = bdev; |
@@ -1854,27 +1855,35 @@ static void register_cache(struct cache_sb *sb, struct page *sb_page, | |||
1854 | if (blk_queue_discard(bdev_get_queue(ca->bdev))) | 1855 | if (blk_queue_discard(bdev_get_queue(ca->bdev))) |
1855 | ca->discard = CACHE_DISCARD(&ca->sb); | 1856 | ca->discard = CACHE_DISCARD(&ca->sb); |
1856 | 1857 | ||
1857 | if (cache_alloc(sb, ca) != 0) | 1858 | ret = cache_alloc(sb, ca); |
1859 | if (ret != 0) | ||
1858 | goto err; | 1860 | goto err; |
1859 | 1861 | ||
1860 | err = "error creating kobject"; | 1862 | if (kobject_add(&ca->kobj, &part_to_dev(bdev->bd_part)->kobj, "bcache")) { |
1861 | if (kobject_add(&ca->kobj, &part_to_dev(bdev->bd_part)->kobj, "bcache")) | 1863 | err = "error calling kobject_add"; |
1862 | goto err; | 1864 | ret = -ENOMEM; |
1865 | goto out; | ||
1866 | } | ||
1863 | 1867 | ||
1864 | mutex_lock(&bch_register_lock); | 1868 | mutex_lock(&bch_register_lock); |
1865 | err = register_cache_set(ca); | 1869 | err = register_cache_set(ca); |
1866 | mutex_unlock(&bch_register_lock); | 1870 | mutex_unlock(&bch_register_lock); |
1867 | 1871 | ||
1868 | if (err) | 1872 | if (err) { |
1869 | goto err; | 1873 | ret = -ENODEV; |
1874 | goto out; | ||
1875 | } | ||
1870 | 1876 | ||
1871 | pr_info("registered cache device %s", bdevname(bdev, name)); | 1877 | pr_info("registered cache device %s", bdevname(bdev, name)); |
1878 | |||
1872 | out: | 1879 | out: |
1873 | kobject_put(&ca->kobj); | 1880 | kobject_put(&ca->kobj); |
1874 | return; | 1881 | |
1875 | err: | 1882 | err: |
1876 | pr_notice("error opening %s: %s", bdevname(bdev, name), err); | 1883 | if (err) |
1877 | goto out; | 1884 | pr_notice("error opening %s: %s", bdevname(bdev, name), err); |
1885 | |||
1886 | return ret; | ||
1878 | } | 1887 | } |
1879 | 1888 | ||
1880 | /* Global interfaces/init */ | 1889 | /* Global interfaces/init */ |
@@ -1972,7 +1981,8 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr, | |||
1972 | if (!ca) | 1981 | if (!ca) |
1973 | goto err_close; | 1982 | goto err_close; |
1974 | 1983 | ||
1975 | register_cache(sb, sb_page, bdev, ca); | 1984 | if (register_cache(sb, sb_page, bdev, ca) != 0) |
1985 | goto err_close; | ||
1976 | } | 1986 | } |
1977 | out: | 1987 | out: |
1978 | if (sb_page) | 1988 | if (sb_page) |