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?= +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 +Suggested-by: Linus Torvalds +Signed-off-by: Bjørn Mork +Signed-off-by: David S. Miller +--- + 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/kernel.spec b/kernel.spec index 56e5d4695..57bfe45ad 100644 --- a/kernel.spec +++ b/kernel.spec @@ -693,6 +693,10 @@ 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 + # END OF PATCH DEFINITIONS %endif @@ -1449,6 +1453,10 @@ 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 + # END OF PATCH APPLICATIONS %endif @@ -2299,6 +2307,7 @@ fi # %changelog * Mon Apr 11 2016 Josh Boyer +- 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 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 +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 +Signed-off-by: David S. Miller +--- + 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 +