diff mbox

block: protect rw_page against device teardown

Message ID 20151120001403.27823.74467.stgit@dwillia2-desk3.jf.intel.com (mailing list archive)
State Superseded
Headers show

Commit Message

Dan Williams Nov. 20, 2015, 12:14 a.m. UTC
Fix use after free crashes like the following:

 general protection fault: 0000 [#1] SMP
 Call Trace:
  [<ffffffffa0050216>] ? pmem_do_bvec.isra.12+0xa6/0xf0 [nd_pmem]
  [<ffffffffa0050ba2>] pmem_rw_page+0x42/0x80 [nd_pmem]
  [<ffffffff8128fd90>] bdev_read_page+0x50/0x60
  [<ffffffff812972f0>] do_mpage_readpage+0x510/0x770
  [<ffffffff8128fd20>] ? I_BDEV+0x20/0x20
  [<ffffffff811d86dc>] ? lru_cache_add+0x1c/0x50
  [<ffffffff81297657>] mpage_readpages+0x107/0x170
  [<ffffffff8128fd20>] ? I_BDEV+0x20/0x20
  [<ffffffff8128fd20>] ? I_BDEV+0x20/0x20
  [<ffffffff8129058d>] blkdev_readpages+0x1d/0x20
  [<ffffffff811d615f>] __do_page_cache_readahead+0x28f/0x310
  [<ffffffff811d6039>] ? __do_page_cache_readahead+0x169/0x310
  [<ffffffff811c5abd>] ? pagecache_get_page+0x2d/0x1d0
  [<ffffffff811c76f6>] filemap_fault+0x396/0x530
  [<ffffffff811f816e>] __do_fault+0x4e/0xf0
  [<ffffffff811fce7d>] handle_mm_fault+0x11bd/0x1b50

Cc: <stable@vger.kernel.org>
Cc: Jens Axboe <axboe@fb.com>
Cc: Matthew Wilcox <willy@linux.intel.com>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 fs/block_dev.c |   18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

Comments

kernel test robot Nov. 20, 2015, 12:32 a.m. UTC | #1
Hi Dan,

[auto build test ERROR on: block/for-next]
[also build test ERROR on: v4.4-rc1 next-20151119]

url:    https://github.com/0day-ci/linux/commits/Dan-Williams/block-protect-rw_page-against-device-teardown/20151120-081807
base:   https://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git for-next
config: xtensa-common_defconfig (attached as .config)
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=xtensa 

All errors (new ones prefixed by >>):

   fs/block_dev.c: In function 'bdev_read_page':
>> fs/block_dev.c:389:2: error: implicit declaration of function 'blk_queue_enter' [-Werror=implicit-function-declaration]
     rc = blk_queue_enter(bdev->bd_queue, GFP_KERNEL);
     ^
>> fs/block_dev.c:393:2: error: implicit declaration of function 'blk_queue_exit' [-Werror=implicit-function-declaration]
     blk_queue_exit(bdev->bd_queue);
     ^
   cc1: some warnings being treated as errors

vim +/blk_queue_enter +389 fs/block_dev.c

   383		const struct block_device_operations *ops = bdev->bd_disk->fops;
   384		int rc = -EOPNOTSUPP;
   385	
   386		if (!ops->rw_page || bdev_get_integrity(bdev))
   387			return rc;
   388	
 > 389		rc = blk_queue_enter(bdev->bd_queue, GFP_KERNEL);
   390		if (rc)
   391			return rc;
   392		rc = ops->rw_page(bdev, sector + get_start_sect(bdev), page, READ);
 > 393		blk_queue_exit(bdev->bd_queue);
   394		return rc;
   395	}
   396	EXPORT_SYMBOL_GPL(bdev_read_page);

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
diff mbox

Patch

diff --git a/fs/block_dev.c b/fs/block_dev.c
index bb0dfb1c7af1..cc0af12acf94 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -390,9 +390,17 @@  int bdev_read_page(struct block_device *bdev, sector_t sector,
 			struct page *page)
 {
 	const struct block_device_operations *ops = bdev->bd_disk->fops;
+	int rc = -EOPNOTSUPP;
+
 	if (!ops->rw_page || bdev_get_integrity(bdev))
-		return -EOPNOTSUPP;
-	return ops->rw_page(bdev, sector + get_start_sect(bdev), page, READ);
+		return rc;
+
+	rc = blk_queue_enter(bdev->bd_queue, GFP_KERNEL);
+	if (rc)
+		return rc;
+	rc = ops->rw_page(bdev, sector + get_start_sect(bdev), page, READ);
+	blk_queue_exit(bdev->bd_queue);
+	return rc;
 }
 EXPORT_SYMBOL_GPL(bdev_read_page);
 
@@ -421,14 +429,20 @@  int bdev_write_page(struct block_device *bdev, sector_t sector,
 	int result;
 	int rw = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : WRITE;
 	const struct block_device_operations *ops = bdev->bd_disk->fops;
+
 	if (!ops->rw_page || bdev_get_integrity(bdev))
 		return -EOPNOTSUPP;
+	result = blk_queue_enter(bdev->bd_queue, GFP_KERNEL);
+	if (result)
+		return result;
+
 	set_page_writeback(page);
 	result = ops->rw_page(bdev, sector + get_start_sect(bdev), page, rw);
 	if (result)
 		end_page_writeback(page);
 	else
 		unlock_page(page);
+	blk_queue_exit(bdev->bd_queue);
 	return result;
 }
 EXPORT_SYMBOL_GPL(bdev_write_page);