[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1350757943-24981-3-git-send-email-hannes@stressinduktion.org>
Date: Sat, 20 Oct 2012 20:32:21 +0200
From: Hannes Frederic Sowa <hannes@...essinduktion.org>
To: linux-kernel@...r.kernel.org
Cc: Hannes Frederic Sowa <hannes@...essinduktion.org>,
Nick Piggin <npiggin@...nel.dk>
Subject: [PATCH 2/4] brd: check for open partitions when BLKFLSBUFing a ram disk
Users of partitions on ram disks could accidentally flush the block
device with ioctl(BLKFLSBUF) while it is in use. This patch prevents
this from happening.
This patch also adds a call to rescan_partitions after BLKFLSBUFing,
for which a EXPORT_SYMBOL_GPL statement was needed. Otherwise some kind
of use-after-free could happen.
After this change BLKFLSBUFing on partitions of a ram disk is never
possible.
Cc: Nick Piggin <npiggin@...nel.dk>
Signed-off-by: Hannes Frederic Sowa <hannes@...essinduktion.org>
---
block/partition-generic.c | 1 +
drivers/block/brd.c | 20 +++++++++++++++++---
2 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/block/partition-generic.c b/block/partition-generic.c
index f1d1451..cd7bc10 100644
--- a/block/partition-generic.c
+++ b/block/partition-generic.c
@@ -528,6 +528,7 @@ rescan:
kfree(state);
return 0;
}
+EXPORT_SYMBOL_GPL(rescan_partitions);
int invalidate_partitions(struct gendisk *disk, struct block_device *bdev)
{
diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index c4965f5..ce1255c 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -385,6 +385,13 @@ static int brd_direct_access(struct block_device *bdev, sector_t sector,
}
#endif
+static int brd_blkdev_in_use(struct block_device *bdev)
+{
+ lockdep_assert_held(&bdev->bd_mutex);
+ return bdev->bd_part_count > 0
+ || bdev->bd_openers > 1;
+}
+
static int brd_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
@@ -399,9 +406,15 @@ static int brd_ioctl(struct block_device *bdev, fmode_t mode,
* release and destroy the ramdisk data.
*/
mutex_lock(&brd_mutex);
+ if (bdget_disk(brd->brd_disk, 0) != bdev) {
+ error = -EBUSY;
+ goto out;
+ }
mutex_lock(&bdev->bd_mutex);
- error = -EBUSY;
- if (bdev->bd_openers <= 1) {
+ error = brd_blkdev_in_use(bdev);
+ if (error) {
+ error = -EBUSY;
+ } else {
/*
* Kill the cache first, so it isn't written back to the
* device.
@@ -411,9 +424,10 @@ static int brd_ioctl(struct block_device *bdev, fmode_t mode,
*/
kill_bdev(bdev);
brd_free_pages(brd);
- error = 0;
+ error = rescan_partitions(brd->brd_disk, bdev);
}
mutex_unlock(&bdev->bd_mutex);
+out:
mutex_unlock(&brd_mutex);
return error;
--
1.7.12.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists