linux/drivers/mtd
Brian Norris 9ea0602697 mtd: blkdevs: fix potential deadlock + lockdep warnings
commit f3c63795e9 upstream.

Commit 073db4a51e ("mtd: fix: avoid race condition when accessing
mtd->usecount") fixed a race condition but due to poor ordering of the
mutex acquisition, introduced a potential deadlock.

The deadlock can occur, for example, when rmmod'ing the m25p80 module, which
will delete one or more MTDs, along with any corresponding mtdblock
devices. This could potentially race with an acquisition of the block
device as follows.

 -> blktrans_open()
    ->  mutex_lock(&dev->lock);
    ->  mutex_lock(&mtd_table_mutex);

 -> del_mtd_device()
    ->  mutex_lock(&mtd_table_mutex);
    ->  blktrans_notify_remove() -> del_mtd_blktrans_dev()
       ->  mutex_lock(&dev->lock);

This is a classic (potential) ABBA deadlock, which can be fixed by
making the A->B ordering consistent everywhere. There was no real
purpose to the ordering in the original patch, AFAIR, so this shouldn't
be a problem. This ordering was actually already present in
del_mtd_blktrans_dev(), for one, where the function tried to ensure that
its caller already held mtd_table_mutex before it acquired &dev->lock:

        if (mutex_trylock(&mtd_table_mutex)) {
                mutex_unlock(&mtd_table_mutex);
                BUG();
        }

So, reverse the ordering of acquisition of &dev->lock and &mtd_table_mutex so
we always acquire mtd_table_mutex first.

Snippets of the lockdep output follow:

  # modprobe -r m25p80
  [   53.419251]
  [   53.420838] ======================================================
  [   53.427300] [ INFO: possible circular locking dependency detected ]
  [   53.433865] 4.3.0-rc6 #96 Not tainted
  [   53.437686] -------------------------------------------------------
  [   53.444220] modprobe/372 is trying to acquire lock:
  [   53.449320]  (&new->lock){+.+...}, at: [<c043fe4c>] del_mtd_blktrans_dev+0x80/0xdc
  [   53.457271]
  [   53.457271] but task is already holding lock:
  [   53.463372]  (mtd_table_mutex){+.+.+.}, at: [<c0439994>] del_mtd_device+0x18/0x100
  [   53.471321]
  [   53.471321] which lock already depends on the new lock.
  [   53.471321]
  [   53.479856]
  [   53.479856] the existing dependency chain (in reverse order) is:
  [   53.487660]
  -> #1 (mtd_table_mutex){+.+.+.}:
  [   53.492331]        [<c043fc5c>] blktrans_open+0x34/0x1a4
  [   53.497879]        [<c01afce0>] __blkdev_get+0xc4/0x3b0
  [   53.503364]        [<c01b0bb8>] blkdev_get+0x108/0x320
  [   53.508743]        [<c01713c0>] do_dentry_open+0x218/0x314
  [   53.514496]        [<c0180454>] path_openat+0x4c0/0xf9c
  [   53.519959]        [<c0182044>] do_filp_open+0x5c/0xc0
  [   53.525336]        [<c0172758>] do_sys_open+0xfc/0x1cc
  [   53.530716]        [<c000f740>] ret_fast_syscall+0x0/0x1c
  [   53.536375]
  -> #0 (&new->lock){+.+...}:
  [   53.540587]        [<c063f124>] mutex_lock_nested+0x38/0x3cc
  [   53.546504]        [<c043fe4c>] del_mtd_blktrans_dev+0x80/0xdc
  [   53.552606]        [<c043f164>] blktrans_notify_remove+0x7c/0x84
  [   53.558891]        [<c04399f0>] del_mtd_device+0x74/0x100
  [   53.564544]        [<c043c670>] del_mtd_partitions+0x80/0xc8
  [   53.570451]        [<c0439aa0>] mtd_device_unregister+0x24/0x48
  [   53.576637]        [<c046ce6c>] spi_drv_remove+0x1c/0x34
  [   53.582207]        [<c03de0f0>] __device_release_driver+0x88/0x114
  [   53.588663]        [<c03de19c>] device_release_driver+0x20/0x2c
  [   53.594843]        [<c03dd9e8>] bus_remove_device+0xd8/0x108
  [   53.600748]        [<c03dacc0>] device_del+0x10c/0x210
  [   53.606127]        [<c03dadd0>] device_unregister+0xc/0x20
  [   53.611849]        [<c046d878>] __unregister+0x10/0x20
  [   53.617211]        [<c03da868>] device_for_each_child+0x50/0x7c
  [   53.623387]        [<c046eae8>] spi_unregister_master+0x58/0x8c
  [   53.629578]        [<c03e12f0>] release_nodes+0x15c/0x1c8
  [   53.635223]        [<c03de0f8>] __device_release_driver+0x90/0x114
  [   53.641689]        [<c03de900>] driver_detach+0xb4/0xb8
  [   53.647147]        [<c03ddc78>] bus_remove_driver+0x4c/0xa0
  [   53.652970]        [<c00cab50>] SyS_delete_module+0x11c/0x1e4
  [   53.658976]        [<c000f740>] ret_fast_syscall+0x0/0x1c
  [   53.664621]
  [   53.664621] other info that might help us debug this:
  [   53.664621]
  [   53.672979]  Possible unsafe locking scenario:
  [   53.672979]
  [   53.679169]        CPU0                    CPU1
  [   53.683900]        ----                    ----
  [   53.688633]   lock(mtd_table_mutex);
  [   53.692383]                                lock(&new->lock);
  [   53.698306]                                lock(mtd_table_mutex);
  [   53.704658]   lock(&new->lock);
  [   53.707946]
  [   53.707946]  *** DEADLOCK ***

Fixes: 073db4a51e ("mtd: fix: avoid race condition when accessing mtd->usecount")
Reported-by: Felipe Balbi <balbi@ti.com>
Tested-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Signed-off-by: Luis Henriques <luis.henriques@canonical.com>
History 2015-12-13 17:49:00 +00:00
..
chips mtd: cfi_cmdset_0001.c: fix resume for LH28F640BF chips 2014-11-13 11:48:57 +00:00
devices mtd: m25p80,spi-nor: Fix module aliases for m25p80 2014-11-13 11:48:34 +00:00
lpddr mtd: lpddr: fix Kconfig dependency, for I/O accessors 2014-05-26 10:38:25 -07:00
maps mtd: dc21285: use raw spinlock functions for nw_gpio_lock 2015-07-15 10:01:21 +01:00
nand mtd: pxa3xx_nand: add a default chunk size 2015-09-30 13:20:45 +01:00
onenand mtd: onenand: fix build warning for dma type 2014-05-20 16:35:31 -07:00
spi-nor mtd: m25p80,spi-nor: Fix module aliases for m25p80 2014-11-13 11:48:34 +00:00
tests mtd: tests: abort torturetest on erase errors 2015-01-15 10:44:05 +00:00
ubi UBI: return ENOSPC if no enough space available 2015-10-19 15:47:00 +01:00
afs.c mtd: make register_mtd_parser return void 2014-01-03 11:22:22 -08:00
ar7part.c mtd: make register_mtd_parser return void 2014-01-03 11:22:22 -08:00
bcm47xxpart.c mtd: bcm47xxpart: allow enabling on ARCH_BCM_5301X 2014-03-10 22:42:29 -07:00
bcm63xxpart.c mtd: make register_mtd_parser return void 2014-01-03 11:22:22 -08:00
cmdlinepart.c mtd: make register_mtd_parser return void 2014-01-03 11:22:22 -08:00
ftl.c mtd/ftl: fix the double free of the buffers allocated in build_maps() 2014-09-17 09:22:20 -07:00
inftlcore.c mtd: nand: add a helper to detect the nand type 2013-10-27 16:27:06 -07:00
inftlmount.c mtd: delete non-required instances of include <linux/init.h> 2014-03-10 22:42:22 -07:00
Kconfig mtd: spi-nor: add the framework for SPI NOR 2014-04-14 11:22:58 -07:00
Makefile mtd: spi-nor: shorten Kconfig naming 2014-04-14 11:23:01 -07:00
mtd_blkdevs.c mtd: blkdevs: fix potential deadlock + lockdep warnings 2015-12-13 17:49:00 +00:00
mtdblock.c mtd: Move major number definitions to major.h 2013-11-06 23:32:59 -08:00
mtdblock_ro.c mtd: Move major number definitions to major.h 2013-11-06 23:32:59 -08:00
mtdchar.c mtd: Fix warning in access_ok() parameter passing 2014-05-20 16:35:29 -07:00
mtdconcat.c mtd: unify initialization of erase_info->fail_addr 2012-03-27 01:02:24 +01:00
mtdcore.c mtd: Fix the behavior of OTP write if there is not enough room for data 2014-03-10 22:42:31 -07:00
mtdcore.h mtd: merge mtdchar module with mtdcore 2013-04-05 13:16:54 +01:00
mtdoops.c mtdoops: don't erase flash at each boot 2012-11-15 15:37:51 +02:00
mtdpart.c mtd: mtdpart: fix add_mtd_partitions error path 2015-12-09 11:40:58 +00:00
mtdsuper.c mtd: Move major number definitions to major.h 2013-11-06 23:32:59 -08:00
mtdswap.c mtd: mtdswap: replace strict_strtoul() with kstrtoul() 2013-08-30 21:52:51 +01:00
nftlcore.c mtd: nand: add a helper to detect the nand type 2013-10-27 16:27:06 -07:00
nftlmount.c mtd: introduce mtd_block_markbad interface 2012-01-09 18:25:48 +00:00
ofpart.c mtd: make register_mtd_parser return void 2014-01-03 11:22:22 -08:00
redboot.c mtd: make register_mtd_parser return void 2014-01-03 11:22:22 -08:00
rfd_ftl.c mtd: remove some duplicative checks 2014-03-10 22:42:25 -07:00
sm_ftl.c mtd: sm_ftl: heap corruption in sm_create_sysfs_attributes() 2014-03-10 22:42:21 -07:00
sm_ftl.h mtd: sm_ftl: cosmetic, use bool when possible 2010-10-25 01:33:08 +01:00
ssfdc.c mtd: nand: add a helper to detect the nand type 2013-10-27 16:27:06 -07:00