[PATCH] UBUNTU: [Upstream] mmc: prevent dangling block device from accessing stale queues

From: Stefan Bader
Date: Wed Jun 03 2009 - 14:17:31 EST


BugLink: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/383668

When the mmc subsytem removes the block device (e.g. for suspend), it will
call mmc_cleanup_queue to release the block device request queue.
However the gendisk struct still has a pointer to that queue which is not
accounted for. If the block device is still open, the gendisk struct will
not get freed and might still use the stale pointer.
This gets even worse for the fact that (in this case) on resume, a new block
device is created which gets the same request queue object from the cache.
Now any stray access to that old block device end up on the new one.
As the functions to get and put the blk queue are not exported, the fix will
delay the actual call to blk_cleanup_queue until the last user of the mmc
block device drops its reference. Until then the blk queue is present but
will reject any I/O.

Signed-off-by: Stefan Bader <stefan.bader@xxxxxxxxxxxxx>
---
drivers/mmc/card/block.c | 6 ++++++
drivers/mmc/card/queue.c | 7 ++++++-
2 files changed, 12 insertions(+), 1 deletions(-)

diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 014b271..69d7cec 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -88,6 +88,12 @@ static void mmc_blk_put(struct mmc_blk_data *md)
int devidx = MINOR(disk_devt(md->disk)) >> MMC_SHIFT;
__clear_bit(devidx, dev_use);

+ /*
+ * We are about to drop the last reference to the disk object.
+ * Nothing else should now be looking at the queue pointer, so
+ * now it won't hurt if we release it.
+ */
+ blk_cleanup_queue(md->disk->queue);
put_disk(md->disk);
kfree(md);
}
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 4978562..163cc28 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -256,7 +256,12 @@ void mmc_cleanup_queue(struct mmc_queue *mq)
kfree(mq->bounce_buf);
mq->bounce_buf = NULL;

- blk_cleanup_queue(mq->queue);
+ /*
+ * Calling blk_cleanup_queue() would be too soon here. As long as
+ * the gendisk has a reference to it and is not released we should
+ * keep the queue. It has been shutdown and will not accept any new
+ * requests, so that should be safe.
+ */

mq->card = NULL;
}
--
1.6.3.1


--------------060807030900020201040907--
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/