diff options
author | Thorsten Leemhuis <fedora@leemhuis.info> | 2016-04-13 07:48:33 +0200 |
---|---|---|
committer | Thorsten Leemhuis <fedora@leemhuis.info> | 2016-04-13 07:48:33 +0200 |
commit | d2a02b99231f946f4e78263d22a321fc8a7a15cd (patch) | |
tree | 19175f971471639f587a58437e1e8362fbf3ed68 | |
parent | d770c998e6727837fa63fbd9441eef7c67df3219 (diff) | |
parent | 0a256336060b41ebafc8724fe9bf24fe9e70b1ff (diff) | |
download | kernel-4.4.7-200.vanilla.knurd.1.fc22.tar.gz kernel-4.4.7-200.vanilla.knurd.1.fc22.tar.xz kernel-4.4.7-200.vanilla.knurd.1.fc22.zip |
Merge remote-tracking branch 'origin/f22' into f22-user-thl-vanilla-fedorakernel-4.4.7-200.vanilla.knurd.1.fc22
-rw-r--r-- | 0001-uas-Limit-qdepth-at-the-scsi-host-level.patch | 45 | ||||
-rw-r--r-- | 09-29-drm-udl-Use-unlocked-gem-unreferencing.patch | 58 | ||||
-rw-r--r-- | HID-wacom-fix-Bamboo-ONE-oops.patch | 46 | ||||
-rw-r--r-- | USB-serial-ftdi_sio-Add-support-for-ICP-DAS-I-756xU-.patch | 59 | ||||
-rw-r--r-- | cdc_ncm-do-not-call-usbnet_link_change-from-cdc_ncm_.patch | 87 | ||||
-rw-r--r-- | ext4-fix-races-between-buffered-IO-and-collapse-inse.patch | 119 | ||||
-rw-r--r-- | ext4-fix-races-between-page-faults-and-hole-punching.patch | 442 | ||||
-rw-r--r-- | ext4-fix-races-of-writeback-with-punch-hole-and-zero.patch | 110 | ||||
-rw-r--r-- | ext4-move-unlocked-dio-protection-from-ext4_alloc_fi.patch | 93 | ||||
-rw-r--r-- | input-gtco-fix-crash-on-detecting-device-without-end.patch | 49 | ||||
-rw-r--r-- | kernel.spec | 138 | ||||
-rw-r--r-- | sources | 2 | ||||
-rw-r--r-- | usbnet-cleanup-after-bind-in-probe.patch | 39 | ||||
-rw-r--r-- | x86-Lock-down-IO-port-access-when-module-security-is.patch | 15 | ||||
-rw-r--r-- | x86-mm-32-Enable-full-randomization-on-i386-and-X86_.patch | 83 |
15 files changed, 1313 insertions, 72 deletions
diff --git a/0001-uas-Limit-qdepth-at-the-scsi-host-level.patch b/0001-uas-Limit-qdepth-at-the-scsi-host-level.patch new file mode 100644 index 000000000..b6c446829 --- /dev/null +++ b/0001-uas-Limit-qdepth-at-the-scsi-host-level.patch @@ -0,0 +1,45 @@ +From 79abe2bd501d628b165f323098d6972d69bd13d7 Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Wed, 16 Mar 2016 13:20:51 +0100 +Subject: [PATCH] uas: Limit qdepth at the scsi-host level + +Commit 64d513ac31bd ("scsi: use host wide tags by default") causes +the scsi-core to queue more cmnds then we can handle on devices with +multiple LUNs, limit the qdepth at the scsi-host level instead of +per slave to fix this. + +BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1315013 +Cc: stable@vger.kernel.org # 4.4.x and 4.5.x +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + drivers/usb/storage/uas.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c +index c90a7e4..b5cb7ab 100644 +--- a/drivers/usb/storage/uas.c ++++ b/drivers/usb/storage/uas.c +@@ -800,7 +800,6 @@ static int uas_slave_configure(struct scsi_device *sdev) + if (devinfo->flags & US_FL_BROKEN_FUA) + sdev->broken_fua = 1; + +- scsi_change_queue_depth(sdev, devinfo->qdepth - 2); + return 0; + } + +@@ -932,6 +931,12 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) + if (result) + goto set_alt0; + ++ /* ++ * 1 tag is reserved for untagged commands + ++ * 1 tag to avoid of by one errors in some bridge firmwares ++ */ ++ shost->can_queue = devinfo->qdepth - 2; ++ + usb_set_intfdata(intf, shost); + result = scsi_add_host(shost, &intf->dev); + if (result) +-- +2.7.3 + diff --git a/09-29-drm-udl-Use-unlocked-gem-unreferencing.patch b/09-29-drm-udl-Use-unlocked-gem-unreferencing.patch new file mode 100644 index 000000000..e2dbabe83 --- /dev/null +++ b/09-29-drm-udl-Use-unlocked-gem-unreferencing.patch @@ -0,0 +1,58 @@ +From patchwork Mon Nov 23 09:32:42 2015 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [09/29] drm/udl: Use unlocked gem unreferencing +From: Daniel Vetter <daniel.vetter@ffwll.ch> +X-Patchwork-Id: 65722 +Message-Id: <1448271183-20523-10-git-send-email-daniel.vetter@ffwll.ch> +To: DRI Development <dri-devel@lists.freedesktop.org> +Cc: Daniel Vetter <daniel.vetter@intel.com>, + Daniel Vetter <daniel.vetter@ffwll.ch>, + Intel Graphics Development <intel-gfx@lists.freedesktop.org>, + Dave Airlie <airlied@redhat.com> +Date: Mon, 23 Nov 2015 10:32:42 +0100 + +For drm_gem_object_unreference callers are required to hold +dev->struct_mutex, which these paths don't. Enforcing this requirement +has become a bit more strict with + +commit ef4c6270bf2867e2f8032e9614d1a8cfc6c71663 +Author: Daniel Vetter <daniel.vetter@ffwll.ch> +Date: Thu Oct 15 09:36:25 2015 +0200 + + drm/gem: Check locking in drm_gem_object_unreference + +Cc: Dave Airlie <airlied@redhat.com> +Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> +--- + drivers/gpu/drm/udl/udl_fb.c | 2 +- + drivers/gpu/drm/udl/udl_gem.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c +index 200419d4d43c..18a2acbccb7d 100644 +--- a/drivers/gpu/drm/udl/udl_fb.c ++++ b/drivers/gpu/drm/udl/udl_fb.c +@@ -538,7 +538,7 @@ static int udlfb_create(struct drm_fb_helper *helper, + out_destroy_fbi: + drm_fb_helper_release_fbi(helper); + out_gfree: +- drm_gem_object_unreference(&ufbdev->ufb.obj->base); ++ drm_gem_object_unreference_unlocked(&ufbdev->ufb.obj->base); + out: + return ret; + } +diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c +index 2a0a784ab6ee..d7528e0d8442 100644 +--- a/drivers/gpu/drm/udl/udl_gem.c ++++ b/drivers/gpu/drm/udl/udl_gem.c +@@ -52,7 +52,7 @@ udl_gem_create(struct drm_file *file, + return ret; + } + +- drm_gem_object_unreference(&obj->base); ++ drm_gem_object_unreference_unlocked(&obj->base); + *handle_p = handle; + return 0; + } diff --git a/HID-wacom-fix-Bamboo-ONE-oops.patch b/HID-wacom-fix-Bamboo-ONE-oops.patch new file mode 100644 index 000000000..09e83179a --- /dev/null +++ b/HID-wacom-fix-Bamboo-ONE-oops.patch @@ -0,0 +1,46 @@ +From 580549ef6b3e3fb3b958de490ca99f43a089a2cf Mon Sep 17 00:00:00 2001 +From: Benjamin Tissoires <benjamin.tissoires@redhat.com> +Date: Fri, 25 Mar 2016 15:26:55 +0100 +Subject: [PATCH] HID: wacom: fix Bamboo ONE oops + +Looks like recent changes in the Wacom driver made the Bamboo ONE crashes. +The tablet behaves as if it was a regular Bamboo device with pen, touch +and pad, but there is no physical pad connected to it. +The weird part is that the pad is still sending events and given that +there is no input node connected to it, we get anull pointer exception. + +Link: https://bugzilla.redhat.com/show_bug.cgi?id=1317116 + +Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> +Acked-by: Ping Cheng <pingc@wacom.com> +Cc: stable@vger.kernel.org +Signed-off-by: Jiri Kosina <jkosina@suse.cz> +--- + drivers/hid/wacom_wac.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c +index bd198bbd4df0..02c4efea241c 100644 +--- a/drivers/hid/wacom_wac.c ++++ b/drivers/hid/wacom_wac.c +@@ -2426,6 +2426,17 @@ void wacom_setup_device_quirks(struct wacom *wacom) + } + + /* ++ * Hack for the Bamboo One: ++ * the device presents a PAD/Touch interface as most Bamboos and even ++ * sends ghosts PAD data on it. However, later, we must disable this ++ * ghost interface, and we can not detect it unless we set it here ++ * to WACOM_DEVICETYPE_PAD or WACOM_DEVICETYPE_TOUCH. ++ */ ++ if (features->type == BAMBOO_PEN && ++ features->pktlen == WACOM_PKGLEN_BBTOUCH3) ++ features->device_type |= WACOM_DEVICETYPE_PAD; ++ ++ /* + * Raw Wacom-mode pen and touch events both come from interface + * 0, whose HID descriptor has an application usage of 0xFF0D + * (i.e., WACOM_VENDORDEFINED_PEN). We route pen packets back +-- +2.5.5 + diff --git a/USB-serial-ftdi_sio-Add-support-for-ICP-DAS-I-756xU-.patch b/USB-serial-ftdi_sio-Add-support-for-ICP-DAS-I-756xU-.patch deleted file mode 100644 index ac8e71c72..000000000 --- a/USB-serial-ftdi_sio-Add-support-for-ICP-DAS-I-756xU-.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 94c78c81df3056e573fb84000a32512e9c16e555 Mon Sep 17 00:00:00 2001 -From: Josh Boyer <jwboyer@fedoraproject.org> -Date: Thu, 10 Mar 2016 08:49:02 -0500 -Subject: [PATCH] USB: serial: ftdi_sio: Add support for ICP DAS I-756xU - devices - -A Fedora user reports that the ftdi_sio driver works properly for the -ICP DAS I-7561U device. Further, the user manual for these devices -instructs users to load the driver and add the ids using the sysfs -interface. - -Add support for these in the driver directly so that the devices work -out of the box instead of needing manual configuration. - -Reported-by: <thesource@mail.ru> -CC: stable <stable@vger.kernel.org> -Signed-off-by: Josh Boyer <jwboyer@fedoraproject.org> ---- - drivers/usb/serial/ftdi_sio.c | 4 ++++ - drivers/usb/serial/ftdi_sio_ids.h | 8 ++++++++ - 2 files changed, 12 insertions(+) - -diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c -index 8c660ae401d8..b61f12160d37 100644 ---- a/drivers/usb/serial/ftdi_sio.c -+++ b/drivers/usb/serial/ftdi_sio.c -@@ -1004,6 +1004,10 @@ static const struct usb_device_id id_table_combined[] = { - { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_DISPLAY_PID) }, - { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_LITE_PID) }, - { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ANALOG_PID) }, -+ /* ICP DAS I-756xU devices */ -+ { USB_DEVICE(ICPDAS_VID, ICPDAS_I7560U_PID) }, -+ { USB_DEVICE(ICPDAS_VID, ICPDAS_I7561U_PID) }, -+ { USB_DEVICE(ICPDAS_VID, ICPDAS_I7563U_PID) }, - { } /* Terminating entry */ - }; - -diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h -index a84df2513994..a4ec24ce6a11 100644 ---- a/drivers/usb/serial/ftdi_sio_ids.h -+++ b/drivers/usb/serial/ftdi_sio_ids.h -@@ -872,6 +872,14 @@ - #define NOVITUS_BONO_E_PID 0x6010 - - /* -+ * ICPDAS I-756*U devices -+ */ -+#define ICPDAS_VID 0x1b5c -+#define ICPDAS_I7560U_PID 0x0103 -+#define ICPDAS_I7561U_PID 0x0104 -+#define ICPDAS_I7563U_PID 0x0105 -+ -+/* - * RT Systems programming cables for various ham radios - */ - #define RTSYSTEMS_VID 0x2100 /* Vendor ID */ --- -2.5.0 - diff --git a/cdc_ncm-do-not-call-usbnet_link_change-from-cdc_ncm_.patch b/cdc_ncm-do-not-call-usbnet_link_change-from-cdc_ncm_.patch new file mode 100644 index 000000000..479914dc2 --- /dev/null +++ b/cdc_ncm-do-not-call-usbnet_link_change-from-cdc_ncm_.patch @@ -0,0 +1,87 @@ +From 4d06dd537f95683aba3651098ae288b7cbff8274 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <bjorn@mork.no> +Date: Mon, 7 Mar 2016 21:15:36 +0100 +Subject: [PATCH] cdc_ncm: do not call usbnet_link_change from cdc_ncm_bind +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +usbnet_link_change will call schedule_work and should be +avoided if bind is failing. Otherwise we will end up with +scheduled work referring to a netdev which has gone away. + +Instead of making the call conditional, we can just defer +it to usbnet_probe, using the driver_info flag made for +this purpose. + +Fixes: 8a34b0ae8778 ("usbnet: cdc_ncm: apply usbnet_link_change") +Reported-by: Andrey Konovalov <andreyknvl@gmail.com> +Suggested-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Bjørn Mork <bjorn@mork.no> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/usb/cdc_ncm.c | 20 +++++--------------- + 1 file changed, 5 insertions(+), 15 deletions(-) + +diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c +index be927964375b..86ba30ba35e8 100644 +--- a/drivers/net/usb/cdc_ncm.c ++++ b/drivers/net/usb/cdc_ncm.c +@@ -988,8 +988,6 @@ EXPORT_SYMBOL_GPL(cdc_ncm_select_altsetting); + + static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf) + { +- int ret; +- + /* MBIM backwards compatible function? */ + if (cdc_ncm_select_altsetting(intf) != CDC_NCM_COMM_ALTSETTING_NCM) + return -ENODEV; +@@ -998,16 +996,7 @@ static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf) + * Additionally, generic NCM devices are assumed to accept arbitrarily + * placed NDP. + */ +- ret = cdc_ncm_bind_common(dev, intf, CDC_NCM_DATA_ALTSETTING_NCM, 0); +- +- /* +- * We should get an event when network connection is "connected" or +- * "disconnected". Set network connection in "disconnected" state +- * (carrier is OFF) during attach, so the IP network stack does not +- * start IPv6 negotiation and more. +- */ +- usbnet_link_change(dev, 0, 0); +- return ret; ++ return cdc_ncm_bind_common(dev, intf, CDC_NCM_DATA_ALTSETTING_NCM, 0); + } + + static void cdc_ncm_align_tail(struct sk_buff *skb, size_t modulus, size_t remainder, size_t max) +@@ -1590,7 +1579,8 @@ static void cdc_ncm_status(struct usbnet *dev, struct urb *urb) + + static const struct driver_info cdc_ncm_info = { + .description = "CDC NCM", +- .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET, ++ .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET ++ | FLAG_LINK_INTR, + .bind = cdc_ncm_bind, + .unbind = cdc_ncm_unbind, + .manage_power = usbnet_manage_power, +@@ -1603,7 +1593,7 @@ static const struct driver_info cdc_ncm_info = { + static const struct driver_info wwan_info = { + .description = "Mobile Broadband Network Device", + .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET +- | FLAG_WWAN, ++ | FLAG_LINK_INTR | FLAG_WWAN, + .bind = cdc_ncm_bind, + .unbind = cdc_ncm_unbind, + .manage_power = usbnet_manage_power, +@@ -1616,7 +1606,7 @@ static const struct driver_info wwan_info = { + static const struct driver_info wwan_noarp_info = { + .description = "Mobile Broadband Network Device (NO ARP)", + .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET +- | FLAG_WWAN | FLAG_NOARP, ++ | FLAG_LINK_INTR | FLAG_WWAN | FLAG_NOARP, + .bind = cdc_ncm_bind, + .unbind = cdc_ncm_unbind, + .manage_power = usbnet_manage_power, +-- +2.5.5 + diff --git a/ext4-fix-races-between-buffered-IO-and-collapse-inse.patch b/ext4-fix-races-between-buffered-IO-and-collapse-inse.patch new file mode 100644 index 000000000..0c89ea77a --- /dev/null +++ b/ext4-fix-races-between-buffered-IO-and-collapse-inse.patch @@ -0,0 +1,119 @@ +From 32ebffd3bbb4162da5ff88f9a35dd32d0a28ea70 Mon Sep 17 00:00:00 2001 +From: Jan Kara <jack@suse.com> +Date: Mon, 7 Dec 2015 14:31:11 -0500 +Subject: [PATCH 3/4] ext4: fix races between buffered IO and collapse / insert + range + +Current code implementing FALLOC_FL_COLLAPSE_RANGE and +FALLOC_FL_INSERT_RANGE is prone to races with buffered writes and page +faults. If buffered write or write via mmap manages to squeeze between +filemap_write_and_wait_range() and truncate_pagecache() in the fallocate +implementations, the written data is simply discarded by +truncate_pagecache() although it should have been shifted. + +Fix the problem by moving filemap_write_and_wait_range() call inside +i_mutex and i_mmap_sem. That way we are protected against races with +both buffered writes and page faults. + +Signed-off-by: Jan Kara <jack@suse.com> +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +--- + fs/ext4/extents.c | 59 +++++++++++++++++++++++++++++-------------------------- + 1 file changed, 31 insertions(+), 28 deletions(-) + +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 65b5ada2833f..4b105c96df08 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -5487,21 +5487,7 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len) + return ret; + } + +- /* +- * Need to round down offset to be aligned with page size boundary +- * for page size > block size. +- */ +- ioffset = round_down(offset, PAGE_SIZE); +- +- /* Write out all dirty pages */ +- ret = filemap_write_and_wait_range(inode->i_mapping, ioffset, +- LLONG_MAX); +- if (ret) +- return ret; +- +- /* Take mutex lock */ + mutex_lock(&inode->i_mutex); +- + /* + * There is no need to overlap collapse range with EOF, in which case + * it is effectively a truncate operation +@@ -5526,6 +5512,27 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len) + * page cache. + */ + down_write(&EXT4_I(inode)->i_mmap_sem); ++ /* ++ * Need to round down offset to be aligned with page size boundary ++ * for page size > block size. ++ */ ++ ioffset = round_down(offset, PAGE_SIZE); ++ /* ++ * Write tail of the last page before removed range since it will get ++ * removed from the page cache below. ++ */ ++ ret = filemap_write_and_wait_range(inode->i_mapping, ioffset, offset); ++ if (ret) ++ goto out_mmap; ++ /* ++ * Write data that will be shifted to preserve them when discarding ++ * page cache below. We are also protected from pages becoming dirty ++ * by i_mmap_sem. ++ */ ++ ret = filemap_write_and_wait_range(inode->i_mapping, offset + len, ++ LLONG_MAX); ++ if (ret) ++ goto out_mmap; + truncate_pagecache(inode, ioffset); + + credits = ext4_writepage_trans_blocks(inode); +@@ -5626,21 +5633,7 @@ int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len) + return ret; + } + +- /* +- * Need to round down to align start offset to page size boundary +- * for page size > block size. +- */ +- ioffset = round_down(offset, PAGE_SIZE); +- +- /* Write out all dirty pages */ +- ret = filemap_write_and_wait_range(inode->i_mapping, ioffset, +- LLONG_MAX); +- if (ret) +- return ret; +- +- /* Take mutex lock */ + mutex_lock(&inode->i_mutex); +- + /* Currently just for extent based files */ + if (!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) { + ret = -EOPNOTSUPP; +@@ -5668,6 +5661,16 @@ int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len) + * page cache. + */ + down_write(&EXT4_I(inode)->i_mmap_sem); ++ /* ++ * Need to round down to align start offset to page size boundary ++ * for page size > block size. ++ */ ++ ioffset = round_down(offset, PAGE_SIZE); ++ /* Write out all dirty pages */ ++ ret = filemap_write_and_wait_range(inode->i_mapping, ioffset, ++ LLONG_MAX); ++ if (ret) ++ goto out_mmap; + truncate_pagecache(inode, ioffset); + + credits = ext4_writepage_trans_blocks(inode); +-- +2.5.5 + diff --git a/ext4-fix-races-between-page-faults-and-hole-punching.patch b/ext4-fix-races-between-page-faults-and-hole-punching.patch new file mode 100644 index 000000000..9034b958c --- /dev/null +++ b/ext4-fix-races-between-page-faults-and-hole-punching.patch @@ -0,0 +1,442 @@ +From ea3d7209ca01da209cda6f0dea8be9cc4b7a933b Mon Sep 17 00:00:00 2001 +From: Jan Kara <jack@suse.com> +Date: Mon, 7 Dec 2015 14:28:03 -0500 +Subject: [PATCH 1/4] ext4: fix races between page faults and hole punching + +Currently, page faults and hole punching are completely unsynchronized. +This can result in page fault faulting in a page into a range that we +are punching after truncate_pagecache_range() has been called and thus +we can end up with a page mapped to disk blocks that will be shortly +freed. Filesystem corruption will shortly follow. Note that the same +race is avoided for truncate by checking page fault offset against +i_size but there isn't similar mechanism available for punching holes. + +Fix the problem by creating new rw semaphore i_mmap_sem in inode and +grab it for writing over truncate, hole punching, and other functions +removing blocks from extent tree and for read over page faults. We +cannot easily use i_data_sem for this since that ranks below transaction +start and we need something ranking above it so that it can be held over +the whole truncate / hole punching operation. Also remove various +workarounds we had in the code to reduce race window when page fault +could have created pages with stale mapping information. + +Signed-off-by: Jan Kara <jack@suse.com> +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +--- + fs/ext4/ext4.h | 10 +++++++++ + fs/ext4/extents.c | 54 ++++++++++++++++++++++++-------------------- + fs/ext4/file.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++-------- + fs/ext4/inode.c | 36 +++++++++++++++++++++-------- + fs/ext4/super.c | 1 + + fs/ext4/truncate.h | 2 ++ + 6 files changed, 127 insertions(+), 42 deletions(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index cc7ca4e87144..348a5ff4a0e2 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -910,6 +910,15 @@ struct ext4_inode_info { + * by other means, so we have i_data_sem. + */ + struct rw_semaphore i_data_sem; ++ /* ++ * i_mmap_sem is for serializing page faults with truncate / punch hole ++ * operations. We have to make sure that new page cannot be faulted in ++ * a section of the inode that is being punched. We cannot easily use ++ * i_data_sem for this since we need protection for the whole punch ++ * operation and i_data_sem ranks below transaction start so we have ++ * to occasionally drop it. ++ */ ++ struct rw_semaphore i_mmap_sem; + struct inode vfs_inode; + struct jbd2_inode *jinode; + +@@ -2484,6 +2493,7 @@ extern int ext4_chunk_trans_blocks(struct inode *, int nrblocks); + extern int ext4_zero_partial_blocks(handle_t *handle, struct inode *inode, + loff_t lstart, loff_t lend); + extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf); ++extern int ext4_filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf); + extern qsize_t *ext4_get_reserved_space(struct inode *inode); + extern void ext4_da_update_reserve_space(struct inode *inode, + int used, int quota_claim); +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 551353b1b17a..5be9ca5a8a7a 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -4770,7 +4770,6 @@ static long ext4_zero_range(struct file *file, loff_t offset, + int partial_begin, partial_end; + loff_t start, end; + ext4_lblk_t lblk; +- struct address_space *mapping = inode->i_mapping; + unsigned int blkbits = inode->i_blkbits; + + trace_ext4_zero_range(inode, offset, len, mode); +@@ -4786,17 +4785,6 @@ static long ext4_zero_range(struct file *file, loff_t offset, + } + + /* +- * Write out all dirty pages to avoid race conditions +- * Then release them. +- */ +- if (mapping->nrpages && mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) { +- ret = filemap_write_and_wait_range(mapping, offset, +- offset + len - 1); +- if (ret) +- return ret; +- } +- +- /* + * Round up offset. This is not fallocate, we neet to zero out + * blocks, so convert interior block aligned part of the range to + * unwritten and possibly manually zero out unaligned parts of the +@@ -4856,16 +4844,22 @@ static long ext4_zero_range(struct file *file, loff_t offset, + flags |= (EXT4_GET_BLOCKS_CONVERT_UNWRITTEN | + EXT4_EX_NOCACHE); + +- /* Now release the pages and zero block aligned part of pages*/ +- truncate_pagecache_range(inode, start, end - 1); +- inode->i_mtime = inode->i_ctime = ext4_current_time(inode); +- + /* Wait all existing dio workers, newcomers will block on i_mutex */ + ext4_inode_block_unlocked_dio(inode); + inode_dio_wait(inode); + ++ /* ++ * Prevent page faults from reinstantiating pages we have ++ * released from page cache. ++ */ ++ down_write(&EXT4_I(inode)->i_mmap_sem); ++ /* Now release the pages and zero block aligned part of pages */ ++ truncate_pagecache_range(inode, start, end - 1); ++ inode->i_mtime = inode->i_ctime = ext4_current_time(inode); ++ + ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size, + flags, mode); ++ up_write(&EXT4_I(inode)->i_mmap_sem); + if (ret) + goto out_dio; + } +@@ -5524,17 +5518,22 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len) + goto out_mutex; + } + +- truncate_pagecache(inode, ioffset); +- + /* Wait for existing dio to complete */ + ext4_inode_block_unlocked_dio(inode); + inode_dio_wait(inode); + ++ /* ++ * Prevent page faults from reinstantiating pages we have released from ++ * page cache. ++ */ ++ down_write(&EXT4_I(inode)->i_mmap_sem); ++ truncate_pagecache(inode, ioffset); ++ + credits = ext4_writepage_trans_blocks(inode); + handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits); + if (IS_ERR(handle)) { + ret = PTR_ERR(handle); +- goto out_dio; ++ goto out_mmap; + } + + down_write(&EXT4_I(inode)->i_data_sem); +@@ -5573,7 +5572,8 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len) + + out_stop: + ext4_journal_stop(handle); +-out_dio: ++out_mmap: ++ up_write(&EXT4_I(inode)->i_mmap_sem); + ext4_inode_resume_unlocked_dio(inode); + out_mutex: + mutex_unlock(&inode->i_mutex); +@@ -5660,17 +5660,22 @@ int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len) + goto out_mutex; + } + +- truncate_pagecache(inode, ioffset); +- + /* Wait for existing dio to complete */ + ext4_inode_block_unlocked_dio(inode); + inode_dio_wait(inode); + ++ /* ++ * Prevent page faults from reinstantiating pages we have released from ++ * page cache. ++ */ ++ down_write(&EXT4_I(inode)->i_mmap_sem); ++ truncate_pagecache(inode, ioffset); ++ + credits = ext4_writepage_trans_blocks(inode); + handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits); + if (IS_ERR(handle)) { + ret = PTR_ERR(handle); +- goto out_dio; ++ goto out_mmap; + } + + /* Expand file to avoid data loss if there is error while shifting */ +@@ -5741,7 +5746,8 @@ int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len) + + out_stop: + ext4_journal_stop(handle); +-out_dio: ++out_mmap: ++ up_write(&EXT4_I(inode)->i_mmap_sem); + ext4_inode_resume_unlocked_dio(inode); + out_mutex: + mutex_unlock(&inode->i_mutex); +diff --git a/fs/ext4/file.c b/fs/ext4/file.c +index 113837e7ba98..0d24ebcd7c9e 100644 +--- a/fs/ext4/file.c ++++ b/fs/ext4/file.c +@@ -209,15 +209,18 @@ static int ext4_dax_fault(struct vm_area_struct *vma, struct vm_fault *vmf) + { + int result; + handle_t *handle = NULL; +- struct super_block *sb = file_inode(vma->vm_file)->i_sb; ++ struct inode *inode = file_inode(vma->vm_file); ++ struct super_block *sb = inode->i_sb; + bool write = vmf->flags & FAULT_FLAG_WRITE; + + if (write) { + sb_start_pagefault(sb); + file_update_time(vma->vm_file); ++ down_read(&EXT4_I(inode)->i_mmap_sem); + handle = ext4_journal_start_sb(sb, EXT4_HT_WRITE_PAGE, + EXT4_DATA_TRANS_BLOCKS(sb)); +- } ++ } else ++ down_read(&EXT4_I(inode)->i_mmap_sem); + + if (IS_ERR(handle)) + result = VM_FAULT_SIGBUS; +@@ -228,8 +231,10 @@ static int ext4_dax_fault(struct vm_area_struct *vma, struct vm_fault *vmf) + if (write) { + if (!IS_ERR(handle)) + ext4_journal_stop(handle); ++ up_read(&EXT4_I(inode)->i_mmap_sem); + sb_end_pagefault(sb); +- } ++ } else ++ up_read(&EXT4_I(inode)->i_mmap_sem); + + return result; + } +@@ -246,10 +251,12 @@ static int ext4_dax_pmd_fault(struct vm_area_struct *vma, unsigned long addr, + if (write) { + sb_start_pagefault(sb); + file_update_time(vma->vm_file); ++ down_read(&EXT4_I(inode)->i_mmap_sem); + handle = ext4_journal_start_sb(sb, EXT4_HT_WRITE_PAGE, + ext4_chunk_trans_blocks(inode, + PMD_SIZE / PAGE_SIZE)); +- } ++ } else ++ down_read(&EXT4_I(inode)->i_mmap_sem); + + if (IS_ERR(handle)) + result = VM_FAULT_SIGBUS; +@@ -260,30 +267,71 @@ static int ext4_dax_pmd_fault(struct vm_area_struct *vma, unsigned long addr, + if (write) { + if (!IS_ERR(handle)) + ext4_journal_stop(handle); ++ up_read(&EXT4_I(inode)->i_mmap_sem); + sb_end_pagefault(sb); +- } ++ } else ++ up_read(&EXT4_I(inode)->i_mmap_sem); + + return result; + } + + static int ext4_dax_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) + { +- return dax_mkwrite(vma, vmf, ext4_get_block_dax, +- ext4_end_io_unwritten); ++ int err; ++ struct inode *inode = file_inode(vma->vm_file); ++ ++ sb_start_pagefault(inode->i_sb); ++ file_update_time(vma->vm_file); ++ down_read(&EXT4_I(inode)->i_mmap_sem); ++ err = __dax_mkwrite(vma, vmf, ext4_get_block_dax, ++ ext4_end_io_unwritten); ++ up_read(&EXT4_I(inode)->i_mmap_sem); ++ sb_end_pagefault(inode->i_sb); ++ ++ return err; ++} ++ ++/* ++ * Handle write fault for VM_MIXEDMAP mappings. Similarly to ext4_dax_mkwrite() ++ * handler we check for races agaist truncate. Note that since we cycle through ++ * i_mmap_sem, we are sure that also any hole punching that began before we ++ * were called is finished by now and so if it included part of the file we ++ * are working on, our pte will get unmapped and the check for pte_same() in ++ * wp_pfn_shared() fails. Thus fault gets retried and things work out as ++ * desired. ++ */ ++static int ext4_dax_pfn_mkwrite(struct vm_area_struct *vma, ++ struct vm_fault *vmf) ++{ ++ struct inode *inode = file_inode(vma->vm_file); ++ struct super_block *sb = inode->i_sb; ++ int ret = VM_FAULT_NOPAGE; ++ loff_t size; ++ ++ sb_start_pagefault(sb); ++ file_update_time(vma->vm_file); ++ down_read(&EXT4_I(inode)->i_mmap_sem); ++ size = (i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT; ++ if (vmf->pgoff >= size) ++ ret = VM_FAULT_SIGBUS; ++ up_read(&EXT4_I(inode)->i_mmap_sem); ++ sb_end_pagefault(sb); ++ ++ return ret; + } + + static const struct vm_operations_struct ext4_dax_vm_ops = { + .fault = ext4_dax_fault, + .pmd_fault = ext4_dax_pmd_fault, + .page_mkwrite = ext4_dax_mkwrite, +- .pfn_mkwrite = dax_pfn_mkwrite, ++ .pfn_mkwrite = ext4_dax_pfn_mkwrite, + }; + #else + #define ext4_dax_vm_ops ext4_file_vm_ops + #endif + + static const struct vm_operations_struct ext4_file_vm_ops = { +- .fault = filemap_fault, ++ .fault = ext4_filemap_fault, + .map_pages = filemap_map_pages, + .page_mkwrite = ext4_page_mkwrite, + }; +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index ea433a7f4bca..d1207d03c961 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -3623,6 +3623,15 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length) + + } + ++ /* Wait all existing dio workers, newcomers will block on i_mutex */ ++ ext4_inode_block_unlocked_dio(inode); ++ inode_dio_wait(inode); ++ ++ /* ++ * Prevent page faults from reinstantiating pages we have released from ++ * page cache. ++ */ ++ down_write(&EXT4_I(inode)->i_mmap_sem); + first_block_offset = round_up(offset, sb->s_blocksize); + last_block_offset = round_down((offset + length), sb->s_blocksize) - 1; + +@@ -3631,10 +3640,6 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length) + truncate_pagecache_range(inode, first_block_offset, + last_block_offset); + +- /* Wait all existing dio workers, newcomers will block on i_mutex */ +- ext4_inode_block_unlocked_dio(inode); +- inode_dio_wait(inode); +- + if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) + credits = ext4_writepage_trans_blocks(inode); + else +@@ -3680,16 +3685,12 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length) + if (IS_SYNC(inode)) + ext4_handle_sync(handle); + +- /* Now release the pages again to reduce race window */ +- if (last_block_offset > first_block_offset) +- truncate_pagecache_range(inode, first_block_offset, +- last_block_offset); +- + inode->i_mtime = inode->i_ctime = ext4_current_time(inode); + ext4_mark_inode_dirty(handle, inode); + out_stop: + ext4_journal_stop(handle); + out_dio: ++ up_write(&EXT4_I(inode)->i_mmap_sem); + ext4_inode_resume_unlocked_dio(inode); + out_mutex: + mutex_unlock(&inode->i_mutex); +@@ -4823,6 +4824,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) + } else + ext4_wait_for_tail_page_commit(inode); + } ++ down_write(&EXT4_I(inode)->i_mmap_sem); + /* + * Truncate pagecache after we've waited for commit + * in data=journal mode to make pages freeable. +@@ -4830,6 +4832,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) + truncate_pagecache(inode, inode->i_size); + if (shrink) + ext4_truncate(inode); ++ up_write(&EXT4_I(inode)->i_mmap_sem); + } + + if (!rc) { +@@ -5278,6 +5281,8 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) + + sb_start_pagefault(inode->i_sb); + file_update_time(vma->vm_file); ++ ++ down_read(&EXT4_I(inode)->i_mmap_sem); + /* Delalloc case is easy... */ + if (test_opt(inode->i_sb, DELALLOC) && + !ext4_should_journal_data(inode) && +@@ -5347,6 +5352,19 @@ retry_alloc: + out_ret: + ret = block_page_mkwrite_return(ret); + out: ++ up_read(&EXT4_I(inode)->i_mmap_sem); + sb_end_pagefault(inode->i_sb); + return ret; + } ++ ++int ext4_filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ++{ ++ struct inode *inode = file_inode(vma->vm_file); ++ int err; ++ ++ down_read(&EXT4_I(inode)->i_mmap_sem); ++ err = filemap_fault(vma, vmf); ++ up_read(&EXT4_I(inode)->i_mmap_sem); ++ ++ return err; ++} +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index c9ab67da6e5a..493370e6590e 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -958,6 +958,7 @@ static void init_once(void *foo) + INIT_LIST_HEAD(&ei->i_orphan); + init_rwsem(&ei->xattr_sem); + init_rwsem(&ei->i_data_sem); ++ init_rwsem(&ei->i_mmap_sem); + inode_init_once(&ei->vfs_inode); + } + +diff --git a/fs/ext4/truncate.h b/fs/ext4/truncate.h +index 011ba6670d99..c70d06a383e2 100644 +--- a/fs/ext4/truncate.h ++++ b/fs/ext4/truncate.h +@@ -10,8 +10,10 @@ + */ + static inline void ext4_truncate_failed_write(struct inode *inode) + { ++ down_write(&EXT4_I(inode)->i_mmap_sem); + truncate_inode_pages(inode->i_mapping, inode->i_size); + ext4_truncate(inode); ++ up_write(&EXT4_I(inode)->i_mmap_sem); + } + + /* +-- +2.5.5 + diff --git a/ext4-fix-races-of-writeback-with-punch-hole-and-zero.patch b/ext4-fix-races-of-writeback-with-punch-hole-and-zero.patch new file mode 100644 index 000000000..9ff9e2761 --- /dev/null +++ b/ext4-fix-races-of-writeback-with-punch-hole-and-zero.patch @@ -0,0 +1,110 @@ +From 011278485ecc3cd2a3954b5d4c73101d919bf1fa Mon Sep 17 00:00:00 2001 +From: Jan Kara <jack@suse.com> +Date: Mon, 7 Dec 2015 14:34:49 -0500 +Subject: [PATCH 4/4] ext4: fix races of writeback with punch hole and zero + range + +When doing delayed allocation, update of on-disk inode size is postponed +until IO submission time. However hole punch or zero range fallocate +calls can end up discarding the tail page cache page and thus on-disk +inode size would never be properly updated. + +Make sure the on-disk inode size is updated before truncating page +cache. + +Signed-off-by: Jan Kara <jack@suse.com> +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +--- + fs/ext4/ext4.h | 3 +++ + fs/ext4/extents.c | 5 +++++ + fs/ext4/inode.c | 35 ++++++++++++++++++++++++++++++++++- + 3 files changed, 42 insertions(+), 1 deletion(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index 348a5ff4a0e2..80f76f092079 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -2858,6 +2858,9 @@ static inline int ext4_update_inode_size(struct inode *inode, loff_t newsize) + return changed; + } + ++int ext4_update_disksize_before_punch(struct inode *inode, loff_t offset, ++ loff_t len); ++ + struct ext4_group_info { + unsigned long bb_state; + struct rb_root bb_free_root; +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 4b105c96df08..3578b25fccfd 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -4847,6 +4847,11 @@ static long ext4_zero_range(struct file *file, loff_t offset, + * released from page cache. + */ + down_write(&EXT4_I(inode)->i_mmap_sem); ++ ret = ext4_update_disksize_before_punch(inode, offset, len); ++ if (ret) { ++ up_write(&EXT4_I(inode)->i_mmap_sem); ++ goto out_dio; ++ } + /* Now release the pages and zero block aligned part of pages */ + truncate_pagecache_range(inode, start, end - 1); + inode->i_mtime = inode->i_ctime = ext4_current_time(inode); +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index d1207d03c961..472e608da13d 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -3559,6 +3559,35 @@ int ext4_can_truncate(struct inode *inode) + } + + /* ++ * We have to make sure i_disksize gets properly updated before we truncate ++ * page cache due to hole punching or zero range. Otherwise i_disksize update ++ * can get lost as it may have been postponed to submission of writeback but ++ * that will never happen after we truncate page cache. ++ */ ++int ext4_update_disksize_before_punch(struct inode *inode, loff_t offset, ++ loff_t len) ++{ ++ handle_t *handle; ++ loff_t size = i_size_read(inode); ++ ++ WARN_ON(!mutex_is_locked(&inode->i_mutex)); ++ if (offset > size || offset + len < size) ++ return 0; ++ ++ if (EXT4_I(inode)->i_disksize >= size) ++ return 0; ++ ++ handle = ext4_journal_start(inode, EXT4_HT_MISC, 1); ++ if (IS_ERR(handle)) ++ return PTR_ERR(handle); ++ ext4_update_i_disksize(inode, size); ++ ext4_mark_inode_dirty(handle, inode); ++ ext4_journal_stop(handle); ++ ++ return 0; ++} ++ ++/* + * ext4_punch_hole: punches a hole in a file by releaseing the blocks + * associated with the given offset and length + * +@@ -3636,9 +3665,13 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length) + last_block_offset = round_down((offset + length), sb->s_blocksize) - 1; + + /* Now release the pages and zero block aligned part of pages*/ +- if (last_block_offset > first_block_offset) ++ if (last_block_offset > first_block_offset) { ++ ret = ext4_update_disksize_before_punch(inode, offset, length); ++ if (ret) ++ goto out_dio; + truncate_pagecache_range(inode, first_block_offset, + last_block_offset); ++ } + + if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) + credits = ext4_writepage_trans_blocks(inode); +-- +2.5.5 + diff --git a/ext4-move-unlocked-dio-protection-from-ext4_alloc_fi.patch b/ext4-move-unlocked-dio-protection-from-ext4_alloc_fi.patch new file mode 100644 index 000000000..3bf6765fa --- /dev/null +++ b/ext4-move-unlocked-dio-protection-from-ext4_alloc_fi.patch @@ -0,0 +1,93 @@ +From 17048e8a083fec7ad841d88ef0812707fbc7e39f Mon Sep 17 00:00:00 2001 +From: Jan Kara <jack@suse.com> +Date: Mon, 7 Dec 2015 14:29:17 -0500 +Subject: [PATCH 2/4] ext4: move unlocked dio protection from + ext4_alloc_file_blocks() + +Currently ext4_alloc_file_blocks() was handling protection against +unlocked DIO. However we now need to sometimes call it under i_mmap_sem +and sometimes not and DIO protection ranks above it (although strictly +speaking this cannot currently create any deadlocks). Also +ext4_zero_range() was actually getting & releasing unlocked DIO +protection twice in some cases. Luckily it didn't introduce any real bug +but it was a land mine waiting to be stepped on. So move DIO protection +out from ext4_alloc_file_blocks() into the two callsites. + +Signed-off-by: Jan Kara <jack@suse.com> +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +--- + fs/ext4/extents.c | 21 ++++++++++----------- + 1 file changed, 10 insertions(+), 11 deletions(-) + +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 5be9ca5a8a7a..65b5ada2833f 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -4685,10 +4685,6 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset, + if (len <= EXT_UNWRITTEN_MAX_LEN) + flags |= EXT4_GET_BLOCKS_NO_NORMALIZE; + +- /* Wait all existing dio workers, newcomers will block on i_mutex */ +- ext4_inode_block_unlocked_dio(inode); +- inode_dio_wait(inode); +- + /* + * credits to insert 1 extent into extent tree + */ +@@ -4752,8 +4748,6 @@ retry: + goto retry; + } + +- ext4_inode_resume_unlocked_dio(inode); +- + return ret > 0 ? ret2 : ret; + } + +@@ -4827,6 +4821,10 @@ static long ext4_zero_range(struct file *file, loff_t offset, + if (mode & FALLOC_FL_KEEP_SIZE) + flags |= EXT4_GET_BLOCKS_KEEP_SIZE; + ++ /* Wait all existing dio workers, newcomers will block on i_mutex */ ++ ext4_inode_block_unlocked_dio(inode); ++ inode_dio_wait(inode); ++ + /* Preallocate the range including the unaligned edges */ + if (partial_begin || partial_end) { + ret = ext4_alloc_file_blocks(file, +@@ -4835,7 +4833,7 @@ static long ext4_zero_range(struct file *file, loff_t offset, + round_down(offset, 1 << blkbits)) >> blkbits, + new_size, flags, mode); + if (ret) +- goto out_mutex; ++ goto out_dio; + + } + +@@ -4844,10 +4842,6 @@ static long ext4_zero_range(struct file *file, loff_t offset, + flags |= (EXT4_GET_BLOCKS_CONVERT_UNWRITTEN | + EXT4_EX_NOCACHE); + +- /* Wait all existing dio workers, newcomers will block on i_mutex */ +- ext4_inode_block_unlocked_dio(inode); +- inode_dio_wait(inode); +- + /* + * Prevent page faults from reinstantiating pages we have + * released from page cache. +@@ -4992,8 +4986,13 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) + goto out; + } + ++ /* Wait all existing dio workers, newcomers will block on i_mutex */ ++ ext4_inode_block_unlocked_dio(inode); ++ inode_dio_wait(inode); ++ + ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size, + flags, mode); ++ ext4_inode_resume_unlocked_dio(inode); + if (ret) + goto out; + +-- +2.5.5 + diff --git a/input-gtco-fix-crash-on-detecting-device-without-end.patch b/input-gtco-fix-crash-on-detecting-device-without-end.patch new file mode 100644 index 000000000..849f607a5 --- /dev/null +++ b/input-gtco-fix-crash-on-detecting-device-without-end.patch @@ -0,0 +1,49 @@ +Subject: [PATCH] Input: gtco: fix crash on detecting device without endpoints +From: Vladis Dronov <vdronov@redhat.com> +Date: 2016-03-18 18:35:00 + +The gtco driver expects at least one valid endpoint. If given +malicious descriptors that specify 0 for the number of endpoints, +it will crash in the probe function. Ensure there is at least +one endpoint on the interface before using it. Fix minor coding +style issue. + +The full report of this issue can be found here: +http://seclists.org/bugtraq/2016/Mar/86 + +Reported-by: Ralf Spenneberg <ralf@spenneberg.net> +Signed-off-by: Vladis Dronov <vdronov@redhat.com> +--- + drivers/input/tablet/gtco.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c +index 3a7f3a4..7c18249 100644 +--- a/drivers/input/tablet/gtco.c ++++ b/drivers/input/tablet/gtco.c +@@ -858,6 +858,14 @@ static int gtco_probe(struct usb_interface *usbinterface, + goto err_free_buf; + } + ++ /* Sanity check that a device has an endpoint */ ++ if (usbinterface->altsetting[0].desc.bNumEndpoints < 1) { ++ dev_err(&usbinterface->dev, ++ "Invalid number of endpoints\n"); ++ error = -EINVAL; ++ goto err_free_urb; ++ } ++ + /* + * The endpoint is always altsetting 0, we know this since we know + * this device only has one interrupt endpoint +@@ -879,7 +887,7 @@ static int gtco_probe(struct usb_interface *usbinterface, + * HID report descriptor + */ + if (usb_get_extra_descriptor(usbinterface->cur_altsetting, +- HID_DEVICE_TYPE, &hid_desc) != 0){ ++ HID_DEVICE_TYPE, &hid_desc) != 0) { + dev_err(&usbinterface->dev, + "Can't retrieve exta USB descriptor to get hid report descriptor length\n"); + error = -EIO; +-- +2.5.0 diff --git a/kernel.spec b/kernel.spec index 38f802232..bed17f105 100644 --- a/kernel.spec +++ b/kernel.spec @@ -58,7 +58,7 @@ Summary: The Linux kernel %define stable_rc 0 # Do we have a -stable update to apply? -%define stable_update 6 +%define stable_update 7 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev %{stable_update} @@ -643,9 +643,6 @@ Patch660: 0001-drm-i915-Pretend-cursor-is-always-on-for-ILK-style-W.patch #rhbz 1316719 Patch662: 0001-cdc-acm-fix-NULL-pointer-reference.patch -#rhbz 1316136 -Patch663: USB-serial-ftdi_sio-Add-support-for-ICP-DAS-I-756xU-.patch - #CVE-2016-3135 rhbz 1317386 1317387 Patch664: netfilter-x_tables-check-for-size-overflow.patch @@ -655,6 +652,31 @@ Patch665: netfilter-x_tables-deal-with-bogus-nextoffset-values.patch #CVE-2016-3135 rhbz 1318172 1318270 Patch666: ipv4-Dont-do-expensive-useless-work-during-inetdev-des.patch +#rhbz 1315013 +Patch679: 0001-uas-Limit-qdepth-at-the-scsi-host-level.patch + +#CVE-2016-2187 rhbz 1317017 1317010 +Patch686: input-gtco-fix-crash-on-detecting-device-without-end.patch + +#rhbz 1295646 +Patch688: 09-29-drm-udl-Use-unlocked-gem-unreferencing.patch + +# CVE-2016-3672 rhbz 1324749 1324750 +Patch690: x86-mm-32-Enable-full-randomization-on-i386-and-X86_.patch + +#CVE-2015-8839 rhbz 1323577 1323579 +Patch691: ext4-fix-races-between-page-faults-and-hole-punching.patch +Patch692: ext4-move-unlocked-dio-protection-from-ext4_alloc_fi.patch +Patch693: ext4-fix-races-between-buffered-IO-and-collapse-inse.patch +Patch694: ext4-fix-races-of-writeback-with-punch-hole-and-zero.patch + +#CVE-2016-3951 rhbz 1324782 1324815 +Patch695: cdc_ncm-do-not-call-usbnet_link_change-from-cdc_ncm_.patch +Patch696: usbnet-cleanup-after-bind-in-probe.patch + +#rhbz 1317116 +Patch697: HID-wacom-fix-Bamboo-ONE-oops.patch + # END OF PATCH DEFINITIONS %endif @@ -1357,6 +1379,70 @@ ApplyPatch netfilter-x_tables-deal-with-bogus-nextoffset-values.patch #CVE-2016-3135 rhbz 1318172 1318270 ApplyPatch ipv4-Dont-do-expensive-useless-work-during-inetdev-des.patch +#CVE-2016-2184 rhbz 1317012 1317470 +ApplyPatch ALSA-usb-audio-Fix-NULL-dereference-in-create_fixed_.patch +ApplyPatch ALSA-usb-audio-Add-sanity-checks-for-endpoint-access.patch +ApplyPatch ALSA-usb-audio-Minor-code-cleanup-in-create_fixed_st.patch +ApplyPatch ALSA-usb-audio-Fix-double-free-in-error-paths-after-.patch + +#CVE-2016-3137 rhbz 1317010 1316996 +ApplyPatch cypress_m8-add-sanity-checking.patch + +#CVE-2016-2186 rhbz 1317015 1317464 +ApplyPatch USB-input-powermate-fix-oops-with-malicious-USB-desc.patch + +#CVE-2016-2188 rhbz 1317018 1317467 +ApplyPatch USB-iowarrior-fix-oops-with-malicious-USB-descriptor.patch + +#CVE-2016-2185 rhbz 1317014 1317471 +ApplyPatch usb_driver_claim_interface-add-sanity-checking.patch +ApplyPatch Input-ati_remote2-fix-crashes-on-detecting-device-wi.patch + +#CVE-2016-3138 rhbz 1317010 1316204 +ApplyPatch cdc-acm-more-sanity-checking.patch + +#CVE-2016-3140 rhbz 1317010 1316995 +ApplyPatch digi_acceleport-do-sanity-checking-for-the-number-of.patch + +ApplyPatch ims-pcu-sanity-check-against-missing-interfaces.patch + +#rhbz 1315013 +ApplyPatch 0001-uas-Limit-qdepth-at-the-scsi-host-level.patch + +#rhbz 1317190 +ApplyPatch thermal-fix.patch + +#rhbz 1318079 +ApplyPatch 0001-Input-synaptics-handle-spurious-release-of-trackstic.patch + +#CVE-2016-2187 rhbz 1317017 1317010 +ApplyPatch input-gtco-fix-crash-on-detecting-device-without-end.patch + +#CVE-2016-3136 rhbz 1317007 1317010 +ApplyPatch mct_u232-sanity-checking-in-probe.patch + +#rhbz 1295646 +ApplyPatch 09-29-drm-udl-Use-unlocked-gem-unreferencing.patch + +# CVE-2016-3157 rhbz 1315711 1321948 +ApplyPatch x86-iopl-64-Properly-context-switch-IOPL-on-Xen-PV.patch + +# CVE-2016-3672 rhbz 1324749 1324750 +ApplyPatch x86-mm-32-Enable-full-randomization-on-i386-and-X86_.patch + +#CVE-2015-8839 rhbz 1323577 1323579 +ApplyPatch ext4-fix-races-between-page-faults-and-hole-punching.patch +ApplyPatch ext4-move-unlocked-dio-protection-from-ext4_alloc_fi.patch +ApplyPatch ext4-fix-races-between-buffered-IO-and-collapse-inse.patch +ApplyPatch ext4-fix-races-of-writeback-with-punch-hole-and-zero.patch + +#CVE-2016-3951 rhbz 1324782 1324815 +ApplyPatch cdc_ncm-do-not-call-usbnet_link_change-from-cdc_ncm_.patch +ApplyPatch usbnet-cleanup-after-bind-in-probe.patch + +#rhbz 1317116 +ApplyPatch HID-wacom-fix-Bamboo-ONE-oops.patch + # END OF PATCH APPLICATIONS %endif @@ -2206,6 +2292,50 @@ fi # # %changelog +* Tue Apr 12 2016 Laura Abbott <labbott@redhat.com> - 4.4.7-200 +- Linux v4.4.7 + +* Tue Apr 12 2016 Josh Boyer <jwboyer@fedoraproject.org> +- Fix Bamboo ONE issues (rhbz 1317116) + +* Mon Apr 11 2016 Josh Boyer <jwboyer@fedoraproject.org> +- CVE-2016-3951 usbnet: crash on invalid USB descriptors (rhbz 1324782 1324815) +- CVE-2015-8839 ext4: data corruption due to punch hole races (rhbz 1323577 1323579) + +* Thu Apr 07 2016 Justin M. Forbes <jforbes@fedoraproject.org> +- Enable Full Randomization on 32bit x86 CVE-2016-3672 (rhbz 1324749 1324750) +` +* Thu Mar 31 2016 Josh Boyer <jwboyer@fedoraproject.org> +- Add two more patches for CVE-2016-2184 + +* Wed Mar 30 2016 Laura Abbott <labbott@redhat.com> - 4.4.6-201 +- Bump and build + +* Tue Mar 29 2016 Josh Boyer <jwboyer@fedoraproject.org> +- CVE-2016-3157 xen: priv escalation on 64bit PV domains with io port access (rhbz 1315711 1321948) + +* Wed Mar 23 2016 Laura Abbott <labbott@fedoraproject.org> +- drm/udl: Use unlocked gem unreferencing (rhbz 1295646) + +* Tue Mar 22 2016 Josh Boyer <jwboyer@fedoraproject.org> +- CVE-2016-3136 mct_u232: oops on invalid USB descriptors (rhbz 1317007 1317010) +- CVE-2016-2187 gtco: oops on invalid USB descriptors (rhbz 1317017 1317010) + +* Mon Mar 21 2016 Laura Abbott <labbott@fedoraproject.org> +- uas: Limit qdepth at the scsi-host level (rhbz 1315013) +- Fix for performance regression caused by thermal (rhbz 1317190) +- Input: synaptics - handle spurious release of trackstick buttons, again (rhbz 1318079) + +* Fri Mar 18 2016 Josh Boyer <jwboyer@fedoraproject.org> +- ims-pcu: sanity checking on missing interfaces +- CVE-2016-3140 digi_acceleport: oops on invalid USB descriptors (rhbz 1317010 1316995) +- CVE-2016-3138 cdc_acm: oops on invalid USB descriptors (rhbz 1317010 1316204) +- CVE-2016-2185 ati_remote2: oops on invalid USB descriptors (rhbz 1317014 1317471) +- CVE-2016-2188 iowarrior: oops on invalid USB descriptors (rhbz 1317018 1317467) +- CVE-2016-2186 powermate: oops on invalid USB descriptors (rhbz 1317015 1317464) +- CVE-2016-3137 cypress_m8: oops on invalid USB descriptors (rhbz 1317010 1316996) +- CVE-2016-2184 alsa: panic on invalid USB descriptors (rhbz 1317012 1317470) + * Wed Mar 16 2016 Laura Abbott <labbott@redhat.com> - 4.4.6-200 - Linux v4.4.6 @@ -1,3 +1,3 @@ 9a78fa2eb6c68ca5a40ed5af08142599 linux-4.4.tar.xz dcbc8fe378a676d5d0dd208cf524e144 perf-man-4.4.tar.gz -d48f09bf61f2500d70f839e190dc7c5a patch-4.4.6.xz +2286314f215706401dd51bf07b179ae4 patch-4.4.7.xz diff --git a/usbnet-cleanup-after-bind-in-probe.patch b/usbnet-cleanup-after-bind-in-probe.patch new file mode 100644 index 000000000..dc231a943 --- /dev/null +++ b/usbnet-cleanup-after-bind-in-probe.patch @@ -0,0 +1,39 @@ +From 1666984c8625b3db19a9abc298931d35ab7bc64b Mon Sep 17 00:00:00 2001 +From: Oliver Neukum <oneukum@suse.com> +Date: Mon, 7 Mar 2016 11:31:10 +0100 +Subject: [PATCH] usbnet: cleanup after bind() in probe() + +In case bind() works, but a later error forces bailing +in probe() in error cases work and a timer may be scheduled. +They must be killed. This fixes an error case related to +the double free reported in +http://www.spinics.net/lists/netdev/msg367669.html +and needs to go on top of Linus' fix to cdc-ncm. + +Signed-off-by: Oliver Neukum <ONeukum@suse.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/usb/usbnet.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c +index 0b0ba7ef14e4..10798128c03f 100644 +--- a/drivers/net/usb/usbnet.c ++++ b/drivers/net/usb/usbnet.c +@@ -1769,6 +1769,13 @@ out3: + if (info->unbind) + info->unbind (dev, udev); + out1: ++ /* subdrivers must undo all they did in bind() if they ++ * fail it, but we may fail later and a deferred kevent ++ * may trigger an error resubmitting itself and, worse, ++ * schedule a timer. So we kill it all just in case. ++ */ ++ cancel_work_sync(&dev->kevent); ++ del_timer_sync(&dev->delay); + free_netdev(net); + out: + return status; +-- +2.5.5 + diff --git a/x86-Lock-down-IO-port-access-when-module-security-is.patch b/x86-Lock-down-IO-port-access-when-module-security-is.patch index 708006c2e..185b1da99 100644 --- a/x86-Lock-down-IO-port-access-when-module-security-is.patch +++ b/x86-Lock-down-IO-port-access-when-module-security-is.patch @@ -1,8 +1,7 @@ -From 7a3cdd26e6d38031338a6cb591ec2f3faaa9234b Mon Sep 17 00:00:00 2001 +From 8010b5eb4680df797575e6306d4d891200e303ab Mon Sep 17 00:00:00 2001 From: Matthew Garrett <matthew.garrett@nebula.com> Date: Thu, 8 Mar 2012 10:35:59 -0500 -Subject: [PATCH 03/20] x86: Lock down IO port access when module security is - enabled +Subject: [PATCH] x86: Lock down IO port access when module security is enabled IO port access would permit users to gain access to PCI configuration registers, which in turn (on a lot of hardware) give access to MMIO register @@ -16,7 +15,7 @@ Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com> 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c -index 37dae792dbbe..1ecc03ca3c15 100644 +index 589b3193f102..ab8372443efb 100644 --- a/arch/x86/kernel/ioport.c +++ b/arch/x86/kernel/ioport.c @@ -15,6 +15,7 @@ @@ -36,7 +35,7 @@ index 37dae792dbbe..1ecc03ca3c15 100644 return -EPERM; /* -@@ -103,7 +104,7 @@ SYSCALL_DEFINE1(iopl, unsigned int, level) +@@ -108,7 +109,7 @@ SYSCALL_DEFINE1(iopl, unsigned int, level) return -EINVAL; /* Trying to gain more privileges? */ if (level > old) { @@ -44,9 +43,9 @@ index 37dae792dbbe..1ecc03ca3c15 100644 + if (!capable(CAP_SYS_RAWIO) || secure_modules()) return -EPERM; } - regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12); + regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | diff --git a/drivers/char/mem.c b/drivers/char/mem.c -index 6b1721f978c2..53fe675f9bd7 100644 +index 71025c2f6bbb..86e5bfa91563 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -27,6 +27,7 @@ @@ -68,5 +67,5 @@ index 6b1721f978c2..53fe675f9bd7 100644 return -EFAULT; while (count-- > 0 && i < 65536) { -- -2.4.3 +2.5.5 diff --git a/x86-mm-32-Enable-full-randomization-on-i386-and-X86_.patch b/x86-mm-32-Enable-full-randomization-on-i386-and-X86_.patch new file mode 100644 index 000000000..0776982c1 --- /dev/null +++ b/x86-mm-32-Enable-full-randomization-on-i386-and-X86_.patch @@ -0,0 +1,83 @@ +From 8b8addf891de8a00e4d39fc32f93f7c5eb8feceb Mon Sep 17 00:00:00 2001 +From: Hector Marco-Gisbert <hecmargi@upv.es> +Date: Thu, 10 Mar 2016 20:51:00 +0100 +Subject: [PATCH] x86/mm/32: Enable full randomization on i386 and X86_32 + +Currently on i386 and on X86_64 when emulating X86_32 in legacy mode, only +the stack and the executable are randomized but not other mmapped files +(libraries, vDSO, etc.). This patch enables randomization for the +libraries, vDSO and mmap requests on i386 and in X86_32 in legacy mode. + +By default on i386 there are 8 bits for the randomization of the libraries, +vDSO and mmaps which only uses 1MB of VA. + +This patch preserves the original randomness, using 1MB of VA out of 3GB or +4GB. We think that 1MB out of 3GB is not a big cost for having the ASLR. + +The first obvious security benefit is that all objects are randomized (not +only the stack and the executable) in legacy mode which highly increases +the ASLR effectiveness, otherwise the attackers may use these +non-randomized areas. But also sensitive setuid/setgid applications are +more secure because currently, attackers can disable the randomization of +these applications by setting the ulimit stack to "unlimited". This is a +very old and widely known trick to disable the ASLR in i386 which has been +allowed for too long. + +Another trick used to disable the ASLR was to set the ADDR_NO_RANDOMIZE +personality flag, but fortunately this doesn't work on setuid/setgid +applications because there is security checks which clear Security-relevant +flags. + +This patch always randomizes the mmap_legacy_base address, removing the +possibility to disable the ASLR by setting the stack to "unlimited". + +Signed-off-by: Hector Marco-Gisbert <hecmargi@upv.es> +Acked-by: Ismael Ripoll Ripoll <iripoll@upv.es> +Acked-by: Kees Cook <keescook@chromium.org> +Acked-by: Arjan van de Ven <arjan@linux.intel.com> +Cc: Linus Torvalds <torvalds@linux-foundation.org> +Cc: Peter Zijlstra <peterz@infradead.org> +Cc: Thomas Gleixner <tglx@linutronix.de> +Cc: akpm@linux-foundation.org +Cc: kees Cook <keescook@chromium.org> +Link: http://lkml.kernel.org/r/1457639460-5242-1-git-send-email-hecmargi@upv.es +Signed-off-by: Ingo Molnar <mingo@kernel.org> +--- + arch/x86/mm/mmap.c | 14 +------------- + 1 file changed, 1 insertion(+), 13 deletions(-) + +diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c +index 96bd1e2..389939f 100644 +--- a/arch/x86/mm/mmap.c ++++ b/arch/x86/mm/mmap.c +@@ -94,18 +94,6 @@ static unsigned long mmap_base(unsigned long rnd) + } + + /* +- * Bottom-up (legacy) layout on X86_32 did not support randomization, X86_64 +- * does, but not when emulating X86_32 +- */ +-static unsigned long mmap_legacy_base(unsigned long rnd) +-{ +- if (mmap_is_ia32()) +- return TASK_UNMAPPED_BASE; +- else +- return TASK_UNMAPPED_BASE + rnd; +-} +- +-/* + * This function, called very early during the creation of a new + * process VM image, sets up which VM layout function to use: + */ +@@ -116,7 +104,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm) + if (current->flags & PF_RANDOMIZE) + random_factor = arch_mmap_rnd(); + +- mm->mmap_legacy_base = mmap_legacy_base(random_factor); ++ mm->mmap_legacy_base = TASK_UNMAPPED_BASE + random_factor; + + if (mmap_is_legacy()) { + mm->mmap_base = mm->mmap_legacy_base; +-- +2.7.3 + |