mtd: fix: avoid race condition when accessing mtd->usecount

Linux-MTD Mailing List linux-mtd at lists.infradead.org
Tue Jun 23 10:59:03 PDT 2015


Gitweb:     http://git.infradead.org/?p=mtd-2.6.git;a=commit;h=073db4a51ee43ccb827f54a4261c0583b028d5ab
Commit:     073db4a51ee43ccb827f54a4261c0583b028d5ab
Parent:     5844feeaa4154d1c46d3462c7a4653d22356d8b4
Author:     Brian Norris <computersforpeace at gmail.com>
AuthorDate: Thu May 7 17:55:16 2015 -0700
Committer:  Brian Norris <computersforpeace at gmail.com>
CommitDate: Tue May 12 10:59:53 2015 -0700

    mtd: fix: avoid race condition when accessing mtd->usecount
    
    On A MIPS 32-cores machine a BUG_ON was triggered because some acesses to
    mtd->usecount were done without taking mtd_table_mutex.
    kernel: Call Trace:
    kernel: [<ffffffff80401818>] __put_mtd_device+0x20/0x50
    kernel: [<ffffffff804086f4>] blktrans_release+0x8c/0xd8
    kernel: [<ffffffff802577e0>] __blkdev_put+0x1a8/0x200
    kernel: [<ffffffff802579a4>] blkdev_close+0x1c/0x30
    kernel: [<ffffffff8022006c>] __fput+0xac/0x250
    kernel: [<ffffffff80171208>] task_work_run+0xd8/0x120
    kernel: [<ffffffff8012c23c>] work_notifysig+0x10/0x18
    kernel:
    kernel:
            Code: 2442ffff  ac8202d8  000217fe <00020336> dc820128  10400003
                   00000000  0040f809  00000000
    kernel: ---[ end trace 080fbb4579b47a73 ]---
    
    Fixed by taking the mutex in blktrans_open and blktrans_release.
    
    Note that this locking is already suggested in
    include/linux/mtd/blktrans.h:
    
    struct mtd_blktrans_ops {
    ...
    	/* Called with mtd_table_mutex held; no race with add/remove */
    	int (*open)(struct mtd_blktrans_dev *dev);
    	void (*release)(struct mtd_blktrans_dev *dev);
    ...
    };
    
    But we weren't following it.
    
    Originally reported by (and patched by) Zhang and Giuseppe,
    independently. Improved and rewritten.
    
    Cc: stable at vger.kernel.org
    Reported-by: Zhang Xingcai <zhangxingcai at huawei.com>
    Reported-by: Giuseppe Cantavenera <giuseppe.cantavenera.ext at nokia.com>
    Tested-by: Giuseppe Cantavenera <giuseppe.cantavenera.ext at nokia.com>
    Acked-by: Alexander Sverdlin <alexander.sverdlin at nokia.com>
    Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 drivers/mtd/mtd_blkdevs.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 2b0c5287..df7c6c7 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -197,6 +197,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
 		return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/
 
 	mutex_lock(&dev->lock);
+	mutex_lock(&mtd_table_mutex);
 
 	if (dev->open)
 		goto unlock;
@@ -220,6 +221,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
 
 unlock:
 	dev->open++;
+	mutex_unlock(&mtd_table_mutex);
 	mutex_unlock(&dev->lock);
 	blktrans_dev_put(dev);
 	return ret;
@@ -230,6 +232,7 @@ error_release:
 error_put:
 	module_put(dev->tr->owner);
 	kref_put(&dev->ref, blktrans_dev_release);
+	mutex_unlock(&mtd_table_mutex);
 	mutex_unlock(&dev->lock);
 	blktrans_dev_put(dev);
 	return ret;
@@ -243,6 +246,7 @@ static void blktrans_release(struct gendisk *disk, fmode_t mode)
 		return;
 
 	mutex_lock(&dev->lock);
+	mutex_lock(&mtd_table_mutex);
 
 	if (--dev->open)
 		goto unlock;
@@ -256,6 +260,7 @@ static void blktrans_release(struct gendisk *disk, fmode_t mode)
 		__put_mtd_device(dev->mtd);
 	}
 unlock:
+	mutex_unlock(&mtd_table_mutex);
 	mutex_unlock(&dev->lock);
 	blktrans_dev_put(dev);
 }



More information about the linux-mtd-cvs mailing list