[PATCH] loopback device can't act as its backing store

From: Franz Pletz
Date: Fri Dec 03 2004 - 14:58:57 EST


The patch below fixes a bug in loop which apparently causes the kernel to call
the initialization routine of a loopback device recursively while trying to set
the backing store to the loopback device it's being mapped to.

Ludwig Schmidt <ludoschmidt@xxxxxx> found this misbehaviour by accident. After
having been informed by him, I analyzed the problem and wrote this patch.

You can verify this bug for instance by issuing the following command
# mount -o loop /dev/loop0 /mnt
with /dev/loop0 being the first free loop device. You should sync before. ;-)

However, if you try setting the backing file of the loopback device using the
losetup utility, you won't experience any crash. For example:
# losetup /dev/loop0 /dev/loop0

But as a matter of fact, the device will be busy until the next reboot. Forced
unloading of loop will succeed. But after reloading, the kernel will lock up on
any attempt accessing a loop device.
Consequently this bug needs to be resolved in any case, although it seems that
there may also be a bug in the mount utility. By looking at the source code of
mount, which ironically shares the same codebase as losetup within the
util-linux package, I couldn't find anything suspicious.

This bug is fully reproduceable on at least all recent 2.6 series kernels.
The patch below applies cleanly on 2.6.10-rc2.

Comments would be graciously appreciated as this being my first serious kernel
patch. ;-)


Signed-off-by: Franz Pletz <franz_pletz@xxxxxxxxxxx>

linux/drivers/block/loop.c | 7 +++++++
1 files changed, 7 insertions(+)

--- linux-2.6.10-rc2/drivers/block/loop.c 2004-11-25 19:56:32.000000000 +0100
+++ linux/drivers/block/loop.c 2004-12-02 23:39:43.516913144 +0100
@@ -596,6 +596,9 @@
old_file = lo->lo_backing_file;

error = -EINVAL;
+ /* new backing store mustn't be the loop device it's being mapped to */
+ if(inode->i_rdev == bdev->bd_dev)
+ goto out_putf;

if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))
goto out_putf;
@@ -652,6 +655,10 @@
lo_flags |= LO_FLAGS_READ_ONLY;

error = -EINVAL;
+ /* new backing store mustn't be the loop device it's being mapped to */
+ if(inode->i_rdev == bdev->bd_dev)
+ goto out_putf;
+
if (S_ISREG(inode->i_mode) || S_ISBLK(inode->i_mode)) {
struct address_space_operations *aops = mapping->a_ops;
/*
-
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/