linux-hardened/drivers/md
Jun'ichi Nomura ae9da83f6d dm: fix thaw_bdev
This patch fixes a bd_mount_sem counter corruption bug in device-mapper.

thaw_bdev() should be called only when freeze_bdev() was called for the
device.
Otherwise, thaw_bdev() will up bd_mount_sem and corrupt the semaphore counter.
struct block_device with the corrupted semaphore may remain in slab cache
and be reused later.

Attached patch will fix it by calling unlock_fs() instead.
unlock_fs() will determine whether it should call thaw_bdev()
by checking the device is frozen or not.

Easy reproducer is:
  #!/bin/sh
  while [ 1 ]; do
     dmsetup --notable create a
     dmsetup --nolockfs suspend a
     dmsetup remove a
  done

It's not easy to see the effect of corrupted semaphore.
So I have tested with putting printk below in bdev_alloc_inode():
        if (atomic_read(&ei->bdev.bd_mount_sem.count) != 1)
                printk(KERN_DEBUG "Incorrect semaphore count = %d (%p)\n",
                        atomic_read(&ei->bdev.bd_mount_sem.count),
                        &ei->bdev);

Without the patch, I saw something like:
 Incorrect semaphore count = 17 (f2ab91c0)

With the patch, the message didn't appear.

The bug was introduced in 2.6.16 with this bug fix:

commit d9dde59ba0
Date:   Fri Feb 24 13:04:24 2006 -0800

    [PATCH] dm: missing bdput/thaw_bdev at removal

    Need to unfreeze and release bdev otherwise the bdev inode with
    inconsistent state is reused later and cause problem.

and backported to 2.6.15.5.

It occurs only in free_dev(), which is called only when the dm device is
removed.  The buggy code is executed only if md->suspended_bdev is
non-NULL and that can happen only when the device was suspended without
noflush.

Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Cc: stable@kernel.org
2007-10-20 02:01:05 +01:00
..
raid6test [PATCH] RAID6 Altivec fix 2005-09-17 11:49:58 -07:00
.gitignore gitignore: misc files 2006-01-01 22:21:50 +01:00
bitmap.c md: change bitmap_unplug and others to void functions 2007-07-17 10:23:15 -07:00
dm-bio-list.h Fix kernel buuild with (CONFIG_COMPAT && ! CONFIG_BLOCK) 2007-09-14 13:56:47 -07:00
dm-bio-record.h
dm-crypt.c dm crypt: missing kfree in ctr error path 2007-10-20 02:01:01 +01:00
dm-delay.c dm delay: fix status 2007-10-20 02:01:04 +01:00
dm-emc.c dm: emc_endio returns void 2007-10-13 09:41:03 -07:00
dm-exception-store.c dm: fix memory leak in dm_create_persistent() when starting metadata update thread fails 2007-07-18 08:38:22 -07:00
dm-hw-handler.c BUG_ON() Conversion in md/dm-hw-handler.c 2006-03-24 18:36:27 +01:00
dm-hw-handler.h dm mpath: log device name 2007-05-09 12:30:46 -07:00
dm-io.c Drop 'size' argument from bio_endio and bi_end_io 2007-10-10 09:25:57 +02:00
dm-io.h dm io: remove old interface 2007-05-09 12:30:47 -07:00
dm-ioctl.c dm io:ctl use constant struct size 2007-10-20 02:00:58 +01:00
dm-linear.c [PATCH] dm: map and endio symbolic return codes 2006-12-08 08:29:09 -08:00
dm-log.c dm log: fix resume failed log device 2007-05-09 12:30:48 -07:00
dm-log.h [PATCH] dm: log: rename complete_resync_work 2006-12-08 08:29:09 -08:00
dm-mpath-rdac.c dm mpath: rdac fix init race 2007-10-20 02:00:57 +01:00
dm-mpath.c Drop 'size' argument from bio_endio and bi_end_io 2007-10-10 09:25:57 +02:00
dm-mpath.h [PATCH] struct path: rename DM's struct path 2006-12-08 08:28:40 -08:00
dm-path-selector.c BUG_ON() Conversion in md/dm-path-selector.c 2006-03-26 18:21:58 +02:00
dm-path-selector.h [PATCH] struct path: rename DM's struct path 2006-12-08 08:28:40 -08:00
dm-raid1.c dm raid1: fix leakage 2007-10-20 02:01:01 +01:00
dm-round-robin.c dm: remove duplicate module name from error msgs 2007-07-12 15:01:08 -07:00
dm-snap.c Drop 'size' argument from bio_endio and bi_end_io 2007-10-10 09:25:57 +02:00
dm-snap.h dm: use kmem_cache macro 2007-07-12 15:01:08 -07:00
dm-stripe.c [PATCH] dm: map and endio symbolic return codes 2006-12-08 08:29:09 -08:00
dm-table.c block: convert blkdev_issue_flush() to use empty barriers 2007-10-16 11:05:02 +02:00
dm-target.c [PATCH] dm: improve error message consistency 2006-06-26 09:58:36 -07:00
dm-zero.c Drop 'size' argument from bio_endio and bi_end_io 2007-10-10 09:25:57 +02:00
dm.c dm: fix thaw_bdev 2007-10-20 02:01:05 +01:00
dm.h block: convert blkdev_issue_flush() to use empty barriers 2007-10-16 11:05:02 +02:00
faulty.c Drop 'size' argument from bio_endio and bi_end_io 2007-10-10 09:25:57 +02:00
Kconfig DM_MULTIPATH_RDAC: "scsi_normalize_sense" undefined 2007-08-24 16:10:39 -07:00
kcopyd.c dm: use kmem_cache macro 2007-07-12 15:01:08 -07:00
kcopyd.h
linear.c block: convert blkdev_issue_flush() to use empty barriers 2007-10-16 11:05:02 +02:00
Makefile Merge branch 'ioat-md-accel-for-linus' of git://lost.foo-projects.org/~dwillia2/git/iop 2007-07-13 10:52:27 -07:00
md.c Use helpers to obtain task pid in printks 2007-10-19 11:53:43 -07:00
mktables.c
multipath.c block: convert blkdev_issue_flush() to use empty barriers 2007-10-16 11:05:02 +02:00
raid0.c md: fix a bug in some never-used code. 2007-10-17 08:43:03 -07:00
raid1.c md: make sure read errors are auto-corrected during a 'check' resync in raid1 2007-10-17 08:43:03 -07:00
raid5.c block: convert blkdev_issue_flush() to use empty barriers 2007-10-16 11:05:02 +02:00
raid6.h [PATCH] RAID6 Altivec fix 2005-09-17 11:49:58 -07:00
raid6algos.c [PATCH] drivers/md/raid6algos.c: fix a NULL dereference 2006-06-23 07:43:08 -07:00
raid6altivec.uc [PATCH] RAID6 Altivec fix 2005-09-17 11:49:58 -07:00
raid6int.uc
raid6mmx.c [PATCH] md: RAID6: clean up CPUID and FPU enter/exit code 2007-03-01 14:53:36 -08:00
raid6recov.c
raid6sse1.c [PATCH] md: RAID6: clean up CPUID and FPU enter/exit code 2007-03-01 14:53:36 -08:00
raid6sse2.c [PATCH] md: RAID6: clean up CPUID and FPU enter/exit code 2007-03-01 14:53:36 -08:00
raid6x86.h [PATCH] md: RAID6: clean up CPUID and FPU enter/exit code 2007-03-01 14:53:36 -08:00
raid10.c block: convert blkdev_issue_flush() to use empty barriers 2007-10-16 11:05:02 +02:00
unroll.pl