From 165894a09dc3e185faf798ebc80b8cfe713ccee7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 28 Feb 2013 16:55:47 -0800 Subject: [PATCH] 3.8-stable patches added patches: block-fix-synchronization-and-limit-check-in-blk_alloc_devt.patch ext4-fix-possible-use-after-free-with-aio.patch firewire-add-minor-number-range-check-to-fw_device_init.patch fs-fix-possible-use-after-free-with-aio.patch idr-fix-a-subtle-bug-in-idr_get_next.patch media-cx18-ivtv-fix-regression-remove-__init-from-a-non-init-function.patch media-omap_vout-find_vma-needs-mmap_sem-held.patch media-rc-unlock-on-error-in-show_protocols.patch media-v4l-reset-subdev-v4l2_dev-field-to-null-if-registration-fails.patch nbd-fsync-and-kill-block-device-on-shutdown.patch sysctl-fix-null-checking-in-bin_dn_node_address.patch xen-blkback-do-not-leak-mode-property.patch xen-blkback-don-t-trust-the-handle-from-the-frontend.patch xen-blkback-use-balloon-pages-for-persistent-grants.patch xen-blkfront-drop-the-use-of-llist_for_each_entry_safe.patch --- ...on-and-limit-check-in-blk_alloc_devt.patch | 61 ++++++++ ...fix-possible-use-after-free-with-aio.patch | 59 ++++++++ ...number-range-check-to-fw_device_init.patch | 36 +++++ ...fix-possible-use-after-free-with-aio.patch | 39 +++++ ...idr-fix-a-subtle-bug-in-idr_get_next.patch | 73 +++++++++ ...move-__init-from-a-non-init-function.patch | 68 +++++++++ ...ap_vout-find_vma-needs-mmap_sem-held.patch | 63 ++++++++ ...rc-unlock-on-error-in-show_protocols.patch | 37 +++++ ...-field-to-null-if-registration-fails.patch | 80 ++++++++++ ...nc-and-kill-block-device-on-shutdown.patch | 91 +++++++++++ queue-3.8/series | 15 ++ ...null-checking-in-bin_dn_node_address.patch | 36 +++++ ...en-blkback-do-not-leak-mode-property.patch | 113 ++++++++++++++ ...t-trust-the-handle-from-the-frontend.patch | 38 +++++ ...-balloon-pages-for-persistent-grants.patch | 53 +++++++ ...the-use-of-llist_for_each_entry_safe.patch | 141 ++++++++++++++++++ 16 files changed, 1003 insertions(+) create mode 100644 queue-3.8/block-fix-synchronization-and-limit-check-in-blk_alloc_devt.patch create mode 100644 queue-3.8/ext4-fix-possible-use-after-free-with-aio.patch create mode 100644 queue-3.8/firewire-add-minor-number-range-check-to-fw_device_init.patch create mode 100644 queue-3.8/fs-fix-possible-use-after-free-with-aio.patch create mode 100644 queue-3.8/idr-fix-a-subtle-bug-in-idr_get_next.patch create mode 100644 queue-3.8/media-cx18-ivtv-fix-regression-remove-__init-from-a-non-init-function.patch create mode 100644 queue-3.8/media-omap_vout-find_vma-needs-mmap_sem-held.patch create mode 100644 queue-3.8/media-rc-unlock-on-error-in-show_protocols.patch create mode 100644 queue-3.8/media-v4l-reset-subdev-v4l2_dev-field-to-null-if-registration-fails.patch create mode 100644 queue-3.8/nbd-fsync-and-kill-block-device-on-shutdown.patch create mode 100644 queue-3.8/sysctl-fix-null-checking-in-bin_dn_node_address.patch create mode 100644 queue-3.8/xen-blkback-do-not-leak-mode-property.patch create mode 100644 queue-3.8/xen-blkback-don-t-trust-the-handle-from-the-frontend.patch create mode 100644 queue-3.8/xen-blkback-use-balloon-pages-for-persistent-grants.patch create mode 100644 queue-3.8/xen-blkfront-drop-the-use-of-llist_for_each_entry_safe.patch diff --git a/queue-3.8/block-fix-synchronization-and-limit-check-in-blk_alloc_devt.patch b/queue-3.8/block-fix-synchronization-and-limit-check-in-blk_alloc_devt.patch new file mode 100644 index 00000000000..1e64dd2dcf2 --- /dev/null +++ b/queue-3.8/block-fix-synchronization-and-limit-check-in-blk_alloc_devt.patch @@ -0,0 +1,61 @@ +From ce23bba842aee98092225d9576dba47c82352521 Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Wed, 27 Feb 2013 17:03:56 -0800 +Subject: block: fix synchronization and limit check in blk_alloc_devt() + +From: Tejun Heo + +commit ce23bba842aee98092225d9576dba47c82352521 upstream. + +idr allocation in blk_alloc_devt() wasn't synchronized against lookup +and removal, and its limit check was off by one - 1 << MINORBITS is +the number of minors allowed, not the maximum allowed minor. + +Add locking and rename MAX_EXT_DEVT to NR_EXT_DEVT and fix limit +checking. + +Signed-off-by: Tejun Heo +Acked-by: Jens Axboe +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + block/genhd.c | 13 +++++-------- + 1 file changed, 5 insertions(+), 8 deletions(-) + +--- a/block/genhd.c ++++ b/block/genhd.c +@@ -25,7 +25,7 @@ static DEFINE_MUTEX(block_class_lock); + struct kobject *block_depr; + + /* for extended dynamic devt allocation, currently only one major is used */ +-#define MAX_EXT_DEVT (1 << MINORBITS) ++#define NR_EXT_DEVT (1 << MINORBITS) + + /* For extended devt allocation. ext_devt_mutex prevents look up + * results from going away underneath its user. +@@ -424,19 +424,16 @@ int blk_alloc_devt(struct hd_struct *par + return -ENOMEM; + mutex_lock(&ext_devt_mutex); + rc = idr_get_new(&ext_devt_idr, part, &idx); ++ if (!rc && idx >= NR_EXT_DEVT) { ++ idr_remove(&ext_devt_idr, idx); ++ rc = -EBUSY; ++ } + mutex_unlock(&ext_devt_mutex); + } while (rc == -EAGAIN); + + if (rc) + return rc; + +- if (idx > MAX_EXT_DEVT) { +- mutex_lock(&ext_devt_mutex); +- idr_remove(&ext_devt_idr, idx); +- mutex_unlock(&ext_devt_mutex); +- return -EBUSY; +- } +- + *devt = MKDEV(BLOCK_EXT_MAJOR, blk_mangle_minor(idx)); + return 0; + } diff --git a/queue-3.8/ext4-fix-possible-use-after-free-with-aio.patch b/queue-3.8/ext4-fix-possible-use-after-free-with-aio.patch new file mode 100644 index 00000000000..83922d21cf8 --- /dev/null +++ b/queue-3.8/ext4-fix-possible-use-after-free-with-aio.patch @@ -0,0 +1,59 @@ +From 091e26dfc156aeb3b73bc5c5f277e433ad39331c Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Tue, 29 Jan 2013 22:48:17 -0500 +Subject: ext4: fix possible use-after-free with AIO + +From: Jan Kara + +commit 091e26dfc156aeb3b73bc5c5f277e433ad39331c upstream. + +Running AIO is pinning inode in memory using file reference. Once AIO +is completed using aio_complete(), file reference is put and inode can +be freed from memory. So we have to be sure that calling aio_complete() +is the last thing we do with the inode. + +Reviewed-by: Carlos Maiolino +Acked-by: Jeff Moyer +Signed-off-by: Jan Kara +Signed-off-by: "Theodore Ts'o" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/inode.c | 2 +- + fs/ext4/page-io.c | 9 ++++----- + 2 files changed, 5 insertions(+), 6 deletions(-) + +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -2977,9 +2977,9 @@ static void ext4_end_io_dio(struct kiocb + if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) { + ext4_free_io_end(io_end); + out: ++ inode_dio_done(inode); + if (is_async) + aio_complete(iocb, ret, 0); +- inode_dio_done(inode); + return; + } + +--- a/fs/ext4/page-io.c ++++ b/fs/ext4/page-io.c +@@ -103,14 +103,13 @@ static int ext4_end_io(ext4_io_end_t *io + "(inode %lu, offset %llu, size %zd, error %d)", + inode->i_ino, offset, size, ret); + } +- if (io->iocb) +- aio_complete(io->iocb, io->result, 0); +- +- if (io->flag & EXT4_IO_END_DIRECT) +- inode_dio_done(inode); + /* Wake up anyone waiting on unwritten extent conversion */ + if (atomic_dec_and_test(&EXT4_I(inode)->i_unwritten)) + wake_up_all(ext4_ioend_wq(inode)); ++ if (io->flag & EXT4_IO_END_DIRECT) ++ inode_dio_done(inode); ++ if (io->iocb) ++ aio_complete(io->iocb, io->result, 0); + return ret; + } + diff --git a/queue-3.8/firewire-add-minor-number-range-check-to-fw_device_init.patch b/queue-3.8/firewire-add-minor-number-range-check-to-fw_device_init.patch new file mode 100644 index 00000000000..60a522f9c8e --- /dev/null +++ b/queue-3.8/firewire-add-minor-number-range-check-to-fw_device_init.patch @@ -0,0 +1,36 @@ +From 3bec60d511179853138836ae6e1b61fe34d9235f Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Wed, 27 Feb 2013 17:04:04 -0800 +Subject: firewire: add minor number range check to fw_device_init() + +From: Tejun Heo + +commit 3bec60d511179853138836ae6e1b61fe34d9235f upstream. + +fw_device_init() didn't check whether the allocated minor number isn't +too large. Fail if it goes overflows MINORBITS. + +Signed-off-by: Tejun Heo +Suggested-by: Stefan Richter +Acked-by: Stefan Richter +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/firewire/core-device.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/firewire/core-device.c ++++ b/drivers/firewire/core-device.c +@@ -1020,6 +1020,10 @@ static void fw_device_init(struct work_s + ret = idr_pre_get(&fw_device_idr, GFP_KERNEL) ? + idr_get_new(&fw_device_idr, device, &minor) : + -ENOMEM; ++ if (minor >= 1 << MINORBITS) { ++ idr_remove(&fw_device_idr, minor); ++ minor = -ENOSPC; ++ } + up_write(&fw_device_rwsem); + + if (ret < 0) diff --git a/queue-3.8/fs-fix-possible-use-after-free-with-aio.patch b/queue-3.8/fs-fix-possible-use-after-free-with-aio.patch new file mode 100644 index 00000000000..3e6e08cd7e8 --- /dev/null +++ b/queue-3.8/fs-fix-possible-use-after-free-with-aio.patch @@ -0,0 +1,39 @@ +From 54c807e71d5ac59dee56c685f2b66e27cd54c475 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Wed, 30 Jan 2013 00:28:01 +0100 +Subject: fs: Fix possible use-after-free with AIO + +From: Jan Kara + +commit 54c807e71d5ac59dee56c685f2b66e27cd54c475 upstream. + +Running AIO is pinning inode in memory using file reference. Once AIO +is completed using aio_complete(), file reference is put and inode can +be freed from memory. So we have to be sure that calling aio_complete() +is the last thing we do with the inode. + +Acked-by: Jeff Moyer +CC: Christoph Hellwig +CC: Jens Axboe +CC: Jeff Moyer +Signed-off-by: Jan Kara +Signed-off-by: Al Viro +Signed-off-by: Greg Kroah-Hartman + +--- + fs/direct-io.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/direct-io.c ++++ b/fs/direct-io.c +@@ -261,9 +261,9 @@ static ssize_t dio_complete(struct dio * + dio->end_io(dio->iocb, offset, transferred, + dio->private, ret, is_async); + } else { ++ inode_dio_done(dio->inode); + if (is_async) + aio_complete(dio->iocb, ret, 0); +- inode_dio_done(dio->inode); + } + + return ret; diff --git a/queue-3.8/idr-fix-a-subtle-bug-in-idr_get_next.patch b/queue-3.8/idr-fix-a-subtle-bug-in-idr_get_next.patch new file mode 100644 index 00000000000..0e0f053ebea --- /dev/null +++ b/queue-3.8/idr-fix-a-subtle-bug-in-idr_get_next.patch @@ -0,0 +1,73 @@ +From 6cdae7416a1c45c2ce105a78187d9b7e8feb9e24 Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Wed, 27 Feb 2013 17:03:34 -0800 +Subject: idr: fix a subtle bug in idr_get_next() + +From: Tejun Heo + +commit 6cdae7416a1c45c2ce105a78187d9b7e8feb9e24 upstream. + +The iteration logic of idr_get_next() is borrowed mostly verbatim from +idr_for_each(). It walks down the tree looking for the slot matching +the current ID. If the matching slot is not found, the ID is +incremented by the distance of single slot at the given level and +repeats. + +The implementation assumes that during the whole iteration id is aligned +to the layer boundaries of the level closest to the leaf, which is true +for all iterations starting from zero or an existing element and thus is +fine for idr_for_each(). + +However, idr_get_next() may be given any point and if the starting id +hits in the middle of a non-existent layer, increment to the next layer +will end up skipping the same offset into it. For example, an IDR with +IDs filled between [64, 127] would look like the following. + + [ 0 64 ... ] + /----/ | + | | + NULL [ 64 ... 127 ] + +If idr_get_next() is called with 63 as the starting point, it will try +to follow down the pointer from 0. As it is NULL, it will then try to +proceed to the next slot in the same level by adding the slot distance +at that level which is 64 - making the next try 127. It goes around the +loop and finds and returns 127 skipping [64, 126]. + +Note that this bug also triggers in idr_for_each_entry() loop which +deletes during iteration as deletions can make layers go away leaving +the iteration with unaligned ID into missing layers. + +Fix it by ensuring proceeding to the next slot doesn't carry over the +unaligned offset - ie. use round_up(id + 1, slot_distance) instead of +id += slot_distance. + +Signed-off-by: Tejun Heo +Reported-by: David Teigland +Cc: KAMEZAWA Hiroyuki +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + lib/idr.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/lib/idr.c ++++ b/lib/idr.c +@@ -625,7 +625,14 @@ void *idr_get_next(struct idr *idp, int + return p; + } + +- id += 1 << n; ++ /* ++ * Proceed to the next layer at the current level. Unlike ++ * idr_for_each(), @id isn't guaranteed to be aligned to ++ * layer boundary at this point and adding 1 << n may ++ * incorrectly skip IDs. Make sure we jump to the ++ * beginning of the next layer using round_up(). ++ */ ++ id = round_up(id + 1, 1 << n); + while (n < fls(id)) { + n += IDR_BITS; + p = *--paa; diff --git a/queue-3.8/media-cx18-ivtv-fix-regression-remove-__init-from-a-non-init-function.patch b/queue-3.8/media-cx18-ivtv-fix-regression-remove-__init-from-a-non-init-function.patch new file mode 100644 index 00000000000..28c5548d5ee --- /dev/null +++ b/queue-3.8/media-cx18-ivtv-fix-regression-remove-__init-from-a-non-init-function.patch @@ -0,0 +1,68 @@ +From cfb046cb800ba306b211fbbe4ac633486e11055f Mon Sep 17 00:00:00 2001 +From: Hans Verkuil +Date: Sat, 9 Feb 2013 05:40:10 -0300 +Subject: media: cx18/ivtv: fix regression: remove __init from a non-init function + +From: Hans Verkuil + +commit cfb046cb800ba306b211fbbe4ac633486e11055f upstream. + +Commits 5e6e81b2890db3969527772a8350825a85c22d5c (cx18) and +2aebbf6737212265b917ed27c875c59d3037110a (ivtv) added an __init +annotation to the cx18-alsa-load and ivtv-alsa-load functions. However, +these functions are called *after* initialization by the main cx18/ivtv +driver. By that time the memory containing those functions is already +freed and your machine goes BOOM. + +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/pci/cx18/cx18-alsa-main.c | 2 +- + drivers/media/pci/cx18/cx18-alsa-pcm.h | 2 +- + drivers/media/pci/ivtv/ivtv-alsa-main.c | 2 +- + drivers/media/pci/ivtv/ivtv-alsa-pcm.h | 2 +- + 4 files changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/media/pci/cx18/cx18-alsa-main.c ++++ b/drivers/media/pci/cx18/cx18-alsa-main.c +@@ -197,7 +197,7 @@ err_exit: + return ret; + } + +-static int __init cx18_alsa_load(struct cx18 *cx) ++static int cx18_alsa_load(struct cx18 *cx) + { + struct v4l2_device *v4l2_dev = &cx->v4l2_dev; + struct cx18_stream *s; +--- a/drivers/media/pci/cx18/cx18-alsa-pcm.h ++++ b/drivers/media/pci/cx18/cx18-alsa-pcm.h +@@ -20,7 +20,7 @@ + * 02111-1307 USA + */ + +-int __init snd_cx18_pcm_create(struct snd_cx18_card *cxsc); ++int snd_cx18_pcm_create(struct snd_cx18_card *cxsc); + + /* Used by cx18-mailbox to announce the PCM data to the module */ + void cx18_alsa_announce_pcm_data(struct snd_cx18_card *card, u8 *pcm_data, +--- a/drivers/media/pci/ivtv/ivtv-alsa-main.c ++++ b/drivers/media/pci/ivtv/ivtv-alsa-main.c +@@ -205,7 +205,7 @@ err_exit: + return ret; + } + +-static int __init ivtv_alsa_load(struct ivtv *itv) ++static int ivtv_alsa_load(struct ivtv *itv) + { + struct v4l2_device *v4l2_dev = &itv->v4l2_dev; + struct ivtv_stream *s; +--- a/drivers/media/pci/ivtv/ivtv-alsa-pcm.h ++++ b/drivers/media/pci/ivtv/ivtv-alsa-pcm.h +@@ -20,4 +20,4 @@ + * 02111-1307 USA + */ + +-int __init snd_ivtv_pcm_create(struct snd_ivtv_card *itvsc); ++int snd_ivtv_pcm_create(struct snd_ivtv_card *itvsc); diff --git a/queue-3.8/media-omap_vout-find_vma-needs-mmap_sem-held.patch b/queue-3.8/media-omap_vout-find_vma-needs-mmap_sem-held.patch new file mode 100644 index 00000000000..0e94b510ee0 --- /dev/null +++ b/queue-3.8/media-omap_vout-find_vma-needs-mmap_sem-held.patch @@ -0,0 +1,63 @@ +From 55ee64b30a38d688232e5eb2860467dddc493573 Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Sun, 16 Dec 2012 16:04:46 -0300 +Subject: media: omap_vout: find_vma() needs ->mmap_sem held + +From: Al Viro + +commit 55ee64b30a38d688232e5eb2860467dddc493573 upstream. + +Walking rbtree while it's modified is a Bad Idea(tm); besides, +the result of find_vma() can be freed just as it's getting returned +to caller. Fortunately, it's easy to fix - just take ->mmap_sem a bit +earlier (and don't bother with find_vma() at all if virtp >= PAGE_OFFSET - +in that case we don't even look at its result). + +While we are at it, what prevents VIDIOC_PREPARE_BUF calling +v4l_prepare_buf() -> (e.g) vb2_ioctl_prepare_buf() -> vb2_prepare_buf() -> +__buf_prepare() -> __qbuf_userptr() -> vb2_vmalloc_get_userptr() -> find_vma(), +AFAICS without having taken ->mmap_sem anywhere in process? The code flow +is bloody convoluted and depends on a bunch of things done by initialization, +so I certainly might've missed something... + +Signed-off-by: Al Viro +Cc: Sakari Ailus +Cc: Laurent Pinchart +Cc: Archit Taneja +Cc: Prabhakar Lad +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/platform/omap/omap_vout.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +--- a/drivers/media/platform/omap/omap_vout.c ++++ b/drivers/media/platform/omap/omap_vout.c +@@ -205,19 +205,21 @@ static u32 omap_vout_uservirt_to_phys(u3 + struct vm_area_struct *vma; + struct mm_struct *mm = current->mm; + +- vma = find_vma(mm, virtp); + /* For kernel direct-mapped memory, take the easy way */ +- if (virtp >= PAGE_OFFSET) { +- physp = virt_to_phys((void *) virtp); +- } else if (vma && (vma->vm_flags & VM_IO) && vma->vm_pgoff) { ++ if (virtp >= PAGE_OFFSET) ++ return virt_to_phys((void *) virtp); ++ ++ down_read(¤t->mm->mmap_sem); ++ vma = find_vma(mm, virtp); ++ if (vma && (vma->vm_flags & VM_IO) && vma->vm_pgoff) { + /* this will catch, kernel-allocated, mmaped-to-usermode + addresses */ + physp = (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma->vm_start); ++ up_read(¤t->mm->mmap_sem); + } else { + /* otherwise, use get_user_pages() for general userland pages */ + int res, nr_pages = 1; + struct page *pages; +- down_read(¤t->mm->mmap_sem); + + res = get_user_pages(current, current->mm, virtp, nr_pages, 1, + 0, &pages, NULL); diff --git a/queue-3.8/media-rc-unlock-on-error-in-show_protocols.patch b/queue-3.8/media-rc-unlock-on-error-in-show_protocols.patch new file mode 100644 index 00000000000..b2adb9614ed --- /dev/null +++ b/queue-3.8/media-rc-unlock-on-error-in-show_protocols.patch @@ -0,0 +1,37 @@ +From 30ebc5e44d057a1619ad63fe32c8c1670c37c4b8 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Tue, 27 Nov 2012 13:35:09 -0300 +Subject: media: rc: unlock on error in show_protocols() + +From: Dan Carpenter + +commit 30ebc5e44d057a1619ad63fe32c8c1670c37c4b8 upstream. + +We recently introduced a new return -ENODEV in this function but we need +to unlock before returning. + +[mchehab@redhat.com: found two patches with the same fix. Merged SOB's/acks into one patch] +Acked-by: Herton R. Krzesinski +Signed-off-by: Dan Carpenter +Signed-off-by: Douglas Bagnall +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/rc/rc-main.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/media/rc/rc-main.c ++++ b/drivers/media/rc/rc-main.c +@@ -789,8 +789,10 @@ static ssize_t show_protocols(struct dev + } else if (dev->raw) { + enabled = dev->raw->enabled_protocols; + allowed = ir_raw_get_allowed_protocols(); +- } else ++ } else { ++ mutex_unlock(&dev->lock); + return -ENODEV; ++ } + + IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n", + (long long)allowed, diff --git a/queue-3.8/media-v4l-reset-subdev-v4l2_dev-field-to-null-if-registration-fails.patch b/queue-3.8/media-v4l-reset-subdev-v4l2_dev-field-to-null-if-registration-fails.patch new file mode 100644 index 00000000000..ce38de999a1 --- /dev/null +++ b/queue-3.8/media-v4l-reset-subdev-v4l2_dev-field-to-null-if-registration-fails.patch @@ -0,0 +1,80 @@ +From 317efce991620adc589b3005b9baed433dcb2a56 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Sat, 24 Nov 2012 21:35:48 -0300 +Subject: media: v4l: Reset subdev v4l2_dev field to NULL if registration fails + +From: Laurent Pinchart + +commit 317efce991620adc589b3005b9baed433dcb2a56 upstream. + +When subdev registration fails the subdev v4l2_dev field is left to a +non-NULL value. Later calls to v4l2_device_unregister_subdev() will +consider the subdev as registered and will module_put() the subdev +module without any matching module_get(). +Fix this by setting the subdev v4l2_dev field to NULL in +v4l2_device_register_subdev() when the function fails. + +Signed-off-by: Laurent Pinchart +Acked-by: Sylwester Nawrocki +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/v4l2-core/v4l2-device.c | 30 ++++++++++++++---------------- + 1 file changed, 14 insertions(+), 16 deletions(-) + +--- a/drivers/media/v4l2-core/v4l2-device.c ++++ b/drivers/media/v4l2-core/v4l2-device.c +@@ -159,31 +159,21 @@ int v4l2_device_register_subdev(struct v + sd->v4l2_dev = v4l2_dev; + if (sd->internal_ops && sd->internal_ops->registered) { + err = sd->internal_ops->registered(sd); +- if (err) { +- module_put(sd->owner); +- return err; +- } ++ if (err) ++ goto error_module; + } + + /* This just returns 0 if either of the two args is NULL */ + err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler, NULL); +- if (err) { +- if (sd->internal_ops && sd->internal_ops->unregistered) +- sd->internal_ops->unregistered(sd); +- module_put(sd->owner); +- return err; +- } ++ if (err) ++ goto error_unregister; + + #if defined(CONFIG_MEDIA_CONTROLLER) + /* Register the entity. */ + if (v4l2_dev->mdev) { + err = media_device_register_entity(v4l2_dev->mdev, entity); +- if (err < 0) { +- if (sd->internal_ops && sd->internal_ops->unregistered) +- sd->internal_ops->unregistered(sd); +- module_put(sd->owner); +- return err; +- } ++ if (err < 0) ++ goto error_unregister; + } + #endif + +@@ -192,6 +182,14 @@ int v4l2_device_register_subdev(struct v + spin_unlock(&v4l2_dev->lock); + + return 0; ++ ++error_unregister: ++ if (sd->internal_ops && sd->internal_ops->unregistered) ++ sd->internal_ops->unregistered(sd); ++error_module: ++ module_put(sd->owner); ++ sd->v4l2_dev = NULL; ++ return err; + } + EXPORT_SYMBOL_GPL(v4l2_device_register_subdev); + diff --git a/queue-3.8/nbd-fsync-and-kill-block-device-on-shutdown.patch b/queue-3.8/nbd-fsync-and-kill-block-device-on-shutdown.patch new file mode 100644 index 00000000000..039cf160926 --- /dev/null +++ b/queue-3.8/nbd-fsync-and-kill-block-device-on-shutdown.patch @@ -0,0 +1,91 @@ +From 3a2d63f87989e01437ba994df5f297528c353d7d Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Wed, 27 Feb 2013 17:05:25 -0800 +Subject: nbd: fsync and kill block device on shutdown + +From: Paolo Bonzini + +commit 3a2d63f87989e01437ba994df5f297528c353d7d upstream. + +There are two problems with shutdown in the NBD driver. + +1: Receiving the NBD_DISCONNECT ioctl does not sync the filesystem. + + This patch adds the sync operation into __nbd_ioctl()'s + NBD_DISCONNECT handler. This is useful because BLKFLSBUF is restricted + to processes that have CAP_SYS_ADMIN, and the NBD client may not + possess it (fsync of the block device does not sync the filesystem, + either). + +2: Once we clear the socket we have no guarantee that later reads will + come from the same backing storage. + + The patch adds calls to kill_bdev() in __nbd_ioctl()'s socket + clearing code so the page cache is cleaned, lest reads that hit on the + page cache will return stale data from the previously-accessible disk. + +Example: + + # qemu-nbd -r -c/dev/nbd0 /dev/sr0 + # file -s /dev/nbd0 + /dev/stdin: # UDF filesystem data (version 1.5) etc. + # qemu-nbd -d /dev/nbd0 + # qemu-nbd -r -c/dev/nbd0 /dev/sda + # file -s /dev/nbd0 + /dev/stdin: # UDF filesystem data (version 1.5) etc. + +While /dev/sda has: + + # file -s /dev/sda + /dev/sda: x86 boot sector; etc. + +Signed-off-by: Paolo Bonzini +Acked-by: Paul Clements +Cc: Alex Bligh +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/nbd.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/block/nbd.c ++++ b/drivers/block/nbd.c +@@ -595,12 +595,20 @@ static int __nbd_ioctl(struct block_devi + struct request sreq; + + dev_info(disk_to_dev(nbd->disk), "NBD_DISCONNECT\n"); ++ if (!nbd->sock) ++ return -EINVAL; + ++ mutex_unlock(&nbd->tx_lock); ++ fsync_bdev(bdev); ++ mutex_lock(&nbd->tx_lock); + blk_rq_init(NULL, &sreq); + sreq.cmd_type = REQ_TYPE_SPECIAL; + nbd_cmd(&sreq) = NBD_CMD_DISC; ++ ++ /* Check again after getting mutex back. */ + if (!nbd->sock) + return -EINVAL; ++ + nbd_send_req(nbd, &sreq); + return 0; + } +@@ -614,6 +622,7 @@ static int __nbd_ioctl(struct block_devi + nbd_clear_que(nbd); + BUG_ON(!list_empty(&nbd->queue_head)); + BUG_ON(!list_empty(&nbd->waiting_queue)); ++ kill_bdev(bdev); + if (file) + fput(file); + return 0; +@@ -702,6 +711,7 @@ static int __nbd_ioctl(struct block_devi + nbd->file = NULL; + nbd_clear_que(nbd); + dev_warn(disk_to_dev(nbd->disk), "queue cleared\n"); ++ kill_bdev(bdev); + queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue); + if (file) + fput(file); diff --git a/queue-3.8/series b/queue-3.8/series index fc1e7472a19..b1dbfec70c8 100644 --- a/queue-3.8/series +++ b/queue-3.8/series @@ -30,3 +30,18 @@ ocfs2-fix-possible-use-after-free-with-aio.patch ocfs2-fix-ocfs2_init_security_and_acl-to-initialize-acl-correctly.patch ocfs2-ac-ac_allow_chain_relink-0-won-t-disable-group-relink.patch block-fix-ext_devt_idr-handling.patch +xen-blkback-do-not-leak-mode-property.patch +xen-blkback-don-t-trust-the-handle-from-the-frontend.patch +xen-blkfront-drop-the-use-of-llist_for_each_entry_safe.patch +xen-blkback-use-balloon-pages-for-persistent-grants.patch +idr-fix-a-subtle-bug-in-idr_get_next.patch +block-fix-synchronization-and-limit-check-in-blk_alloc_devt.patch +firewire-add-minor-number-range-check-to-fw_device_init.patch +sysctl-fix-null-checking-in-bin_dn_node_address.patch +nbd-fsync-and-kill-block-device-on-shutdown.patch +fs-fix-possible-use-after-free-with-aio.patch +ext4-fix-possible-use-after-free-with-aio.patch +media-cx18-ivtv-fix-regression-remove-__init-from-a-non-init-function.patch +media-v4l-reset-subdev-v4l2_dev-field-to-null-if-registration-fails.patch +media-omap_vout-find_vma-needs-mmap_sem-held.patch +media-rc-unlock-on-error-in-show_protocols.patch diff --git a/queue-3.8/sysctl-fix-null-checking-in-bin_dn_node_address.patch b/queue-3.8/sysctl-fix-null-checking-in-bin_dn_node_address.patch new file mode 100644 index 00000000000..d1a58a954d2 --- /dev/null +++ b/queue-3.8/sysctl-fix-null-checking-in-bin_dn_node_address.patch @@ -0,0 +1,36 @@ +From df1778be1a33edffa51d094eeda87c858ded6560 Mon Sep 17 00:00:00 2001 +From: Xi Wang +Date: Wed, 27 Feb 2013 17:05:21 -0800 +Subject: sysctl: fix null checking in bin_dn_node_address() + +From: Xi Wang + +commit df1778be1a33edffa51d094eeda87c858ded6560 upstream. + +The null check of `strchr() + 1' is broken, which is always non-null, +leading to OOB read. Instead, check the result of strchr(). + +Signed-off-by: Xi Wang +Cc: "Eric W. Biederman" +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/sysctl_binary.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/kernel/sysctl_binary.c ++++ b/kernel/sysctl_binary.c +@@ -1194,9 +1194,10 @@ static ssize_t bin_dn_node_address(struc + + /* Convert the decnet address to binary */ + result = -EIO; +- nodep = strchr(buf, '.') + 1; ++ nodep = strchr(buf, '.'); + if (!nodep) + goto out; ++ ++nodep; + + area = simple_strtoul(buf, NULL, 10); + node = simple_strtoul(nodep, NULL, 10); diff --git a/queue-3.8/xen-blkback-do-not-leak-mode-property.patch b/queue-3.8/xen-blkback-do-not-leak-mode-property.patch new file mode 100644 index 00000000000..bbbe6778b69 --- /dev/null +++ b/queue-3.8/xen-blkback-do-not-leak-mode-property.patch @@ -0,0 +1,113 @@ +From 9d092603cc306ee6edfe917bf9ab8beb5f32d7bc Mon Sep 17 00:00:00 2001 +From: Jan Beulich +Date: Thu, 20 Dec 2012 10:31:11 +0000 +Subject: xen-blkback: do not leak mode property + +From: Jan Beulich + +commit 9d092603cc306ee6edfe917bf9ab8beb5f32d7bc upstream. + +"be->mode" is obtained from xenbus_read(), which does a kmalloc() for +the message body. The short string is never released, so do it along +with freeing "be" itself, and make sure the string isn't kept when +backend_changed() doesn't complete successfully (which made it +desirable to slightly re-structure that function, so that the error +cleanup can be done in one place). + +Reported-by: Olaf Hering +Signed-off-by: Jan Beulich +Signed-off-by: Konrad Rzeszutek Wilk +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/xen-blkback/xenbus.c | 49 ++++++++++++++++++------------------- + 1 file changed, 24 insertions(+), 25 deletions(-) + +--- a/drivers/block/xen-blkback/xenbus.c ++++ b/drivers/block/xen-blkback/xenbus.c +@@ -367,6 +367,7 @@ static int xen_blkbk_remove(struct xenbu + be->blkif = NULL; + } + ++ kfree(be->mode); + kfree(be); + dev_set_drvdata(&dev->dev, NULL); + return 0; +@@ -502,6 +503,7 @@ static void backend_changed(struct xenbu + = container_of(watch, struct backend_info, backend_watch); + struct xenbus_device *dev = be->dev; + int cdrom = 0; ++ unsigned long handle; + char *device_type; + + DPRINTK(""); +@@ -521,10 +523,10 @@ static void backend_changed(struct xenbu + return; + } + +- if ((be->major || be->minor) && +- ((be->major != major) || (be->minor != minor))) { +- pr_warn(DRV_PFX "changing physical device (from %x:%x to %x:%x) not supported.\n", +- be->major, be->minor, major, minor); ++ if (be->major | be->minor) { ++ if (be->major != major || be->minor != minor) ++ pr_warn(DRV_PFX "changing physical device (from %x:%x to %x:%x) not supported.\n", ++ be->major, be->minor, major, minor); + return; + } + +@@ -542,36 +544,33 @@ static void backend_changed(struct xenbu + kfree(device_type); + } + +- if (be->major == 0 && be->minor == 0) { +- /* Front end dir is a number, which is used as the handle. */ ++ /* Front end dir is a number, which is used as the handle. */ ++ err = strict_strtoul(strrchr(dev->otherend, '/') + 1, 0, &handle); ++ if (err) ++ return; + +- char *p = strrchr(dev->otherend, '/') + 1; +- long handle; +- err = strict_strtoul(p, 0, &handle); +- if (err) +- return; ++ be->major = major; ++ be->minor = minor; + +- be->major = major; +- be->minor = minor; +- +- err = xen_vbd_create(be->blkif, handle, major, minor, +- (NULL == strchr(be->mode, 'w')), cdrom); +- if (err) { +- be->major = 0; +- be->minor = 0; +- xenbus_dev_fatal(dev, err, "creating vbd structure"); +- return; +- } ++ err = xen_vbd_create(be->blkif, handle, major, minor, ++ !strchr(be->mode, 'w'), cdrom); + ++ if (err) ++ xenbus_dev_fatal(dev, err, "creating vbd structure"); ++ else { + err = xenvbd_sysfs_addif(dev); + if (err) { + xen_vbd_free(&be->blkif->vbd); +- be->major = 0; +- be->minor = 0; + xenbus_dev_fatal(dev, err, "creating sysfs entries"); +- return; + } ++ } + ++ if (err) { ++ kfree(be->mode); ++ be->mode = NULL; ++ be->major = 0; ++ be->minor = 0; ++ } else { + /* We're potentially connected now */ + xen_update_blkif_status(be->blkif); + } diff --git a/queue-3.8/xen-blkback-don-t-trust-the-handle-from-the-frontend.patch b/queue-3.8/xen-blkback-don-t-trust-the-handle-from-the-frontend.patch new file mode 100644 index 00000000000..6bf3b5d6840 --- /dev/null +++ b/queue-3.8/xen-blkback-don-t-trust-the-handle-from-the-frontend.patch @@ -0,0 +1,38 @@ +From 01c681d4c70d64cb72142a2823f27c4146a02e63 Mon Sep 17 00:00:00 2001 +From: Konrad Rzeszutek Wilk +Date: Wed, 16 Jan 2013 11:36:23 -0500 +Subject: xen/blkback: Don't trust the handle from the frontend. + +From: Konrad Rzeszutek Wilk + +commit 01c681d4c70d64cb72142a2823f27c4146a02e63 upstream. + +The 'handle' is the device that the request is from. For the life-time +of the ring we copy it from a request to a response so that the frontend +is not surprised by it. But we do not need it - when we start processing +I/Os we have our own 'struct phys_req' which has only most essential +information about the request. In fact the 'vbd_translate' ends up +over-writing the preq.dev with a value from the backend. + +This assignment of preq.dev with the 'handle' value is superfluous +so lets not do it. + +Acked-by: Jan Beulich +Acked-by: Ian Campbell +Signed-off-by: Konrad Rzeszutek Wilk +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/xen-blkback/blkback.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/block/xen-blkback/blkback.c ++++ b/drivers/block/xen-blkback/blkback.c +@@ -879,7 +879,6 @@ static int dispatch_rw_block_io(struct x + goto fail_response; + } + +- preq.dev = req->u.rw.handle; + preq.sector_number = req->u.rw.sector_number; + preq.nr_sects = 0; + diff --git a/queue-3.8/xen-blkback-use-balloon-pages-for-persistent-grants.patch b/queue-3.8/xen-blkback-use-balloon-pages-for-persistent-grants.patch new file mode 100644 index 00000000000..5afbe96939c --- /dev/null +++ b/queue-3.8/xen-blkback-use-balloon-pages-for-persistent-grants.patch @@ -0,0 +1,53 @@ +From 087ffecdaa1875cc683a7a5bc0695b3ebfce3bad Mon Sep 17 00:00:00 2001 +From: Roger Pau Monne +Date: Thu, 14 Feb 2013 11:12:09 +0100 +Subject: xen-blkback: use balloon pages for persistent grants + +From: Roger Pau Monne + +commit 087ffecdaa1875cc683a7a5bc0695b3ebfce3bad upstream. + +With current persistent grants implementation we are not freeing the +persistent grants after we disconnect the device. Since grant map +operations change the mfn of the allocated page, and we can no longer +pass it to __free_page without setting the mfn to a sane value, use +balloon grant pages instead, as the gntdev device does. + +Signed-off-by: Roger Pau Monné +Cc: Konrad Rzeszutek Wilk +Signed-off-by: Konrad Rzeszutek Wilk +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/xen-blkback/blkback.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/block/xen-blkback/blkback.c ++++ b/drivers/block/xen-blkback/blkback.c +@@ -46,6 +46,7 @@ + #include + #include + #include ++#include + #include "common.h" + + /* +@@ -239,6 +240,7 @@ static void free_persistent_gnts(struct + ret = gnttab_unmap_refs(unmap, NULL, pages, + segs_to_unmap); + BUG_ON(ret); ++ free_xenballooned_pages(segs_to_unmap, pages); + segs_to_unmap = 0; + } + +@@ -527,8 +529,8 @@ static int xen_blkbk_map(struct blkif_re + GFP_KERNEL); + if (!persistent_gnt) + return -ENOMEM; +- persistent_gnt->page = alloc_page(GFP_KERNEL); +- if (!persistent_gnt->page) { ++ if (alloc_xenballooned_pages(1, &persistent_gnt->page, ++ false)) { + kfree(persistent_gnt); + return -ENOMEM; + } diff --git a/queue-3.8/xen-blkfront-drop-the-use-of-llist_for_each_entry_safe.patch b/queue-3.8/xen-blkfront-drop-the-use-of-llist_for_each_entry_safe.patch new file mode 100644 index 00000000000..aa3fdb3f214 --- /dev/null +++ b/queue-3.8/xen-blkfront-drop-the-use-of-llist_for_each_entry_safe.patch @@ -0,0 +1,141 @@ +From f84adf4921ae3115502f44ff467b04bf2f88cf04 Mon Sep 17 00:00:00 2001 +From: Konrad Rzeszutek Wilk +Date: Wed, 13 Feb 2013 13:01:55 -0500 +Subject: xen-blkfront: drop the use of llist_for_each_entry_safe + +From: Konrad Rzeszutek Wilk + +commit f84adf4921ae3115502f44ff467b04bf2f88cf04 upstream. + +Replace llist_for_each_entry_safe with a while loop. + +llist_for_each_entry_safe can trigger a bug in GCC 4.1, so it's best +to remove it and use a while loop and do the deletion manually. + +Specifically this bug can be triggered by hot-unplugging a disk, either +by doing xm block-detach or by save/restore cycle. + +BUG: unable to handle kernel paging request at fffffffffffffff0 +IP: [] blkif_free+0x63/0x130 [xen_blkfront] +The crash call trace is: + ... +bad_area_nosemaphore+0x13/0x20 +do_page_fault+0x25e/0x4b0 +page_fault+0x25/0x30 +? blkif_free+0x63/0x130 [xen_blkfront] +blkfront_resume+0x46/0xa0 [xen_blkfront] +xenbus_dev_resume+0x6c/0x140 +pm_op+0x192/0x1b0 +device_resume+0x82/0x1e0 +dpm_resume+0xc9/0x1a0 +dpm_resume_end+0x15/0x30 +do_suspend+0x117/0x1e0 + +When drilling down to the assembler code, on newer GCC it does +.L29: + cmpq $-16, %r12 #, persistent_gnt check + je .L30 #, out of the loop +.L25: + ... code in the loop + testq %r13, %r13 # n + je .L29 #, back to the top of the loop + cmpq $-16, %r12 #, persistent_gnt check + movq 16(%r12), %r13 # .node.next, n + jne .L25 #, back to the top of the loop +.L30: + +While on GCC 4.1, it is: +L78: + ... code in the loop + testq %r13, %r13 # n + je .L78 #, back to the top of the loop + movq 16(%rbx), %r13 # .node.next, n + jmp .L78 #, back to the top of the loop + +Which basically means that the exit loop condition instead of +being: + + &(pos)->member != NULL; + +is: + ; + +which makes the loop unbound. + +Since xen-blkfront is the only user of the llist_for_each_entry_safe +macro remove it from llist.h. + +Orabug: 16263164 +Signed-off-by: Konrad Rzeszutek Wilk +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/xen-blkfront.c | 13 ++++++++++--- + include/linux/llist.h | 25 ------------------------- + 2 files changed, 10 insertions(+), 28 deletions(-) + +--- a/drivers/block/xen-blkfront.c ++++ b/drivers/block/xen-blkfront.c +@@ -791,7 +791,7 @@ static void blkif_restart_queue(struct w + static void blkif_free(struct blkfront_info *info, int suspend) + { + struct llist_node *all_gnts; +- struct grant *persistent_gnt; ++ struct grant *persistent_gnt, *tmp; + struct llist_node *n; + + /* Prevent new requests being issued until we fix things up. */ +@@ -805,10 +805,17 @@ static void blkif_free(struct blkfront_i + /* Remove all persistent grants */ + if (info->persistent_gnts_c) { + all_gnts = llist_del_all(&info->persistent_gnts); +- llist_for_each_entry_safe(persistent_gnt, n, all_gnts, node) { ++ persistent_gnt = llist_entry(all_gnts, typeof(*(persistent_gnt)), node); ++ while (persistent_gnt) { + gnttab_end_foreign_access(persistent_gnt->gref, 0, 0UL); + __free_page(pfn_to_page(persistent_gnt->pfn)); +- kfree(persistent_gnt); ++ tmp = persistent_gnt; ++ n = persistent_gnt->node.next; ++ if (n) ++ persistent_gnt = llist_entry(n, typeof(*(persistent_gnt)), node); ++ else ++ persistent_gnt = NULL; ++ kfree(tmp); + } + info->persistent_gnts_c = 0; + } +--- a/include/linux/llist.h ++++ b/include/linux/llist.h +@@ -125,31 +125,6 @@ static inline void init_llist_head(struc + (pos) = llist_entry((pos)->member.next, typeof(*(pos)), member)) + + /** +- * llist_for_each_entry_safe - iterate safely against remove over some entries +- * of lock-less list of given type. +- * @pos: the type * to use as a loop cursor. +- * @n: another type * to use as a temporary storage. +- * @node: the fist entry of deleted list entries. +- * @member: the name of the llist_node with the struct. +- * +- * In general, some entries of the lock-less list can be traversed +- * safely only after being removed from list, so start with an entry +- * instead of list head. This variant allows removal of entries +- * as we iterate. +- * +- * If being used on entries deleted from lock-less list directly, the +- * traverse order is from the newest to the oldest added entry. If +- * you want to traverse from the oldest to the newest, you must +- * reverse the order by yourself before traversing. +- */ +-#define llist_for_each_entry_safe(pos, n, node, member) \ +- for ((pos) = llist_entry((node), typeof(*(pos)), member), \ +- (n) = (pos)->member.next; \ +- &(pos)->member != NULL; \ +- (pos) = llist_entry(n, typeof(*(pos)), member), \ +- (n) = (&(pos)->member != NULL) ? (pos)->member.next : NULL) +- +-/** + * llist_empty - tests whether a lock-less list is empty + * @head: the list to test + * -- 2.47.3