Hi, I clearly can reproduce the issue on 3.3 and 3.8, but not on 3.0. I think the issue appeared around v3.2 time. I am trying to bisect it and give you more info later. On Mon, Apr 1, 2013 at 5:26 PM, <gregkh@xxxxxxxxxxxxxxxxxxx> wrote: > > This is a note to let you know that I've just added the patch titled > > loop: prevent bdev freeing while device in use > > to the 3.0-stable tree which can be found at: > http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary > > The filename of the patch is: > loop-prevent-bdev-freeing-while-device-in-use.patch > and it can be found in the queue-3.0 subdirectory. > > If you, or anyone else, feels it should not be added to the stable tree, > please let <stable@xxxxxxxxxxxxxxx> know about it. > > > From c1681bf8a7b1b98edee8b862a42c19c4e53205fd Mon Sep 17 00:00:00 2001 > From: Anatol Pomozov <anatol.pomozov@xxxxxxxxx> > Date: Mon, 1 Apr 2013 09:47:56 -0700 > Subject: loop: prevent bdev freeing while device in use > > From: Anatol Pomozov <anatol.pomozov@xxxxxxxxx> > > commit c1681bf8a7b1b98edee8b862a42c19c4e53205fd upstream. > > struct block_device lifecycle is defined by its inode (see fs/block_dev.c) - > block_device allocated first time we access /dev/loopXX and deallocated on > bdev_destroy_inode. When we create the device "losetup /dev/loopXX afile" > we want that block_device stay alive until we destroy the loop device > with "losetup -d". > > But because we do not hold /dev/loopXX inode its counter goes 0, and > inode/bdev can be destroyed at any moment. Usually it happens at memory > pressure or when user drops inode cache (like in the test below). When later in > loop_clr_fd() we want to use bdev we have use-after-free error with following > stack: > > BUG: unable to handle kernel NULL pointer dereference at 0000000000000280 > bd_set_size+0x10/0xa0 > loop_clr_fd+0x1f8/0x420 [loop] > lo_ioctl+0x200/0x7e0 [loop] > lo_compat_ioctl+0x47/0xe0 [loop] > compat_blkdev_ioctl+0x341/0x1290 > do_filp_open+0x42/0xa0 > compat_sys_ioctl+0xc1/0xf20 > do_sys_open+0x16e/0x1d0 > sysenter_dispatch+0x7/0x1a > > To prevent use-after-free we need to grab the device in loop_set_fd() > and put it later in loop_clr_fd(). > > The issue is reprodusible on current Linus head and v3.3. Here is the test: > > dd if=/dev/zero of=loop.file bs=1M count=1 > while [ true ]; do > losetup /dev/loop0 loop.file > echo 2 > /proc/sys/vm/drop_caches > losetup -d /dev/loop0 > done > > [ Doing bdgrab/bput in loop_set_fd/loop_clr_fd is safe, because every > time we call loop_set_fd() we check that loop_device->lo_state is > Lo_unbound and set it to Lo_bound If somebody will try to set_fd again > it will get EBUSY. And if we try to loop_clr_fd() on unbound loop > device we'll get ENXIO. > > loop_set_fd/loop_clr_fd (and any other loop ioctl) is called under > loop_device->lo_ctl_mutex. ] > > Signed-off-by: Anatol Pomozov <anatol.pomozov@xxxxxxxxx> > Cc: Al Viro <viro@xxxxxxxxxxxxxxxxxx> > Signed-off-by: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx> > Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> > > --- > drivers/block/loop.c | 9 ++++++++- > fs/block_dev.c | 1 + > 2 files changed, 9 insertions(+), 1 deletion(-) > > --- a/drivers/block/loop.c > +++ b/drivers/block/loop.c > @@ -928,6 +928,11 @@ static int loop_set_fd(struct loop_devic > wake_up_process(lo->lo_thread); > if (max_part > 0) > ioctl_by_bdev(bdev, BLKRRPART, 0); > + > + /* Grab the block_device to prevent its destruction after we > + * put /dev/loopXX inode. Later in loop_clr_fd() we bdput(bdev). > + */ > + bdgrab(bdev); > return 0; > > out_clr: > @@ -1024,8 +1029,10 @@ static int loop_clr_fd(struct loop_devic > memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE); > memset(lo->lo_crypt_name, 0, LO_NAME_SIZE); > memset(lo->lo_file_name, 0, LO_NAME_SIZE); > - if (bdev) > + if (bdev) { > + bdput(bdev); > invalidate_bdev(bdev); > + } > set_capacity(lo->lo_disk, 0); > loop_sysfs_exit(lo); > if (bdev) { > --- a/fs/block_dev.c > +++ b/fs/block_dev.c > @@ -576,6 +576,7 @@ struct block_device *bdgrab(struct block > ihold(bdev->bd_inode); > return bdev; > } > +EXPORT_SYMBOL(bdgrab); > > long nr_blockdev_pages(void) > { > > > Patches currently in stable-queue which might be from anatol.pomozov@xxxxxxxxx are > > queue-3.0/loop-prevent-bdev-freeing-while-device-in-use.patch -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html