From c7ef44a0388a61ad030b7ab60c849f0fa2aba8a9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 1 Apr 2013 17:26:18 -0700 Subject: [PATCH] 3.4-stable patches added patches: loop-prevent-bdev-freeing-while-device-in-use.patch --- ...ent-bdev-freeing-while-device-in-use.patch | 99 +++++++++++++++++++ queue-3.4/series | 1 + 2 files changed, 100 insertions(+) create mode 100644 queue-3.4/loop-prevent-bdev-freeing-while-device-in-use.patch diff --git a/queue-3.4/loop-prevent-bdev-freeing-while-device-in-use.patch b/queue-3.4/loop-prevent-bdev-freeing-while-device-in-use.patch new file mode 100644 index 00000000000..5d3e7609b6d --- /dev/null +++ b/queue-3.4/loop-prevent-bdev-freeing-while-device-in-use.patch @@ -0,0 +1,99 @@ +From c1681bf8a7b1b98edee8b862a42c19c4e53205fd Mon Sep 17 00:00:00 2001 +From: Anatol Pomozov +Date: Mon, 1 Apr 2013 09:47:56 -0700 +Subject: loop: prevent bdev freeing while device in use + +From: Anatol Pomozov + +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 +Cc: Al Viro +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -908,6 +908,11 @@ static int loop_set_fd(struct loop_devic + lo->lo_flags |= LO_FLAGS_PARTSCAN; + if (lo->lo_flags & LO_FLAGS_PARTSCAN) + 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: +@@ -1004,8 +1009,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 +@@ -604,6 +604,7 @@ struct block_device *bdgrab(struct block + ihold(bdev->bd_inode); + return bdev; + } ++EXPORT_SYMBOL(bdgrab); + + long nr_blockdev_pages(void) + { diff --git a/queue-3.4/series b/queue-3.4/series index 260f16debf9..9662220626b 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -31,3 +31,4 @@ btrfs-don-t-drop-path-when-printing-out-tree-errors-in-scrub.patch usb-gadget-udc-core-fix-a-regression-during-gadget-driver-unbinding.patch signal-define-__arch_has_sa_restorer-so-we-know-whether-to-clear-3.0-3.2-3.4.patch kernel-signal.c-use-__arch_has_sa_restorer-instead-of-sa_restorer.patch +loop-prevent-bdev-freeing-while-device-in-use.patch -- 2.47.3