From: Greg Kroah-Hartman Date: Mon, 13 Jan 2014 17:58:42 +0000 (-0800) Subject: 3.12-stable patches X-Git-Tag: v3.4.77~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=71e394ae63f1e9de84507f309bce35ccb7107604;p=thirdparty%2Fkernel%2Fstable-queue.git 3.12-stable patches added patches: arc_emac-fix-potential-use-after-free.patch arm-7923-1-mm-fix-dcache-flush-logic-for-compound-high-pages.patch arm-fix-bad-mode-in-...-handler-message-for-undefined-instructions.patch arm-fix-footbridge-clockevent-device.patch bridge-use-spin_lock_bh-in-br_multicast_set_hash_max.patch drivers-net-hamradio-integer-overflow-in-hdlcdrv_ioctl.patch hamradio-yam-fix-info-leak-in-ioctl.patch ip_gre-fix-msg_name-parsing-for-recvfrom-recvmsg.patch ipv4-fix-tunneled-vm-traffic-over-hw-vxlan-gre-gso-nic.patch ipv6-always-set-the-new-created-dst-s-from-in-ip6_rt_copy.patch ipv6-fix-illegal-mac_header-comparison-on-32bit.patch net-fec-fix-potential-use-after-free.patch net-inet_diag-zero-out-uninitialized-idiag_-src-dst-fields.patch net-llc-fix-use-after-free-in-llc_ui_recvmsg.patch net-rose-restore-old-recvmsg-behavior.patch net-unix-allow-bind-to-fail-on-mutex-lock.patch net-unix-allow-set_peek_off-to-fail.patch netpoll-fix-missing-txq-unlock-and-and-oops.patch netvsc-don-t-flush-peers-notifying-work-during-setting-mtu.patch rds-prevent-dereference-of-a-null-device.patch sfc-add-length-checks-to-efx_xmit_with_hwtstamp-and-efx_ptp_is_ptp_tx.patch sfc-maintain-current-frequency-adjustment-when-applying-a-time-offset.patch sfc-poll-for-mcdi-completion-once-before-timeout-occurs.patch sfc-ptp-moderate-log-message-on-event-queue-overflow.patch sfc-rate-limit-log-message-for-ptp-packets-without-a-matching-timestamp-event.patch sfc-refactor-efx_mcdi_poll-by-introducing-efx_mcdi_poll_once.patch sfc-rx-buffer-allocation-takes-prefix-size-into-account-in-ip-header-alignment.patch sfc-stop-re-start-ptp-when-stopping-starting-the-datapath.patch tg3-initialize-reg_base_addr-at-pci-config-offset-120-to-0.patch virtio-net-fix-refill-races-during-restore.patch virtio-net-make-all-rx-paths-handle-errors.patch virtio_net-don-t-leak-memory-or-block-when-too-many-frags.patch virtio_net-fix-error-handling-for-mergeable-buffers.patch vlan-fix-header-ops-passthru-when-doing-tx-vlan-offload.patch vxlan-release-rt-when-found-circular-route.patch --- diff --git a/queue-3.12/arc_emac-fix-potential-use-after-free.patch b/queue-3.12/arc_emac-fix-potential-use-after-free.patch new file mode 100644 index 00000000000..3df3c3d8b1b --- /dev/null +++ b/queue-3.12/arc_emac-fix-potential-use-after-free.patch @@ -0,0 +1,45 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: Eric Dumazet +Date: Thu, 19 Dec 2013 18:10:40 -0800 +Subject: arc_emac: fix potential use after free + +From: Eric Dumazet + +[ Upstream commit 37ec274e9713eafc2ba6c4471420f06cb8f68ecf ] + +Signed-off-by: Eric Dumazet + +skb_tx_timestamp(skb) should be called _before_ TX completion +has a chance to trigger, otherwise it is too late and we access +freed memory. + +Fixes: e4f2379db6c6 ("ethernet/arc/arc_emac - Add new driver") +From: Eric Dumazet +Cc: Alexey Brodkin +Cc: Richard Cochran +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/arc/emac_main.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/arc/emac_main.c ++++ b/drivers/net/ethernet/arc/emac_main.c +@@ -565,6 +565,8 @@ static int arc_emac_tx(struct sk_buff *s + /* Make sure pointer to data buffer is set */ + wmb(); + ++ skb_tx_timestamp(skb); ++ + *info = cpu_to_le32(FOR_EMAC | FIRST_OR_LAST_MASK | len); + + /* Increment index to point to the next BD */ +@@ -579,8 +581,6 @@ static int arc_emac_tx(struct sk_buff *s + + arc_reg_set(priv, R_STATUS, TXPL_MASK); + +- skb_tx_timestamp(skb); +- + return NETDEV_TX_OK; + } + diff --git a/queue-3.12/arm-7923-1-mm-fix-dcache-flush-logic-for-compound-high-pages.patch b/queue-3.12/arm-7923-1-mm-fix-dcache-flush-logic-for-compound-high-pages.patch new file mode 100644 index 00000000000..57d63578507 --- /dev/null +++ b/queue-3.12/arm-7923-1-mm-fix-dcache-flush-logic-for-compound-high-pages.patch @@ -0,0 +1,50 @@ +From 2a7cfcbc0553365d75716f69ee7b704cac7c9248 Mon Sep 17 00:00:00 2001 +From: Steven Capper +Date: Mon, 16 Dec 2013 17:25:52 +0100 +Subject: ARM: 7923/1: mm: fix dcache flush logic for compound high pages + +From: Steven Capper + +commit 2a7cfcbc0553365d75716f69ee7b704cac7c9248 upstream. + +When given a compound high page, __flush_dcache_page will only flush +the first page of the compound page repeatedly rather than the entire +set of constituent pages. + +This error was introduced by: + 0b19f93 ARM: mm: Add support for flushing HugeTLB pages. + +This patch corrects the logic such that all constituent pages are now +flushed. + +Signed-off-by: Steve Capper +Acked-by: Will Deacon +Signed-off-by: Russell King +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/mm/flush.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/arch/arm/mm/flush.c ++++ b/arch/arm/mm/flush.c +@@ -175,16 +175,16 @@ void __flush_dcache_page(struct address_ + unsigned long i; + if (cache_is_vipt_nonaliasing()) { + for (i = 0; i < (1 << compound_order(page)); i++) { +- void *addr = kmap_atomic(page); ++ void *addr = kmap_atomic(page + i); + __cpuc_flush_dcache_area(addr, PAGE_SIZE); + kunmap_atomic(addr); + } + } else { + for (i = 0; i < (1 << compound_order(page)); i++) { +- void *addr = kmap_high_get(page); ++ void *addr = kmap_high_get(page + i); + if (addr) { + __cpuc_flush_dcache_area(addr, PAGE_SIZE); +- kunmap_high(page); ++ kunmap_high(page + i); + } + } + } diff --git a/queue-3.12/arm-fix-bad-mode-in-...-handler-message-for-undefined-instructions.patch b/queue-3.12/arm-fix-bad-mode-in-...-handler-message-for-undefined-instructions.patch new file mode 100644 index 00000000000..16c1a8f1657 --- /dev/null +++ b/queue-3.12/arm-fix-bad-mode-in-...-handler-message-for-undefined-instructions.patch @@ -0,0 +1,36 @@ +From 29c350bf28da333e41e30497b649fe335712a2ab Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Fri, 3 Jan 2014 15:01:39 +0000 +Subject: ARM: fix "bad mode in ... handler" message for undefined instructions + +From: Russell King + +commit 29c350bf28da333e41e30497b649fe335712a2ab upstream. + +The array was missing the final entry for the undefined instruction +exception handler; this commit adds it. + +Signed-off-by: Russell King +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/kernel/traps.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/arch/arm/kernel/traps.c ++++ b/arch/arm/kernel/traps.c +@@ -35,7 +35,13 @@ + #include + #include + +-static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" }; ++static const char *handler[]= { ++ "prefetch abort", ++ "data abort", ++ "address exception", ++ "interrupt", ++ "undefined instruction", ++}; + + void *vectors_page; + diff --git a/queue-3.12/arm-fix-footbridge-clockevent-device.patch b/queue-3.12/arm-fix-footbridge-clockevent-device.patch new file mode 100644 index 00000000000..51dca5c8f49 --- /dev/null +++ b/queue-3.12/arm-fix-footbridge-clockevent-device.patch @@ -0,0 +1,39 @@ +From 4ff859fe1dc0da0f87bbdfff78f527898878fa4a Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Sun, 29 Dec 2013 12:39:50 +0000 +Subject: ARM: fix footbridge clockevent device + +From: Russell King + +commit 4ff859fe1dc0da0f87bbdfff78f527898878fa4a upstream. + +The clockevents code was being told that the footbridge clock event +device ticks at 16x the rate which it actually does. This leads to +timekeeping problems since it allows the clocksource to wrap before +the kernel notices. Fix this by using the correct clock. + +Fixes: 4e8d76373c9fd ("ARM: footbridge: convert to clockevents/clocksource") +Signed-off-by: Russell King +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/mach-footbridge/dc21285-timer.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/arch/arm/mach-footbridge/dc21285-timer.c ++++ b/arch/arm/mach-footbridge/dc21285-timer.c +@@ -96,11 +96,12 @@ static struct irqaction footbridge_timer + void __init footbridge_timer_init(void) + { + struct clock_event_device *ce = &ckevt_dc21285; ++ unsigned rate = DIV_ROUND_CLOSEST(mem_fclk_21285, 16); + +- clocksource_register_hz(&cksrc_dc21285, (mem_fclk_21285 + 8) / 16); ++ clocksource_register_hz(&cksrc_dc21285, rate); + + setup_irq(ce->irq, &footbridge_timer_irq); + + ce->cpumask = cpumask_of(smp_processor_id()); +- clockevents_config_and_register(ce, mem_fclk_21285, 0x4, 0xffffff); ++ clockevents_config_and_register(ce, rate, 0x4, 0xffffff); + } diff --git a/queue-3.12/bridge-use-spin_lock_bh-in-br_multicast_set_hash_max.patch b/queue-3.12/bridge-use-spin_lock_bh-in-br_multicast_set_hash_max.patch new file mode 100644 index 00000000000..93c7f9e442a --- /dev/null +++ b/queue-3.12/bridge-use-spin_lock_bh-in-br_multicast_set_hash_max.patch @@ -0,0 +1,63 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: Curt Brune +Date: Mon, 6 Jan 2014 11:00:32 -0800 +Subject: bridge: use spin_lock_bh() in br_multicast_set_hash_max + +From: Curt Brune + +[ Upstream commit fe0d692bbc645786bce1a98439e548ae619269f5 ] + +br_multicast_set_hash_max() is called from process context in +net/bridge/br_sysfs_br.c by the sysfs store_hash_max() function. + +br_multicast_set_hash_max() calls spin_lock(&br->multicast_lock), +which can deadlock the CPU if a softirq that also tries to take the +same lock interrupts br_multicast_set_hash_max() while the lock is +held . This can happen quite easily when any of the bridge multicast +timers expire, which try to take the same lock. + +The fix here is to use spin_lock_bh(), preventing other softirqs from +executing on this CPU. + +Steps to reproduce: + +1. Create a bridge with several interfaces (I used 4). +2. Set the "multicast query interval" to a low number, like 2. +3. Enable the bridge as a multicast querier. +4. Repeatedly set the bridge hash_max parameter via sysfs. + + # brctl addbr br0 + # brctl addif br0 eth1 eth2 eth3 eth4 + # brctl setmcqi br0 2 + # brctl setmcquerier br0 1 + + # while true ; do echo 4096 > /sys/class/net/br0/bridge/hash_max; done + +Signed-off-by: Curt Brune +Signed-off-by: Scott Feldman +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/bridge/br_multicast.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/net/bridge/br_multicast.c ++++ b/net/bridge/br_multicast.c +@@ -2004,7 +2004,7 @@ int br_multicast_set_hash_max(struct net + u32 old; + struct net_bridge_mdb_htable *mdb; + +- spin_lock(&br->multicast_lock); ++ spin_lock_bh(&br->multicast_lock); + if (!netif_running(br->dev)) + goto unlock; + +@@ -2036,7 +2036,7 @@ rollback: + } + + unlock: +- spin_unlock(&br->multicast_lock); ++ spin_unlock_bh(&br->multicast_lock); + + return err; + } diff --git a/queue-3.12/drivers-net-hamradio-integer-overflow-in-hdlcdrv_ioctl.patch b/queue-3.12/drivers-net-hamradio-integer-overflow-in-hdlcdrv_ioctl.patch new file mode 100644 index 00000000000..6756dfc1907 --- /dev/null +++ b/queue-3.12/drivers-net-hamradio-integer-overflow-in-hdlcdrv_ioctl.patch @@ -0,0 +1,32 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: Wenliang Fan +Date: Tue, 17 Dec 2013 11:25:28 +0800 +Subject: drivers/net/hamradio: Integer overflow in hdlcdrv_ioctl() + +From: Wenliang Fan + +[ Upstream commit e9db5c21d3646a6454fcd04938dd215ac3ab620a ] + +The local variable 'bi' comes from userspace. If userspace passed a +large number to 'bi.data.calibrate', there would be an integer overflow +in the following line: + s->hdlctx.calibrate = bi.data.calibrate * s->par.bitrate / 16; + +Signed-off-by: Wenliang Fan +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/hamradio/hdlcdrv.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/net/hamradio/hdlcdrv.c ++++ b/drivers/net/hamradio/hdlcdrv.c +@@ -571,6 +571,8 @@ static int hdlcdrv_ioctl(struct net_devi + case HDLCDRVCTL_CALIBRATE: + if(!capable(CAP_SYS_RAWIO)) + return -EPERM; ++ if (bi.data.calibrate > INT_MAX / s->par.bitrate) ++ return -EINVAL; + s->hdlctx.calibrate = bi.data.calibrate * s->par.bitrate / 16; + return 0; + diff --git a/queue-3.12/hamradio-yam-fix-info-leak-in-ioctl.patch b/queue-3.12/hamradio-yam-fix-info-leak-in-ioctl.patch new file mode 100644 index 00000000000..7a8eb828290 --- /dev/null +++ b/queue-3.12/hamradio-yam-fix-info-leak-in-ioctl.patch @@ -0,0 +1,33 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: =?UTF-8?q?Salva=20Peir=C3=B3?= +Date: Tue, 17 Dec 2013 10:06:30 +0100 +Subject: hamradio/yam: fix info leak in ioctl +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Salva Peiró + +[ Upstream commit 8e3fbf870481eb53b2d3a322d1fc395ad8b367ed ] + +The yam_ioctl() code fails to initialise the cmd field +of the struct yamdrv_ioctl_cfg. Add an explicit memset(0) +before filling the structure to avoid the 4-byte info leak. + +Signed-off-by: Salva Peiró +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/hamradio/yam.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/hamradio/yam.c ++++ b/drivers/net/hamradio/yam.c +@@ -1057,6 +1057,7 @@ static int yam_ioctl(struct net_device * + break; + + case SIOCYAMGCFG: ++ memset(&yi, 0, sizeof(yi)); + yi.cfg.mask = 0xffffffff; + yi.cfg.iobase = yp->iobase; + yi.cfg.irq = yp->irq; diff --git a/queue-3.12/ip_gre-fix-msg_name-parsing-for-recvfrom-recvmsg.patch b/queue-3.12/ip_gre-fix-msg_name-parsing-for-recvfrom-recvmsg.patch new file mode 100644 index 00000000000..e4547a5bdb9 --- /dev/null +++ b/queue-3.12/ip_gre-fix-msg_name-parsing-for-recvfrom-recvmsg.patch @@ -0,0 +1,53 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: =?UTF-8?q?Timo=20Ter=C3=A4s?= +Date: Mon, 16 Dec 2013 11:02:09 +0200 +Subject: ip_gre: fix msg_name parsing for recvfrom/recvmsg +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Timo Teräs + +[ Upstream commit 0e3da5bb8da45890b1dc413404e0f978ab71173e ] + +ipgre_header_parse() needs to parse the tunnel's ip header and it +uses mac_header to locate the iphdr. This got broken when gre tunneling +was refactored as mac_header is no longer updated to point to iphdr. +Introduce skb_pop_mac_header() helper to do the mac_header assignment +and use it in ipgre_rcv() to fix msg_name parsing. + +Bug introduced in commit c54419321455 (GRE: Refactor GRE tunneling code.) + +Cc: Pravin B Shelar +Signed-off-by: Timo Teräs +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/skbuff.h | 5 +++++ + net/ipv4/ip_gre.c | 1 + + 2 files changed, 6 insertions(+) + +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -1638,6 +1638,11 @@ static inline void skb_set_mac_header(st + skb->mac_header += offset; + } + ++static inline void skb_pop_mac_header(struct sk_buff *skb) ++{ ++ skb->mac_header = skb->network_header; ++} ++ + static inline void skb_probe_transport_header(struct sk_buff *skb, + const int offset_hint) + { +--- a/net/ipv4/ip_gre.c ++++ b/net/ipv4/ip_gre.c +@@ -217,6 +217,7 @@ static int ipgre_rcv(struct sk_buff *skb + iph->saddr, iph->daddr, tpi->key); + + if (tunnel) { ++ skb_pop_mac_header(skb); + ip_tunnel_rcv(tunnel, skb, tpi, log_ecn_error); + return PACKET_RCVD; + } diff --git a/queue-3.12/ipv4-fix-tunneled-vm-traffic-over-hw-vxlan-gre-gso-nic.patch b/queue-3.12/ipv4-fix-tunneled-vm-traffic-over-hw-vxlan-gre-gso-nic.patch new file mode 100644 index 00000000000..0f9708151f2 --- /dev/null +++ b/queue-3.12/ipv4-fix-tunneled-vm-traffic-over-hw-vxlan-gre-gso-nic.patch @@ -0,0 +1,177 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: Wei-Chun Chao +Date: Thu, 26 Dec 2013 13:10:22 -0800 +Subject: ipv4: fix tunneled VM traffic over hw VXLAN/GRE GSO NIC + +From: Wei-Chun Chao + +[ Upstream commit 7a7ffbabf99445704be01bff5d7e360da908cf8e ] + +VM to VM GSO traffic is broken if it goes through VXLAN or GRE +tunnel and the physical NIC on the host supports hardware VXLAN/GRE +GSO offload (e.g. bnx2x and next-gen mlx4). + +Two issues - +(VXLAN) VM traffic has SKB_GSO_DODGY and SKB_GSO_UDP_TUNNEL with +SKB_GSO_TCP/UDP set depending on the inner protocol. GSO header +integrity check fails in udp4_ufo_fragment if inner protocol is +TCP. Also gso_segs is calculated incorrectly using skb->len that +includes tunnel header. Fix: robust check should only be applied +to the inner packet. + +(VXLAN & GRE) Once GSO header integrity check passes, NULL segs +is returned and the original skb is sent to hardware. However the +tunnel header is already pulled. Fix: tunnel header needs to be +restored so that hardware can perform GSO properly on the original +packet. + +Signed-off-by: Wei-Chun Chao +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/netdevice.h | 13 +++++++++++++ + net/ipv4/gre_offload.c | 11 +++++++---- + net/ipv4/udp.c | 6 +++++- + net/ipv4/udp_offload.c | 37 +++++++++++++++++++------------------ + 4 files changed, 44 insertions(+), 23 deletions(-) + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -2954,6 +2954,19 @@ static inline void netif_set_gso_max_siz + dev->gso_max_size = size; + } + ++static inline void skb_gso_error_unwind(struct sk_buff *skb, __be16 protocol, ++ int pulled_hlen, u16 mac_offset, ++ int mac_len) ++{ ++ skb->protocol = protocol; ++ skb->encapsulation = 1; ++ skb_push(skb, pulled_hlen); ++ skb_reset_transport_header(skb); ++ skb->mac_header = mac_offset; ++ skb->network_header = skb->mac_header + mac_len; ++ skb->mac_len = mac_len; ++} ++ + static inline bool netif_is_bond_master(struct net_device *dev) + { + return dev->flags & IFF_MASTER && dev->priv_flags & IFF_BONDING; +--- a/net/ipv4/gre_offload.c ++++ b/net/ipv4/gre_offload.c +@@ -28,6 +28,7 @@ static struct sk_buff *gre_gso_segment(s + netdev_features_t enc_features; + int ghl = GRE_HEADER_SECTION; + struct gre_base_hdr *greh; ++ u16 mac_offset = skb->mac_header; + int mac_len = skb->mac_len; + __be16 protocol = skb->protocol; + int tnl_hlen; +@@ -57,13 +58,13 @@ static struct sk_buff *gre_gso_segment(s + } else + csum = false; + ++ if (unlikely(!pskb_may_pull(skb, ghl))) ++ goto out; ++ + /* setup inner skb. */ + skb->protocol = greh->protocol; + skb->encapsulation = 0; + +- if (unlikely(!pskb_may_pull(skb, ghl))) +- goto out; +- + __skb_pull(skb, ghl); + skb_reset_mac_header(skb); + skb_set_network_header(skb, skb_inner_network_offset(skb)); +@@ -72,8 +73,10 @@ static struct sk_buff *gre_gso_segment(s + /* segment inner packet. */ + enc_features = skb->dev->hw_enc_features & netif_skb_features(skb); + segs = skb_mac_gso_segment(skb, enc_features); +- if (!segs || IS_ERR(segs)) ++ if (!segs || IS_ERR(segs)) { ++ skb_gso_error_unwind(skb, protocol, ghl, mac_offset, mac_len); + goto out; ++ } + + skb = segs; + tnl_hlen = skb_tnl_header_len(skb); +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -2294,6 +2294,7 @@ struct sk_buff *skb_udp_tunnel_segment(s + netdev_features_t features) + { + struct sk_buff *segs = ERR_PTR(-EINVAL); ++ u16 mac_offset = skb->mac_header; + int mac_len = skb->mac_len; + int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb); + __be16 protocol = skb->protocol; +@@ -2313,8 +2314,11 @@ struct sk_buff *skb_udp_tunnel_segment(s + /* segment inner packet. */ + enc_features = skb->dev->hw_enc_features & netif_skb_features(skb); + segs = skb_mac_gso_segment(skb, enc_features); +- if (!segs || IS_ERR(segs)) ++ if (!segs || IS_ERR(segs)) { ++ skb_gso_error_unwind(skb, protocol, tnl_hlen, mac_offset, ++ mac_len); + goto out; ++ } + + outer_hlen = skb_tnl_header_len(skb); + skb = segs; +--- a/net/ipv4/udp_offload.c ++++ b/net/ipv4/udp_offload.c +@@ -41,6 +41,14 @@ static struct sk_buff *udp4_ufo_fragment + { + struct sk_buff *segs = ERR_PTR(-EINVAL); + unsigned int mss; ++ int offset; ++ __wsum csum; ++ ++ if (skb->encapsulation && ++ skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL) { ++ segs = skb_udp_tunnel_segment(skb, features); ++ goto out; ++ } + + mss = skb_shinfo(skb)->gso_size; + if (unlikely(skb->len <= mss)) +@@ -62,27 +70,20 @@ static struct sk_buff *udp4_ufo_fragment + goto out; + } + ++ /* Do software UFO. Complete and fill in the UDP checksum as ++ * HW cannot do checksum of UDP packets sent as multiple ++ * IP fragments. ++ */ ++ offset = skb_checksum_start_offset(skb); ++ csum = skb_checksum(skb, offset, skb->len - offset, 0); ++ offset += skb->csum_offset; ++ *(__sum16 *)(skb->data + offset) = csum_fold(csum); ++ skb->ip_summed = CHECKSUM_NONE; ++ + /* Fragment the skb. IP headers of the fragments are updated in + * inet_gso_segment() + */ +- if (skb->encapsulation && skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL) +- segs = skb_udp_tunnel_segment(skb, features); +- else { +- int offset; +- __wsum csum; +- +- /* Do software UFO. Complete and fill in the UDP checksum as +- * HW cannot do checksum of UDP packets sent as multiple +- * IP fragments. +- */ +- offset = skb_checksum_start_offset(skb); +- csum = skb_checksum(skb, offset, skb->len - offset, 0); +- offset += skb->csum_offset; +- *(__sum16 *)(skb->data + offset) = csum_fold(csum); +- skb->ip_summed = CHECKSUM_NONE; +- +- segs = skb_segment(skb, features); +- } ++ segs = skb_segment(skb, features); + out: + return segs; + } diff --git a/queue-3.12/ipv6-always-set-the-new-created-dst-s-from-in-ip6_rt_copy.patch b/queue-3.12/ipv6-always-set-the-new-created-dst-s-from-in-ip6_rt_copy.patch new file mode 100644 index 00000000000..227a2b1e0d5 --- /dev/null +++ b/queue-3.12/ipv6-always-set-the-new-created-dst-s-from-in-ip6_rt_copy.patch @@ -0,0 +1,40 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: Li RongQing +Date: Thu, 19 Dec 2013 12:40:26 +0800 +Subject: ipv6: always set the new created dst's from in ip6_rt_copy + +From: Li RongQing + +[ Upstream commit 24f5b855e17df7e355eacd6c4a12cc4d6a6c9ff0 ] + +ip6_rt_copy only sets dst.from if ort has flag RTF_ADDRCONF and RTF_DEFAULT. +but the prefix routes which did get installed by hand locally can have an +expiration, and no any flag combination which can ensure a potential from +does never expire, so we should always set the new created dst's from. + +This also fixes the new created dst is always expired since the ort, which +is created by RA, maybe has RTF_EXPIRES and RTF_ADDRCONF, but no RTF_DEFAULT. + +Suggested-by: Hannes Frederic Sowa +CC: Gao feng +Signed-off-by: Li RongQing +Acked-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/route.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -1910,9 +1910,7 @@ static struct rt6_info *ip6_rt_copy(stru + else + rt->rt6i_gateway = *dest; + rt->rt6i_flags = ort->rt6i_flags; +- if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) == +- (RTF_DEFAULT | RTF_ADDRCONF)) +- rt6_set_from(rt, ort); ++ rt6_set_from(rt, ort); + rt->rt6i_metric = 0; + + #ifdef CONFIG_IPV6_SUBTREES diff --git a/queue-3.12/ipv6-fix-illegal-mac_header-comparison-on-32bit.patch b/queue-3.12/ipv6-fix-illegal-mac_header-comparison-on-32bit.patch new file mode 100644 index 00000000000..da8fae6216f --- /dev/null +++ b/queue-3.12/ipv6-fix-illegal-mac_header-comparison-on-32bit.patch @@ -0,0 +1,25 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: Hannes Frederic Sowa +Date: Fri, 13 Dec 2013 15:12:27 +0100 +Subject: ipv6: fix illegal mac_header comparison on 32bit + +From: Hannes Frederic Sowa + +Signed-off-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/udp_offload.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/ipv6/udp_offload.c ++++ b/net/ipv6/udp_offload.c +@@ -88,7 +88,7 @@ static struct sk_buff *udp6_ufo_fragment + + /* Check if there is enough headroom to insert fragment header. */ + tnl_hlen = skb_tnl_header_len(skb); +- if (skb->mac_header < (tnl_hlen + frag_hdr_sz)) { ++ if (skb_mac_header(skb) < skb->head + tnl_hlen + frag_hdr_sz) { + if (gso_pskb_expand_head(skb, tnl_hlen + frag_hdr_sz)) + goto out; + } diff --git a/queue-3.12/net-fec-fix-potential-use-after-free.patch b/queue-3.12/net-fec-fix-potential-use-after-free.patch new file mode 100644 index 00000000000..15e0bc1ea3c --- /dev/null +++ b/queue-3.12/net-fec-fix-potential-use-after-free.patch @@ -0,0 +1,45 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: Eric Dumazet +Date: Thu, 19 Dec 2013 10:53:02 -0800 +Subject: net: fec: fix potential use after free + +From: Eric Dumazet + +[ Upstream commit 7a2a84518cfb263d2c4171b3d63671f88316adb2 ] + +skb_tx_timestamp(skb) should be called _before_ TX completion +has a chance to trigger, otherwise it is too late and we access +freed memory. + +Signed-off-by: Eric Dumazet +Fixes: de5fb0a05348 ("net: fec: put tx to napi poll function to fix dead lock") +Cc: Frank Li +Cc: Richard Cochran +Acked-by: Richard Cochran +Acked-by: Frank Li +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/freescale/fec_main.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -425,6 +425,8 @@ fec_enet_start_xmit(struct sk_buff *skb, + /* If this was the last BD in the ring, start at the beginning again. */ + bdp = fec_enet_get_nextdesc(bdp, fep); + ++ skb_tx_timestamp(skb); ++ + fep->cur_tx = bdp; + + if (fep->cur_tx == fep->dirty_tx) +@@ -433,8 +435,6 @@ fec_enet_start_xmit(struct sk_buff *skb, + /* Trigger transmission start */ + writel(0, fep->hwp + FEC_X_DES_ACTIVE); + +- skb_tx_timestamp(skb); +- + return NETDEV_TX_OK; + } + diff --git a/queue-3.12/net-inet_diag-zero-out-uninitialized-idiag_-src-dst-fields.patch b/queue-3.12/net-inet_diag-zero-out-uninitialized-idiag_-src-dst-fields.patch new file mode 100644 index 00000000000..b770ef817fb --- /dev/null +++ b/queue-3.12/net-inet_diag-zero-out-uninitialized-idiag_-src-dst-fields.patch @@ -0,0 +1,88 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: Daniel Borkmann +Date: Tue, 17 Dec 2013 00:38:39 +0100 +Subject: net: inet_diag: zero out uninitialized idiag_{src,dst} fields + +From: Daniel Borkmann + +[ Upstream commit b1aac815c0891fe4a55a6b0b715910142227700f ] + +Jakub reported while working with nlmon netlink sniffer that parts of +the inet_diag_sockid are not initialized when r->idiag_family != AF_INET6. +That is, fields of r->id.idiag_src[1 ... 3], r->id.idiag_dst[1 ... 3]. + +In fact, it seems that we can leak 6 * sizeof(u32) byte of kernel [slab] +memory through this. At least, in udp_dump_one(), we allocate a skb in ... + + rep = nlmsg_new(sizeof(struct inet_diag_msg) + ..., GFP_KERNEL); + +... and then pass that to inet_sk_diag_fill() that puts the whole struct +inet_diag_msg into the skb, where we only fill out r->id.idiag_src[0], +r->id.idiag_dst[0] and leave the rest untouched: + + r->id.idiag_src[0] = inet->inet_rcv_saddr; + r->id.idiag_dst[0] = inet->inet_daddr; + +struct inet_diag_msg embeds struct inet_diag_sockid that is correctly / +fully filled out in IPv6 case, but for IPv4 not. + +So just zero them out by using plain memset (for this little amount of +bytes it's probably not worth the extra check for idiag_family == AF_INET). + +Similarly, fix also other places where we fill that out. + +Reported-by: Jakub Zawadzki +Signed-off-by: Daniel Borkmann +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/inet_diag.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/net/ipv4/inet_diag.c ++++ b/net/ipv4/inet_diag.c +@@ -106,6 +106,10 @@ int inet_sk_diag_fill(struct sock *sk, s + + r->id.idiag_sport = inet->inet_sport; + r->id.idiag_dport = inet->inet_dport; ++ ++ memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src)); ++ memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst)); ++ + r->id.idiag_src[0] = inet->inet_rcv_saddr; + r->id.idiag_dst[0] = inet->inet_daddr; + +@@ -240,12 +244,19 @@ static int inet_twsk_diag_fill(struct in + + r->idiag_family = tw->tw_family; + r->idiag_retrans = 0; ++ + r->id.idiag_if = tw->tw_bound_dev_if; + sock_diag_save_cookie(tw, r->id.idiag_cookie); ++ + r->id.idiag_sport = tw->tw_sport; + r->id.idiag_dport = tw->tw_dport; ++ ++ memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src)); ++ memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst)); ++ + r->id.idiag_src[0] = tw->tw_rcv_saddr; + r->id.idiag_dst[0] = tw->tw_daddr; ++ + r->idiag_state = tw->tw_substate; + r->idiag_timer = 3; + r->idiag_expires = DIV_ROUND_UP(tmo * 1000, HZ); +@@ -732,8 +743,13 @@ static int inet_diag_fill_req(struct sk_ + + r->id.idiag_sport = inet->inet_sport; + r->id.idiag_dport = ireq->rmt_port; ++ ++ memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src)); ++ memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst)); ++ + r->id.idiag_src[0] = ireq->loc_addr; + r->id.idiag_dst[0] = ireq->rmt_addr; ++ + r->idiag_expires = jiffies_to_msecs(tmo); + r->idiag_rqueue = 0; + r->idiag_wqueue = 0; diff --git a/queue-3.12/net-llc-fix-use-after-free-in-llc_ui_recvmsg.patch b/queue-3.12/net-llc-fix-use-after-free-in-llc_ui_recvmsg.patch new file mode 100644 index 00000000000..eb97845baeb --- /dev/null +++ b/queue-3.12/net-llc-fix-use-after-free-in-llc_ui_recvmsg.patch @@ -0,0 +1,65 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: Daniel Borkmann +Date: Mon, 30 Dec 2013 23:40:50 +0100 +Subject: net: llc: fix use after free in llc_ui_recvmsg + +From: Daniel Borkmann + +[ Upstream commit 4d231b76eef6c4a6bd9c96769e191517765942cb ] + +While commit 30a584d944fb fixes datagram interface in LLC, a use +after free bug has been introduced for SOCK_STREAM sockets that do +not make use of MSG_PEEK. + +The flow is as follow ... + + if (!(flags & MSG_PEEK)) { + ... + sk_eat_skb(sk, skb, false); + ... + } + ... + if (used + offset < skb->len) + continue; + +... where sk_eat_skb() calls __kfree_skb(). Therefore, cache +original length and work on skb_len to check partial reads. + +Fixes: 30a584d944fb ("[LLX]: SOCK_DGRAM interface fixes") +Signed-off-by: Daniel Borkmann +Cc: Stephen Hemminger +Cc: Arnaldo Carvalho de Melo +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/llc/af_llc.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/net/llc/af_llc.c ++++ b/net/llc/af_llc.c +@@ -715,7 +715,7 @@ static int llc_ui_recvmsg(struct kiocb * + unsigned long cpu_flags; + size_t copied = 0; + u32 peek_seq = 0; +- u32 *seq; ++ u32 *seq, skb_len; + unsigned long used; + int target; /* Read at least this many bytes */ + long timeo; +@@ -812,6 +812,7 @@ static int llc_ui_recvmsg(struct kiocb * + } + continue; + found_ok_skb: ++ skb_len = skb->len; + /* Ok so how much can we use? */ + used = skb->len - offset; + if (len < used) +@@ -844,7 +845,7 @@ static int llc_ui_recvmsg(struct kiocb * + } + + /* Partial read */ +- if (used + offset < skb->len) ++ if (used + offset < skb_len) + continue; + } while (len > 0); + diff --git a/queue-3.12/net-rose-restore-old-recvmsg-behavior.patch b/queue-3.12/net-rose-restore-old-recvmsg-behavior.patch new file mode 100644 index 00000000000..7b3f186020f --- /dev/null +++ b/queue-3.12/net-rose-restore-old-recvmsg-behavior.patch @@ -0,0 +1,61 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: Florian Westphal +Date: Mon, 23 Dec 2013 00:32:31 +0100 +Subject: net: rose: restore old recvmsg behavior + +From: Florian Westphal + +[ Upstream commit f81152e35001e91997ec74a7b4e040e6ab0acccf ] + +recvmsg handler in net/rose/af_rose.c performs size-check ->msg_namelen. + +After commit f3d3342602f8bcbf37d7c46641cb9bca7618eb1c +(net: rework recvmsg handler msg_name and msg_namelen logic), we now +always take the else branch due to namelen being initialized to 0. + +Digging in netdev-vger-cvs git repo shows that msg_namelen was +initialized with a fixed-size since at least 1995, so the else branch +was never taken. + +Compile tested only. + +Signed-off-by: Florian Westphal +Acked-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/rose/af_rose.c | 16 ++++------------ + 1 file changed, 4 insertions(+), 12 deletions(-) + +--- a/net/rose/af_rose.c ++++ b/net/rose/af_rose.c +@@ -1253,6 +1253,7 @@ static int rose_recvmsg(struct kiocb *io + + if (msg->msg_name) { + struct sockaddr_rose *srose; ++ struct full_sockaddr_rose *full_srose = msg->msg_name; + + memset(msg->msg_name, 0, sizeof(struct full_sockaddr_rose)); + srose = msg->msg_name; +@@ -1260,18 +1261,9 @@ static int rose_recvmsg(struct kiocb *io + srose->srose_addr = rose->dest_addr; + srose->srose_call = rose->dest_call; + srose->srose_ndigis = rose->dest_ndigis; +- if (msg->msg_namelen >= sizeof(struct full_sockaddr_rose)) { +- struct full_sockaddr_rose *full_srose = (struct full_sockaddr_rose *)msg->msg_name; +- for (n = 0 ; n < rose->dest_ndigis ; n++) +- full_srose->srose_digis[n] = rose->dest_digis[n]; +- msg->msg_namelen = sizeof(struct full_sockaddr_rose); +- } else { +- if (rose->dest_ndigis >= 1) { +- srose->srose_ndigis = 1; +- srose->srose_digi = rose->dest_digis[0]; +- } +- msg->msg_namelen = sizeof(struct sockaddr_rose); +- } ++ for (n = 0 ; n < rose->dest_ndigis ; n++) ++ full_srose->srose_digis[n] = rose->dest_digis[n]; ++ msg->msg_namelen = sizeof(struct full_sockaddr_rose); + } + + skb_free_datagram(sk, skb); diff --git a/queue-3.12/net-unix-allow-bind-to-fail-on-mutex-lock.patch b/queue-3.12/net-unix-allow-bind-to-fail-on-mutex-lock.patch new file mode 100644 index 00000000000..220f219552d --- /dev/null +++ b/queue-3.12/net-unix-allow-bind-to-fail-on-mutex-lock.patch @@ -0,0 +1,47 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: Sasha Levin +Date: Fri, 13 Dec 2013 10:54:22 -0500 +Subject: net: unix: allow bind to fail on mutex lock + +From: Sasha Levin + +[ Upstream commit 37ab4fa7844a044dc21fde45e2a0fc2f3c3b6490 ] + +This is similar to the set_peek_off patch where calling bind while the +socket is stuck in unix_dgram_recvmsg() will block and cause a hung task +spew after a while. + +This is also the last place that did a straightforward mutex_lock(), so +there shouldn't be any more of these patches. + +Signed-off-by: Sasha Levin +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/unix/af_unix.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -718,7 +718,9 @@ static int unix_autobind(struct socket * + int err; + unsigned int retries = 0; + +- mutex_lock(&u->readlock); ++ err = mutex_lock_interruptible(&u->readlock); ++ if (err) ++ return err; + + err = 0; + if (u->addr) +@@ -877,7 +879,9 @@ static int unix_bind(struct socket *sock + goto out; + addr_len = err; + +- mutex_lock(&u->readlock); ++ err = mutex_lock_interruptible(&u->readlock); ++ if (err) ++ goto out; + + err = -EINVAL; + if (u->addr) diff --git a/queue-3.12/net-unix-allow-set_peek_off-to-fail.patch b/queue-3.12/net-unix-allow-set_peek_off-to-fail.patch new file mode 100644 index 00000000000..8e8a72cbecf --- /dev/null +++ b/queue-3.12/net-unix-allow-set_peek_off-to-fail.patch @@ -0,0 +1,72 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: Sasha Levin +Date: Sat, 7 Dec 2013 17:26:27 -0500 +Subject: net: unix: allow set_peek_off to fail + +From: Sasha Levin + +[ Upstream commit 12663bfc97c8b3fdb292428105dd92d563164050 ] + +unix_dgram_recvmsg() will hold the readlock of the socket until recv +is complete. + +In the same time, we may try to setsockopt(SO_PEEK_OFF) which will hang until +unix_dgram_recvmsg() will complete (which can take a while) without allowing +us to break out of it, triggering a hung task spew. + +Instead, allow set_peek_off to fail, this way userspace will not hang. + +Signed-off-by: Sasha Levin +Acked-by: Pavel Emelyanov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/net.h | 2 +- + net/core/sock.c | 2 +- + net/unix/af_unix.c | 8 ++++++-- + 3 files changed, 8 insertions(+), 4 deletions(-) + +--- a/include/linux/net.h ++++ b/include/linux/net.h +@@ -180,7 +180,7 @@ struct proto_ops { + int offset, size_t size, int flags); + ssize_t (*splice_read)(struct socket *sock, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, unsigned int flags); +- void (*set_peek_off)(struct sock *sk, int val); ++ int (*set_peek_off)(struct sock *sk, int val); + }; + + #define DECLARE_SOCKADDR(type, dst, src) \ +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -888,7 +888,7 @@ set_rcvbuf: + + case SO_PEEK_OFF: + if (sock->ops->set_peek_off) +- sock->ops->set_peek_off(sk, val); ++ ret = sock->ops->set_peek_off(sk, val); + else + ret = -EOPNOTSUPP; + break; +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -530,13 +530,17 @@ static int unix_seqpacket_sendmsg(struct + static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *, + struct msghdr *, size_t, int); + +-static void unix_set_peek_off(struct sock *sk, int val) ++static int unix_set_peek_off(struct sock *sk, int val) + { + struct unix_sock *u = unix_sk(sk); + +- mutex_lock(&u->readlock); ++ if (mutex_lock_interruptible(&u->readlock)) ++ return -EINTR; ++ + sk->sk_peek_off = val; + mutex_unlock(&u->readlock); ++ ++ return 0; + } + + diff --git a/queue-3.12/netpoll-fix-missing-txq-unlock-and-and-oops.patch b/queue-3.12/netpoll-fix-missing-txq-unlock-and-and-oops.patch new file mode 100644 index 00000000000..13fd9d03692 --- /dev/null +++ b/queue-3.12/netpoll-fix-missing-txq-unlock-and-and-oops.patch @@ -0,0 +1,49 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: "David S. Miller" +Date: Thu, 2 Jan 2014 19:50:52 -0500 +Subject: netpoll: Fix missing TXQ unlock and and OOPS. + +From: "David S. Miller" + +[ Upstream commit aca5f58f9ba803ec8c2e6bcf890db17589e8dfcc ] + +The VLAN tag handling code in netpoll_send_skb_on_dev() has two problems. + +1) It exits without unlocking the TXQ. + +2) It then tries to queue a NULL skb to npinfo->txq. + +Reported-by: Ahmed Tamrawi +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/core/netpoll.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/net/core/netpoll.c ++++ b/net/core/netpoll.c +@@ -386,8 +386,14 @@ void netpoll_send_skb_on_dev(struct netp + !vlan_hw_offload_capable(netif_skb_features(skb), + skb->vlan_proto)) { + skb = __vlan_put_tag(skb, skb->vlan_proto, vlan_tx_tag_get(skb)); +- if (unlikely(!skb)) +- break; ++ if (unlikely(!skb)) { ++ /* This is actually a packet drop, but we ++ * don't want the code at the end of this ++ * function to try and re-queue a NULL skb. ++ */ ++ status = NETDEV_TX_OK; ++ goto unlock_txq; ++ } + skb->vlan_tci = 0; + } + +@@ -395,6 +401,7 @@ void netpoll_send_skb_on_dev(struct netp + if (status == NETDEV_TX_OK) + txq_trans_update(txq); + } ++ unlock_txq: + __netif_tx_unlock(txq); + + if (status == NETDEV_TX_OK) diff --git a/queue-3.12/netvsc-don-t-flush-peers-notifying-work-during-setting-mtu.patch b/queue-3.12/netvsc-don-t-flush-peers-notifying-work-during-setting-mtu.patch new file mode 100644 index 00000000000..384b4c80da4 --- /dev/null +++ b/queue-3.12/netvsc-don-t-flush-peers-notifying-work-during-setting-mtu.patch @@ -0,0 +1,90 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: Jason Wang +Date: Fri, 13 Dec 2013 17:21:27 +0800 +Subject: netvsc: don't flush peers notifying work during setting mtu + +From: Jason Wang + +[ Upstream commit 50dc875f2e6e2e04aed3b3033eb0ac99192d6d02 ] + +There's a possible deadlock if we flush the peers notifying work during setting +mtu: + +[ 22.991149] ====================================================== +[ 22.991173] [ INFO: possible circular locking dependency detected ] +[ 22.991198] 3.10.0-54.0.1.el7.x86_64.debug #1 Not tainted +[ 22.991219] ------------------------------------------------------- +[ 22.991243] ip/974 is trying to acquire lock: +[ 22.991261] ((&(&net_device_ctx->dwork)->work)){+.+.+.}, at: [] flush_work+0x5/0x2e0 +[ 22.991307] +but task is already holding lock: +[ 22.991330] (rtnl_mutex){+.+.+.}, at: [] rtnetlink_rcv+0x1b/0x40 +[ 22.991367] +which lock already depends on the new lock. + +[ 22.991398] +the existing dependency chain (in reverse order) is: +[ 22.991426] +-> #1 (rtnl_mutex){+.+.+.}: +[ 22.991449] [] __lock_acquire+0xb19/0x1260 +[ 22.991477] [] lock_acquire+0xa2/0x1f0 +[ 22.991501] [] mutex_lock_nested+0x89/0x4f0 +[ 22.991529] [] rtnl_lock+0x17/0x20 +[ 22.991552] [] netdev_notify_peers+0x12/0x30 +[ 22.991579] [] netvsc_send_garp+0x22/0x30 [hv_netvsc] +[ 22.991610] [] process_one_work+0x211/0x6e0 +[ 22.991637] [] worker_thread+0x11b/0x3a0 +[ 22.991663] [] kthread+0xed/0x100 +[ 22.991686] [] ret_from_fork+0x7c/0xb0 +[ 22.991715] +-> #0 ((&(&net_device_ctx->dwork)->work)){+.+.+.}: +[ 22.991715] [] check_prevs_add+0x967/0x970 +[ 22.991715] [] __lock_acquire+0xb19/0x1260 +[ 22.991715] [] lock_acquire+0xa2/0x1f0 +[ 22.991715] [] flush_work+0x4e/0x2e0 +[ 22.991715] [] __cancel_work_timer+0x95/0x130 +[ 22.991715] [] cancel_delayed_work_sync+0x13/0x20 +[ 22.991715] [] netvsc_change_mtu+0x84/0x200 [hv_netvsc] +[ 22.991715] [] dev_set_mtu+0x34/0x80 +[ 22.991715] [] do_setlink+0x23a/0xa00 +[ 22.991715] [] rtnl_newlink+0x394/0x5e0 +[ 22.991715] [] rtnetlink_rcv_msg+0x9c/0x260 +[ 22.991715] [] netlink_rcv_skb+0xa9/0xc0 +[ 22.991715] [] rtnetlink_rcv+0x2a/0x40 +[ 22.991715] [] netlink_unicast+0xdd/0x190 +[ 22.991715] [] netlink_sendmsg+0x337/0x750 +[ 22.991715] [] sock_sendmsg+0x99/0xd0 +[ 22.991715] [] ___sys_sendmsg+0x39e/0x3b0 +[ 22.991715] [] __sys_sendmsg+0x42/0x80 +[ 22.991715] [] SyS_sendmsg+0x12/0x20 +[ 22.991715] [] system_call_fastpath+0x16/0x1b + +This is because we hold the rtnl_lock() before ndo_change_mtu() and try to flush +the work in netvsc_change_mtu(), in the mean time, netdev_notify_peers() may be +called from worker and also trying to hold the rtnl_lock. This will lead the +flush won't succeed forever. Solve this by not canceling and flushing the work, +this is safe because the transmission done by NETDEV_NOTIFY_PEERS was +synchronized with the netif_tx_disable() called by netvsc_change_mtu(). + +Reported-by: Yaju Cao +Tested-by: Yaju Cao +Cc: K. Y. Srinivasan +Cc: Haiyang Zhang +Signed-off-by: Jason Wang +Acked-by: Haiyang Zhang +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/hyperv/netvsc_drv.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -327,7 +327,6 @@ static int netvsc_change_mtu(struct net_ + return -EINVAL; + + nvdev->start_remove = true; +- cancel_delayed_work_sync(&ndevctx->dwork); + cancel_work_sync(&ndevctx->work); + netif_tx_disable(ndev); + rndis_filter_device_remove(hdev); diff --git a/queue-3.12/rds-prevent-dereference-of-a-null-device.patch b/queue-3.12/rds-prevent-dereference-of-a-null-device.patch new file mode 100644 index 00000000000..e461e716f0e --- /dev/null +++ b/queue-3.12/rds-prevent-dereference-of-a-null-device.patch @@ -0,0 +1,77 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: Sasha Levin +Date: Wed, 18 Dec 2013 23:49:42 -0500 +Subject: rds: prevent dereference of a NULL device + +From: Sasha Levin + +[ Upstream commit c2349758acf1874e4c2b93fe41d072336f1a31d0 ] + +Binding might result in a NULL device, which is dereferenced +causing this BUG: + +[ 1317.260548] BUG: unable to handle kernel NULL pointer dereference at 000000000000097 +4 +[ 1317.261847] IP: [] rds_ib_laddr_check+0x82/0x110 +[ 1317.263315] PGD 418bcb067 PUD 3ceb21067 PMD 0 +[ 1317.263502] Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC +[ 1317.264179] Dumping ftrace buffer: +[ 1317.264774] (ftrace buffer empty) +[ 1317.265220] Modules linked in: +[ 1317.265824] CPU: 4 PID: 836 Comm: trinity-child46 Tainted: G W 3.13.0-rc4- +next-20131218-sasha-00013-g2cebb9b-dirty #4159 +[ 1317.267415] task: ffff8803ddf33000 ti: ffff8803cd31a000 task.ti: ffff8803cd31a000 +[ 1317.268399] RIP: 0010:[] [] rds_ib_laddr_check+ +0x82/0x110 +[ 1317.269670] RSP: 0000:ffff8803cd31bdf8 EFLAGS: 00010246 +[ 1317.270230] RAX: 0000000000000000 RBX: ffff88020b0dd388 RCX: 0000000000000000 +[ 1317.270230] RDX: ffffffff8439822e RSI: 00000000000c000a RDI: 0000000000000286 +[ 1317.270230] RBP: ffff8803cd31be38 R08: 0000000000000000 R09: 0000000000000000 +[ 1317.270230] R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000000000 +[ 1317.270230] R13: 0000000054086700 R14: 0000000000a25de0 R15: 0000000000000031 +[ 1317.270230] FS: 00007ff40251d700(0000) GS:ffff88022e200000(0000) knlGS:000000000000 +0000 +[ 1317.270230] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b +[ 1317.270230] CR2: 0000000000000974 CR3: 00000003cd478000 CR4: 00000000000006e0 +[ 1317.270230] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +[ 1317.270230] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000090602 +[ 1317.270230] Stack: +[ 1317.270230] 0000000054086700 5408670000a25de0 5408670000000002 0000000000000000 +[ 1317.270230] ffffffff84223542 00000000ea54c767 0000000000000000 ffffffff86d26160 +[ 1317.270230] ffff8803cd31be68 ffffffff84223556 ffff8803cd31beb8 ffff8800c6765280 +[ 1317.270230] Call Trace: +[ 1317.270230] [] ? rds_trans_get_preferred+0x42/0xa0 +[ 1317.270230] [] rds_trans_get_preferred+0x56/0xa0 +[ 1317.270230] [] rds_bind+0x73/0xf0 +[ 1317.270230] [] SYSC_bind+0x92/0xf0 +[ 1317.270230] [] ? context_tracking_user_exit+0xb8/0x1d0 +[ 1317.270230] [] ? trace_hardirqs_on+0xd/0x10 +[ 1317.270230] [] ? syscall_trace_enter+0x32/0x290 +[ 1317.270230] [] SyS_bind+0xe/0x10 +[ 1317.270230] [] tracesys+0xdd/0xe2 +[ 1317.270230] Code: 00 8b 45 cc 48 8d 75 d0 48 c7 45 d8 00 00 00 00 66 c7 45 d0 02 00 +89 45 d4 48 89 df e8 78 49 76 ff 41 89 c4 85 c0 75 0c 48 8b 03 <80> b8 74 09 00 00 01 7 +4 06 41 bc 9d ff ff ff f6 05 2a b6 c2 02 +[ 1317.270230] RIP [] rds_ib_laddr_check+0x82/0x110 +[ 1317.270230] RSP +[ 1317.270230] CR2: 0000000000000974 + +Signed-off-by: Sasha Levin +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/rds/ib.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/net/rds/ib.c ++++ b/net/rds/ib.c +@@ -338,7 +338,8 @@ static int rds_ib_laddr_check(__be32 add + ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin); + /* due to this, we will claim to support iWARP devices unless we + check node_type. */ +- if (ret || cm_id->device->node_type != RDMA_NODE_IB_CA) ++ if (ret || !cm_id->device || ++ cm_id->device->node_type != RDMA_NODE_IB_CA) + ret = -EADDRNOTAVAIL; + + rdsdebug("addr %pI4 ret %d node type %d\n", diff --git a/queue-3.12/series b/queue-3.12/series index a06652a3414..9cd445a6067 100644 --- a/queue-3.12/series +++ b/queue-3.12/series @@ -13,3 +13,38 @@ packet-fix-send-path-when-running-with-proto-0.patch ipv6-don-t-count-addrconf-generated-routes-against-gc-limit.patch net-drop_monitor-fix-the-value-of-maxattr.patch inet-fix-null-pointer-oops-in-fib-6-_rule_suppress.patch +net-unix-allow-set_peek_off-to-fail.patch +vxlan-release-rt-when-found-circular-route.patch +tg3-initialize-reg_base_addr-at-pci-config-offset-120-to-0.patch +netvsc-don-t-flush-peers-notifying-work-during-setting-mtu.patch +ipv6-fix-illegal-mac_header-comparison-on-32bit.patch +net-unix-allow-bind-to-fail-on-mutex-lock.patch +ip_gre-fix-msg_name-parsing-for-recvfrom-recvmsg.patch +net-inet_diag-zero-out-uninitialized-idiag_-src-dst-fields.patch +drivers-net-hamradio-integer-overflow-in-hdlcdrv_ioctl.patch +hamradio-yam-fix-info-leak-in-ioctl.patch +net-fec-fix-potential-use-after-free.patch +ipv6-always-set-the-new-created-dst-s-from-in-ip6_rt_copy.patch +rds-prevent-dereference-of-a-null-device.patch +arc_emac-fix-potential-use-after-free.patch +net-rose-restore-old-recvmsg-behavior.patch +vlan-fix-header-ops-passthru-when-doing-tx-vlan-offload.patch +virtio_net-fix-error-handling-for-mergeable-buffers.patch +virtio-net-make-all-rx-paths-handle-errors.patch +virtio_net-don-t-leak-memory-or-block-when-too-many-frags.patch +ipv4-fix-tunneled-vm-traffic-over-hw-vxlan-gre-gso-nic.patch +virtio-net-fix-refill-races-during-restore.patch +net-llc-fix-use-after-free-in-llc_ui_recvmsg.patch +netpoll-fix-missing-txq-unlock-and-and-oops.patch +bridge-use-spin_lock_bh-in-br_multicast_set_hash_max.patch +sfc-add-length-checks-to-efx_xmit_with_hwtstamp-and-efx_ptp_is_ptp_tx.patch +sfc-ptp-moderate-log-message-on-event-queue-overflow.patch +sfc-rate-limit-log-message-for-ptp-packets-without-a-matching-timestamp-event.patch +sfc-stop-re-start-ptp-when-stopping-starting-the-datapath.patch +sfc-maintain-current-frequency-adjustment-when-applying-a-time-offset.patch +sfc-rx-buffer-allocation-takes-prefix-size-into-account-in-ip-header-alignment.patch +sfc-refactor-efx_mcdi_poll-by-introducing-efx_mcdi_poll_once.patch +sfc-poll-for-mcdi-completion-once-before-timeout-occurs.patch +arm-fix-footbridge-clockevent-device.patch +arm-fix-bad-mode-in-...-handler-message-for-undefined-instructions.patch +arm-7923-1-mm-fix-dcache-flush-logic-for-compound-high-pages.patch diff --git a/queue-3.12/sfc-add-length-checks-to-efx_xmit_with_hwtstamp-and-efx_ptp_is_ptp_tx.patch b/queue-3.12/sfc-add-length-checks-to-efx_xmit_with_hwtstamp-and-efx_ptp_is_ptp_tx.patch new file mode 100644 index 00000000000..3df49eb25c1 --- /dev/null +++ b/queue-3.12/sfc-add-length-checks-to-efx_xmit_with_hwtstamp-and-efx_ptp_is_ptp_tx.patch @@ -0,0 +1,41 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: Ben Hutchings +Date: Fri, 6 Dec 2013 19:26:40 +0000 +Subject: sfc: Add length checks to efx_xmit_with_hwtstamp() and efx_ptp_is_ptp_tx() + +From: Ben Hutchings + +[ Upstream commit e5a498e943fbc497f236ab8cf31366c75f337ce6 ] + +efx_ptp_is_ptp_tx() must be robust against skbs from raw sockets that +have invalid IPv4 and UDP headers. + +Add checks that: +- the transport header has been found +- there is enough space between network and transport header offset + for an IPv4 header +- there is enough space after the transport header offset for a + UDP header + +Fixes: 7c236c43b838 ('sfc: Add support for IEEE-1588 PTP') +Signed-off-by: Ben Hutchings +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/sfc/ptp.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/ethernet/sfc/ptp.c ++++ b/drivers/net/ethernet/sfc/ptp.c +@@ -989,7 +989,11 @@ bool efx_ptp_is_ptp_tx(struct efx_nic *e + skb->len >= PTP_MIN_LENGTH && + skb->len <= MC_CMD_PTP_IN_TRANSMIT_PACKET_MAXNUM && + likely(skb->protocol == htons(ETH_P_IP)) && ++ skb_transport_header_was_set(skb) && ++ skb_network_header_len(skb) >= sizeof(struct iphdr) && + ip_hdr(skb)->protocol == IPPROTO_UDP && ++ skb_headlen(skb) >= ++ skb_transport_offset(skb) + sizeof(struct udphdr) && + udp_hdr(skb)->dest == htons(PTP_EVENT_PORT); + } + diff --git a/queue-3.12/sfc-maintain-current-frequency-adjustment-when-applying-a-time-offset.patch b/queue-3.12/sfc-maintain-current-frequency-adjustment-when-applying-a-time-offset.patch new file mode 100644 index 00000000000..a16ff542ddd --- /dev/null +++ b/queue-3.12/sfc-maintain-current-frequency-adjustment-when-applying-a-time-offset.patch @@ -0,0 +1,45 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: Ben Hutchings +Date: Thu, 5 Dec 2013 17:24:06 +0000 +Subject: sfc: Maintain current frequency adjustment when applying a time offset + +From: Ben Hutchings + +[ Upstream commit cd6fe65e923175e4f2e9fb585b1d78c6bf580fc6 ] + +There is a single MCDI PTP operation for setting the frequency +adjustment and applying a time offset to the hardware clock. When +applying a time offset we should not change the frequency adjustment. + +These two operations can now be requested separately but this requires +a flash firmware update. Keep using the single operation, but +remember and repeat the previous frequency adjustment. + +Fixes: 7c236c43b838 ('sfc: Add support for IEEE-1588 PTP') +Signed-off-by: Ben Hutchings +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/sfc/ptp.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/sfc/ptp.c ++++ b/drivers/net/ethernet/sfc/ptp.c +@@ -1426,7 +1426,7 @@ static int efx_phc_adjfreq(struct ptp_cl + if (rc != 0) + return rc; + +- ptp_data->current_adjfreq = delta; ++ ptp_data->current_adjfreq = adjustment_ns; + return 0; + } + +@@ -1441,7 +1441,7 @@ static int efx_phc_adjtime(struct ptp_cl + + MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_ADJUST); + MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0); +- MCDI_SET_QWORD(inbuf, PTP_IN_ADJUST_FREQ, 0); ++ MCDI_SET_QWORD(inbuf, PTP_IN_ADJUST_FREQ, ptp_data->current_adjfreq); + MCDI_SET_DWORD(inbuf, PTP_IN_ADJUST_SECONDS, (u32)delta_ts.tv_sec); + MCDI_SET_DWORD(inbuf, PTP_IN_ADJUST_NANOSECONDS, (u32)delta_ts.tv_nsec); + return efx_mcdi_rpc(efx, MC_CMD_PTP, inbuf, sizeof(inbuf), diff --git a/queue-3.12/sfc-poll-for-mcdi-completion-once-before-timeout-occurs.patch b/queue-3.12/sfc-poll-for-mcdi-completion-once-before-timeout-occurs.patch new file mode 100644 index 00000000000..4b51319b3db --- /dev/null +++ b/queue-3.12/sfc-poll-for-mcdi-completion-once-before-timeout-occurs.patch @@ -0,0 +1,57 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: Robert Stonehouse +Date: Wed, 9 Oct 2013 11:52:48 +0100 +Subject: sfc: Poll for MCDI completion once before timeout occurs + +From: Robert Stonehouse + +[ Upstream commit 6b294b8efedaa7cf7507154148e2c79766ad6f96 ] + +There is an as-yet unexplained bug that sometimes prevents (or delays) +the driver seeing the completion event for a completed MCDI request on +the SFC9120. The requested configuration change will have happened +but the driver assumes it to have failed, and this can result in +further failures. We can mitigate this by polling for completion +after unsuccessfully waiting for an event. + +Fixes: 8127d661e77f ('sfc: Add support for Solarflare SFC9100 family') +Signed-off-by: Ben Hutchings +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/sfc/mcdi.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/sfc/mcdi.c ++++ b/drivers/net/ethernet/sfc/mcdi.c +@@ -630,6 +630,16 @@ int efx_mcdi_rpc_finish(struct efx_nic * + rc = efx_mcdi_await_completion(efx); + + if (rc != 0) { ++ netif_err(efx, hw, efx->net_dev, ++ "MC command 0x%x inlen %d mode %d timed out\n", ++ cmd, (int)inlen, mcdi->mode); ++ ++ if (mcdi->mode == MCDI_MODE_EVENTS && efx_mcdi_poll_once(efx)) { ++ netif_err(efx, hw, efx->net_dev, ++ "MCDI request was completed without an event\n"); ++ rc = 0; ++ } ++ + /* Close the race with efx_mcdi_ev_cpl() executing just too late + * and completing a request we've just cancelled, by ensuring + * that the seqno check therein fails. +@@ -638,11 +648,9 @@ int efx_mcdi_rpc_finish(struct efx_nic * + ++mcdi->seqno; + ++mcdi->credits; + spin_unlock_bh(&mcdi->iface_lock); ++ } + +- netif_err(efx, hw, efx->net_dev, +- "MC command 0x%x inlen %d mode %d timed out\n", +- cmd, (int)inlen, mcdi->mode); +- } else { ++ if (rc == 0) { + size_t hdr_len, data_len; + + /* At the very least we need a memory barrier here to ensure diff --git a/queue-3.12/sfc-ptp-moderate-log-message-on-event-queue-overflow.patch b/queue-3.12/sfc-ptp-moderate-log-message-on-event-queue-overflow.patch new file mode 100644 index 00000000000..60bba5c05d9 --- /dev/null +++ b/queue-3.12/sfc-ptp-moderate-log-message-on-event-queue-overflow.patch @@ -0,0 +1,93 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: Laurence Evans +Date: Mon, 28 Jan 2013 14:51:17 +0000 +Subject: sfc: PTP: Moderate log message on event queue overflow + +From: Laurence Evans + +[ Upstream commit f32116003c39f3a6815215a7512e1ea8d1e4bbc7 ] + +Limit syslog flood if a PTP packet storm occurs. + +Fixes: 7c236c43b838 ('sfc: Add support for IEEE-1588 PTP') +Signed-off-by: Ben Hutchings +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/sfc/ptp.c | 23 +++++++++++++++++++++-- + 1 file changed, 21 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/sfc/ptp.c ++++ b/drivers/net/ethernet/sfc/ptp.c +@@ -220,6 +220,7 @@ struct efx_ptp_timeset { + * @evt_list: List of MC receive events awaiting packets + * @evt_free_list: List of free events + * @evt_lock: Lock for manipulating evt_list and evt_free_list ++ * @evt_overflow: Boolean indicating that event list has overflowed + * @rx_evts: Instantiated events (on evt_list and evt_free_list) + * @workwq: Work queue for processing pending PTP operations + * @work: Work task +@@ -270,6 +271,7 @@ struct efx_ptp_data { + struct list_head evt_list; + struct list_head evt_free_list; + spinlock_t evt_lock; ++ bool evt_overflow; + struct efx_ptp_event_rx rx_evts[MAX_RECEIVE_EVENTS]; + struct workqueue_struct *workwq; + struct work_struct work; +@@ -635,6 +637,11 @@ static void efx_ptp_drop_time_expired_ev + } + } + } ++ /* If the event overflow flag is set and the event list is now empty ++ * clear the flag to re-enable the overflow warning message. ++ */ ++ if (ptp->evt_overflow && list_empty(&ptp->evt_list)) ++ ptp->evt_overflow = false; + spin_unlock_bh(&ptp->evt_lock); + } + +@@ -676,6 +683,11 @@ static enum ptp_packet_state efx_ptp_mat + break; + } + } ++ /* If the event overflow flag is set and the event list is now empty ++ * clear the flag to re-enable the overflow warning message. ++ */ ++ if (ptp->evt_overflow && list_empty(&ptp->evt_list)) ++ ptp->evt_overflow = false; + spin_unlock_bh(&ptp->evt_lock); + + return rc; +@@ -809,6 +821,7 @@ static int efx_ptp_stop(struct efx_nic * + list_for_each_safe(cursor, next, &efx->ptp_data->evt_list) { + list_move(cursor, &efx->ptp_data->evt_free_list); + } ++ ptp->evt_overflow = false; + spin_unlock_bh(&efx->ptp_data->evt_lock); + + return rc; +@@ -901,6 +914,7 @@ static int efx_ptp_probe_channel(struct + spin_lock_init(&ptp->evt_lock); + for (pos = 0; pos < MAX_RECEIVE_EVENTS; pos++) + list_add(&ptp->rx_evts[pos].link, &ptp->evt_free_list); ++ ptp->evt_overflow = false; + + ptp->phc_clock_info.owner = THIS_MODULE; + snprintf(ptp->phc_clock_info.name, +@@ -1299,8 +1313,13 @@ static void ptp_event_rx(struct efx_nic + list_add_tail(&evt->link, &ptp->evt_list); + + queue_work(ptp->workwq, &ptp->work); +- } else { +- netif_err(efx, rx_err, efx->net_dev, "No free PTP event"); ++ } else if (!ptp->evt_overflow) { ++ /* Log a warning message and set the event overflow flag. ++ * The message won't be logged again until the event queue ++ * becomes empty. ++ */ ++ netif_err(efx, rx_err, efx->net_dev, "PTP event queue overflow\n"); ++ ptp->evt_overflow = true; + } + spin_unlock_bh(&ptp->evt_lock); + } diff --git a/queue-3.12/sfc-rate-limit-log-message-for-ptp-packets-without-a-matching-timestamp-event.patch b/queue-3.12/sfc-rate-limit-log-message-for-ptp-packets-without-a-matching-timestamp-event.patch new file mode 100644 index 00000000000..7d4bdca4ef0 --- /dev/null +++ b/queue-3.12/sfc-rate-limit-log-message-for-ptp-packets-without-a-matching-timestamp-event.patch @@ -0,0 +1,35 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: Ben Hutchings +Date: Fri, 6 Dec 2013 22:10:46 +0000 +Subject: sfc: Rate-limit log message for PTP packets without a matching timestamp event + +From: Ben Hutchings + +[ Upstream commit 35f9a7a380728a94d417e5824a866f969423ac83 ] + +In case of a flood of PTP packets, the timestamp peripheral and MC +firmware on the SFN[56]322F boards may not be able to provide +timestamp events for all packets. Don't complain too much about this. + +Fixes: 7c236c43b838 ('sfc: Add support for IEEE-1588 PTP') +Signed-off-by: Ben Hutchings +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/sfc/ptp.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/sfc/ptp.c ++++ b/drivers/net/ethernet/sfc/ptp.c +@@ -717,8 +717,9 @@ static bool efx_ptp_process_events(struc + __skb_queue_tail(q, skb); + } else if (time_after(jiffies, match->expiry)) { + match->state = PTP_PACKET_STATE_TIMED_OUT; +- netif_warn(efx, rx_err, efx->net_dev, +- "PTP packet - no timestamp seen\n"); ++ if (net_ratelimit()) ++ netif_warn(efx, rx_err, efx->net_dev, ++ "PTP packet - no timestamp seen\n"); + __skb_queue_tail(q, skb); + } else { + /* Replace unprocessed entry and stop */ diff --git a/queue-3.12/sfc-refactor-efx_mcdi_poll-by-introducing-efx_mcdi_poll_once.patch b/queue-3.12/sfc-refactor-efx_mcdi_poll-by-introducing-efx_mcdi_poll_once.patch new file mode 100644 index 00000000000..dc33b682a73 --- /dev/null +++ b/queue-3.12/sfc-refactor-efx_mcdi_poll-by-introducing-efx_mcdi_poll_once.patch @@ -0,0 +1,68 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: Robert Stonehouse +Date: Wed, 9 Oct 2013 11:52:43 +0100 +Subject: sfc: Refactor efx_mcdi_poll() by introducing efx_mcdi_poll_once() + +From: Robert Stonehouse + +[ Upstream commit 5731d7b35e5b87157a9b9973cc2eff70c50aec58 ] + +Signed-off-by: Ben Hutchings +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/sfc/mcdi.c | 23 +++++++++++++++++------ + 1 file changed, 17 insertions(+), 6 deletions(-) + +--- a/drivers/net/ethernet/sfc/mcdi.c ++++ b/drivers/net/ethernet/sfc/mcdi.c +@@ -50,6 +50,7 @@ struct efx_mcdi_async_param { + static void efx_mcdi_timeout_async(unsigned long context); + static int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating, + bool *was_attached_out); ++static bool efx_mcdi_poll_once(struct efx_nic *efx); + + static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx) + { +@@ -237,6 +238,21 @@ static void efx_mcdi_read_response_heade + } + } + ++static bool efx_mcdi_poll_once(struct efx_nic *efx) ++{ ++ struct efx_mcdi_iface *mcdi = efx_mcdi(efx); ++ ++ rmb(); ++ if (!efx->type->mcdi_poll_response(efx)) ++ return false; ++ ++ spin_lock_bh(&mcdi->iface_lock); ++ efx_mcdi_read_response_header(efx); ++ spin_unlock_bh(&mcdi->iface_lock); ++ ++ return true; ++} ++ + static int efx_mcdi_poll(struct efx_nic *efx) + { + struct efx_mcdi_iface *mcdi = efx_mcdi(efx); +@@ -272,18 +288,13 @@ static int efx_mcdi_poll(struct efx_nic + + time = jiffies; + +- rmb(); +- if (efx->type->mcdi_poll_response(efx)) ++ if (efx_mcdi_poll_once(efx)) + break; + + if (time_after(time, finish)) + return -ETIMEDOUT; + } + +- spin_lock_bh(&mcdi->iface_lock); +- efx_mcdi_read_response_header(efx); +- spin_unlock_bh(&mcdi->iface_lock); +- + /* Return rc=0 like wait_event_timeout() */ + return 0; + } diff --git a/queue-3.12/sfc-rx-buffer-allocation-takes-prefix-size-into-account-in-ip-header-alignment.patch b/queue-3.12/sfc-rx-buffer-allocation-takes-prefix-size-into-account-in-ip-header-alignment.patch new file mode 100644 index 00000000000..00020f41e24 --- /dev/null +++ b/queue-3.12/sfc-rx-buffer-allocation-takes-prefix-size-into-account-in-ip-header-alignment.patch @@ -0,0 +1,85 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: Andrew Rybchenko +Date: Sat, 16 Nov 2013 11:02:27 +0400 +Subject: sfc: RX buffer allocation takes prefix size into account in IP header alignment + +From: Andrew Rybchenko + +[ Upstream commit 2ec030144f648a6dd208f95f55ece212f1b72771 ] + +rx_prefix_size is 4-bytes aligned on Falcon/Siena (16 bytes), but it is equal +to 14 on EF10. So, it should be taken into account if arch requires IP header +to be 4-bytes aligned (via NET_IP_ALIGN). + +Fixes: 8127d661e77f ('sfc: Add support for Solarflare SFC9100 family') +Signed-off-by: Ben Hutchings +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/sfc/efx.c | 4 +++- + drivers/net/ethernet/sfc/net_driver.h | 3 +++ + drivers/net/ethernet/sfc/rx.c | 6 +++--- + 3 files changed, 9 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/sfc/efx.c ++++ b/drivers/net/ethernet/sfc/efx.c +@@ -585,7 +585,7 @@ static void efx_start_datapath(struct ef + EFX_MAX_FRAME_LEN(efx->net_dev->mtu) + + efx->type->rx_buffer_padding); + rx_buf_len = (sizeof(struct efx_rx_page_state) + +- NET_IP_ALIGN + efx->rx_dma_len); ++ efx->rx_ip_align + efx->rx_dma_len); + if (rx_buf_len <= PAGE_SIZE) { + efx->rx_scatter = efx->type->always_rx_scatter; + efx->rx_buffer_order = 0; +@@ -2554,6 +2554,8 @@ static int efx_init_struct(struct efx_ni + + efx->net_dev = net_dev; + efx->rx_prefix_size = efx->type->rx_prefix_size; ++ efx->rx_ip_align = ++ NET_IP_ALIGN ? (efx->rx_prefix_size + NET_IP_ALIGN) % 4 : 0; + efx->rx_packet_hash_offset = + efx->type->rx_hash_offset - efx->type->rx_prefix_size; + spin_lock_init(&efx->stats_lock); +--- a/drivers/net/ethernet/sfc/net_driver.h ++++ b/drivers/net/ethernet/sfc/net_driver.h +@@ -673,6 +673,8 @@ struct vfdi_status; + * @n_channels: Number of channels in use + * @n_rx_channels: Number of channels used for RX (= number of RX queues) + * @n_tx_channels: Number of channels used for TX ++ * @rx_ip_align: RX DMA address offset to have IP header aligned in ++ * in accordance with NET_IP_ALIGN + * @rx_dma_len: Current maximum RX DMA length + * @rx_buffer_order: Order (log2) of number of pages for each RX buffer + * @rx_buffer_truesize: Amortised allocation size of an RX buffer, +@@ -806,6 +808,7 @@ struct efx_nic { + unsigned rss_spread; + unsigned tx_channel_offset; + unsigned n_tx_channels; ++ unsigned int rx_ip_align; + unsigned int rx_dma_len; + unsigned int rx_buffer_order; + unsigned int rx_buffer_truesize; +--- a/drivers/net/ethernet/sfc/rx.c ++++ b/drivers/net/ethernet/sfc/rx.c +@@ -93,7 +93,7 @@ static inline void efx_sync_rx_buffer(st + + void efx_rx_config_page_split(struct efx_nic *efx) + { +- efx->rx_page_buf_step = ALIGN(efx->rx_dma_len + NET_IP_ALIGN, ++ efx->rx_page_buf_step = ALIGN(efx->rx_dma_len + efx->rx_ip_align, + EFX_RX_BUF_ALIGNMENT); + efx->rx_bufs_per_page = efx->rx_buffer_order ? 1 : + ((PAGE_SIZE - sizeof(struct efx_rx_page_state)) / +@@ -188,9 +188,9 @@ static int efx_init_rx_buffers(struct ef + do { + index = rx_queue->added_count & rx_queue->ptr_mask; + rx_buf = efx_rx_buffer(rx_queue, index); +- rx_buf->dma_addr = dma_addr + NET_IP_ALIGN; ++ rx_buf->dma_addr = dma_addr + efx->rx_ip_align; + rx_buf->page = page; +- rx_buf->page_offset = page_offset + NET_IP_ALIGN; ++ rx_buf->page_offset = page_offset + efx->rx_ip_align; + rx_buf->len = efx->rx_dma_len; + rx_buf->flags = 0; + ++rx_queue->added_count; diff --git a/queue-3.12/sfc-stop-re-start-ptp-when-stopping-starting-the-datapath.patch b/queue-3.12/sfc-stop-re-start-ptp-when-stopping-starting-the-datapath.patch new file mode 100644 index 00000000000..220c4a01da9 --- /dev/null +++ b/queue-3.12/sfc-stop-re-start-ptp-when-stopping-starting-the-datapath.patch @@ -0,0 +1,123 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: Alexandre Rames +Date: Fri, 8 Nov 2013 10:20:31 +0000 +Subject: sfc: Stop/re-start PTP when stopping/starting the datapath. + +From: Alexandre Rames + +[ Upstream commit 2ea4dc28a5bcec408e01a8772763871638a5ec79 ] + +This disables PTP when we bring the interface down to avoid getting +unmatched RX timestamp events, and tries to re-enable it when bringing +the interface up. + +[bwh: Make efx_ptp_stop() safe on Falcon. Introduce + efx_ptp_{start,stop}_datapath() functions; we'll expand them later.] + +Fixes: 7c236c43b838 ('sfc: Add support for IEEE-1588 PTP') +Signed-off-by: Ben Hutchings +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/sfc/efx.c | 4 ++++ + drivers/net/ethernet/sfc/nic.h | 2 ++ + drivers/net/ethernet/sfc/ptp.c | 30 +++++++++++++++++++++++++++--- + 3 files changed, 33 insertions(+), 3 deletions(-) + +--- a/drivers/net/ethernet/sfc/efx.c ++++ b/drivers/net/ethernet/sfc/efx.c +@@ -645,6 +645,8 @@ static void efx_start_datapath(struct ef + WARN_ON(channel->rx_pkt_n_frags); + } + ++ efx_ptp_start_datapath(efx); ++ + if (netif_device_present(efx->net_dev)) + netif_tx_wake_all_queues(efx->net_dev); + } +@@ -659,6 +661,8 @@ static void efx_stop_datapath(struct efx + EFX_ASSERT_RESET_SERIALISED(efx); + BUG_ON(efx->port_enabled); + ++ efx_ptp_stop_datapath(efx); ++ + /* Stop RX refill */ + efx_for_each_channel(channel, efx) { + efx_for_each_channel_rx_queue(rx_queue, channel) +--- a/drivers/net/ethernet/sfc/nic.h ++++ b/drivers/net/ethernet/sfc/nic.h +@@ -528,6 +528,8 @@ extern void efx_ptp_get_ts_info(struct e + extern bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); + extern int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); + extern void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev); ++void efx_ptp_start_datapath(struct efx_nic *efx); ++void efx_ptp_stop_datapath(struct efx_nic *efx); + + extern const struct efx_nic_type falcon_a1_nic_type; + extern const struct efx_nic_type falcon_b0_nic_type; +--- a/drivers/net/ethernet/sfc/ptp.c ++++ b/drivers/net/ethernet/sfc/ptp.c +@@ -801,9 +801,14 @@ fail: + static int efx_ptp_stop(struct efx_nic *efx) + { + struct efx_ptp_data *ptp = efx->ptp_data; +- int rc = efx_ptp_disable(efx); + struct list_head *cursor; + struct list_head *next; ++ int rc; ++ ++ if (ptp == NULL) ++ return 0; ++ ++ rc = efx_ptp_disable(efx); + + if (ptp->rxfilter_installed) { + efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED, +@@ -828,6 +833,13 @@ static int efx_ptp_stop(struct efx_nic * + return rc; + } + ++static int efx_ptp_restart(struct efx_nic *efx) ++{ ++ if (efx->ptp_data && efx->ptp_data->enabled) ++ return efx_ptp_start(efx); ++ return 0; ++} ++ + static void efx_ptp_pps_worker(struct work_struct *work) + { + struct efx_ptp_data *ptp = +@@ -1125,7 +1137,7 @@ static int efx_ptp_change_mode(struct ef + { + if ((enable_wanted != efx->ptp_data->enabled) || + (enable_wanted && (efx->ptp_data->mode != new_mode))) { +- int rc; ++ int rc = 0; + + if (enable_wanted) { + /* Change of mode requires disable */ +@@ -1142,7 +1154,8 @@ static int efx_ptp_change_mode(struct ef + * succeed. + */ + efx->ptp_data->mode = new_mode; +- rc = efx_ptp_start(efx); ++ if (netif_running(efx->net_dev)) ++ rc = efx_ptp_start(efx); + if (rc == 0) { + rc = efx_ptp_synchronize(efx, + PTP_SYNC_ATTEMPTS * 2); +@@ -1515,3 +1528,14 @@ void efx_ptp_probe(struct efx_nic *efx) + efx->extra_channel_type[EFX_EXTRA_CHANNEL_PTP] = + &efx_ptp_channel_type; + } ++ ++void efx_ptp_start_datapath(struct efx_nic *efx) ++{ ++ if (efx_ptp_restart(efx)) ++ netif_err(efx, drv, efx->net_dev, "Failed to restart PTP.\n"); ++} ++ ++void efx_ptp_stop_datapath(struct efx_nic *efx) ++{ ++ efx_ptp_stop(efx); ++} diff --git a/queue-3.12/tg3-initialize-reg_base_addr-at-pci-config-offset-120-to-0.patch b/queue-3.12/tg3-initialize-reg_base_addr-at-pci-config-offset-120-to-0.patch new file mode 100644 index 00000000000..92cc7585d50 --- /dev/null +++ b/queue-3.12/tg3-initialize-reg_base_addr-at-pci-config-offset-120-to-0.patch @@ -0,0 +1,37 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: Nat Gurumoorthy +Date: Mon, 9 Dec 2013 10:43:21 -0800 +Subject: tg3: Initialize REG_BASE_ADDR at PCI config offset 120 to 0 + +From: Nat Gurumoorthy + +[ Upstream commit 388d3335575f4c056dcf7138a30f1454e2145cd8 ] + +The new tg3 driver leaves REG_BASE_ADDR (PCI config offset 120) +uninitialized. From power on reset this register may have garbage in it. The +Register Base Address register defines the device local address of a +register. The data pointed to by this location is read or written using +the Register Data register (PCI config offset 128). When REG_BASE_ADDR has +garbage any read or write of Register Data Register (PCI 128) will cause the +PCI bus to lock up. The TCO watchdog will fire and bring down the system. + +Signed-off-by: Nat Gurumoorthy +Acked-by: Michael Chan +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/broadcom/tg3.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/net/ethernet/broadcom/tg3.c ++++ b/drivers/net/ethernet/broadcom/tg3.c +@@ -16485,6 +16485,9 @@ static int tg3_get_invariants(struct tg3 + /* Clear this out for sanity. */ + tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0); + ++ /* Clear TG3PCI_REG_BASE_ADDR to prevent hangs. */ ++ tw32(TG3PCI_REG_BASE_ADDR, 0); ++ + pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE, + &pci_state_reg); + if ((pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0 && diff --git a/queue-3.12/virtio-net-fix-refill-races-during-restore.patch b/queue-3.12/virtio-net-fix-refill-races-during-restore.patch new file mode 100644 index 00000000000..8f536eb2258 --- /dev/null +++ b/queue-3.12/virtio-net-fix-refill-races-during-restore.patch @@ -0,0 +1,52 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: Jason Wang +Date: Mon, 30 Dec 2013 11:34:40 +0800 +Subject: virtio-net: fix refill races during restore + +From: Jason Wang + +[ Upstream commit 6cd4ce0099da7702f885b6fa9ebb49e3831d90b4 ] + +During restoring, try_fill_recv() was called with neither napi lock nor napi +disabled. This can lead two try_fill_recv() was called in the same time. Fix +this by refilling before trying to enable napi. + +Fixes 0741bcb5584f9e2390ae6261573c4de8314999f2 +(virtio: net: Add freeze, restore handlers to support S4). + +Cc: Amit Shah +Cc: Rusty Russell +Cc: Michael S. Tsirkin +Cc: Eric Dumazet +Signed-off-by: Jason Wang +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/virtio_net.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +--- a/drivers/net/virtio_net.c ++++ b/drivers/net/virtio_net.c +@@ -1772,16 +1772,17 @@ static int virtnet_restore(struct virtio + if (err) + return err; + +- if (netif_running(vi->dev)) ++ if (netif_running(vi->dev)) { ++ for (i = 0; i < vi->curr_queue_pairs; i++) ++ if (!try_fill_recv(&vi->rq[i], GFP_KERNEL)) ++ schedule_delayed_work(&vi->refill, 0); ++ + for (i = 0; i < vi->max_queue_pairs; i++) + virtnet_napi_enable(&vi->rq[i]); ++ } + + netif_device_attach(vi->dev); + +- for (i = 0; i < vi->curr_queue_pairs; i++) +- if (!try_fill_recv(&vi->rq[i], GFP_KERNEL)) +- schedule_delayed_work(&vi->refill, 0); +- + mutex_lock(&vi->config_lock); + vi->config_enable = true; + mutex_unlock(&vi->config_lock); diff --git a/queue-3.12/virtio-net-make-all-rx-paths-handle-errors.patch b/queue-3.12/virtio-net-make-all-rx-paths-handle-errors.patch new file mode 100644 index 00000000000..1d5fe4a52db --- /dev/null +++ b/queue-3.12/virtio-net-make-all-rx-paths-handle-errors.patch @@ -0,0 +1,105 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: "Michael S. Tsirkin" +Date: Thu, 26 Dec 2013 15:32:51 +0200 +Subject: virtio-net: make all RX paths handle errors + consistently + +From: "Michael S. Tsirkin" + +receive mergeable now handles errors internally. +Do same for big and small packet paths, otherwise +the logic is too hard to follow. + +Cc: Jason Wang +Cc: David S. Miller +Acked-by: Michael Dalton +Signed-off-by: Michael S. Tsirkin + +(cherry picked from commit f121159d72091f25afb22007c833e60a6845e912) +Acked-by: Jason Wang +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/virtio_net.c | 56 ++++++++++++++++++++++++++++++----------------- + 1 file changed, 36 insertions(+), 20 deletions(-) + +--- a/drivers/net/virtio_net.c ++++ b/drivers/net/virtio_net.c +@@ -297,6 +297,34 @@ static struct sk_buff *page_to_skb(struc + return skb; + } + ++static struct sk_buff *receive_small(void *buf, unsigned int len) ++{ ++ struct sk_buff * skb = buf; ++ ++ len -= sizeof(struct virtio_net_hdr); ++ skb_trim(skb, len); ++ ++ return skb; ++} ++ ++static struct sk_buff *receive_big(struct net_device *dev, ++ struct receive_queue *rq, ++ void *buf) ++{ ++ struct page *page = buf; ++ struct sk_buff *skb = page_to_skb(rq, page, 0); ++ ++ if (unlikely(!skb)) ++ goto err; ++ ++ return skb; ++ ++err: ++ dev->stats.rx_dropped++; ++ give_pages(rq, page); ++ return NULL; ++} ++ + static struct sk_buff *receive_mergeable(struct net_device *dev, + struct receive_queue *rq, + void *buf, +@@ -360,7 +388,6 @@ static void receive_buf(struct receive_q + struct net_device *dev = vi->dev; + struct virtnet_stats *stats = this_cpu_ptr(vi->stats); + struct sk_buff *skb; +- struct page *page; + struct skb_vnet_hdr *hdr; + + if (unlikely(len < sizeof(struct virtio_net_hdr) + ETH_HLEN)) { +@@ -372,26 +399,15 @@ static void receive_buf(struct receive_q + dev_kfree_skb(buf); + return; + } ++ if (vi->mergeable_rx_bufs) ++ skb = receive_mergeable(dev, rq, buf, len); ++ else if (vi->big_packets) ++ skb = receive_big(dev, rq, buf); ++ else ++ skb = receive_small(buf, len); + +- if (!vi->mergeable_rx_bufs && !vi->big_packets) { +- skb = buf; +- len -= sizeof(struct virtio_net_hdr); +- skb_trim(skb, len); +- } else { +- page = buf; +- if (vi->mergeable_rx_bufs) { +- skb = receive_mergeable(dev, rq, page, len); +- if (unlikely(!skb)) +- return; +- } else { +- skb = page_to_skb(rq, page, len); +- if (unlikely(!skb)) { +- dev->stats.rx_dropped++; +- give_pages(rq, page); +- return; +- } +- } +- } ++ if (unlikely(!skb)) ++ return; + + hdr = skb_vnet_hdr(skb); + diff --git a/queue-3.12/virtio_net-don-t-leak-memory-or-block-when-too-many-frags.patch b/queue-3.12/virtio_net-don-t-leak-memory-or-block-when-too-many-frags.patch new file mode 100644 index 00000000000..da5e5a450a7 --- /dev/null +++ b/queue-3.12/virtio_net-don-t-leak-memory-or-block-when-too-many-frags.patch @@ -0,0 +1,39 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: "Michael S. Tsirkin" +Date: Thu, 26 Dec 2013 15:32:55 +0200 +Subject: virtio_net: don't leak memory or block when too many frags + +From: "Michael S. Tsirkin" + +We leak an skb when there are too many frags, +we also stop processing the packet in the middle, +the result is almost sure to be loss of networking. + +Reported-by: Michael Dalton +Acked-by: Michael Dalton +Signed-off-by: Michael S. Tsirkin +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/virtio_net.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/virtio_net.c ++++ b/drivers/net/virtio_net.c +@@ -344,7 +344,7 @@ static struct sk_buff *receive_mergeable + if (i >= MAX_SKB_FRAGS) { + pr_debug("%s: packet too long\n", skb->dev->name); + skb->dev->stats.rx_length_errors++; +- return NULL; ++ goto err_frags; + } + page = virtqueue_get_buf(rq->vq, &len); + if (!page) { +@@ -365,6 +365,7 @@ static struct sk_buff *receive_mergeable + err_skb: + give_pages(rq, page); + while (--num_buf) { ++err_frags: + buf = virtqueue_get_buf(rq->vq, &len); + if (unlikely(!buf)) { + pr_debug("%s: rx error: %d buffers missing\n", diff --git a/queue-3.12/virtio_net-fix-error-handling-for-mergeable-buffers.patch b/queue-3.12/virtio_net-fix-error-handling-for-mergeable-buffers.patch new file mode 100644 index 00000000000..9fcbb9c95a6 --- /dev/null +++ b/queue-3.12/virtio_net-fix-error-handling-for-mergeable-buffers.patch @@ -0,0 +1,132 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: "Michael S. Tsirkin" +Date: Thu, 26 Dec 2013 15:32:47 +0200 +Subject: virtio_net: fix error handling for mergeable buffers + +From: "Michael S. Tsirkin" + +Eric Dumazet noticed that if we encounter an error +when processing a mergeable buffer, we don't +dequeue all of the buffers from this packet, +the result is almost sure to be loss of networking. + +Fix this issue. + +Cc: Rusty Russell +Cc: Michael Dalton +Acked-by: Michael Dalton +Cc: Eric Dumazet +Cc: Jason Wang +Cc: David S. Miller + +Signed-off-by: Michael S. Tsirkin + +(cherry picked from commit 8fc3b9e9a229778e5af3aa453c44f1a3857ba769) +Acked-by: Jason Wang +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/virtio_net.c | 66 ++++++++++++++++++++++++++++++++--------------- + 1 file changed, 46 insertions(+), 20 deletions(-) + +--- a/drivers/net/virtio_net.c ++++ b/drivers/net/virtio_net.c +@@ -297,26 +297,33 @@ static struct sk_buff *page_to_skb(struc + return skb; + } + +-static int receive_mergeable(struct receive_queue *rq, struct sk_buff *skb) ++static struct sk_buff *receive_mergeable(struct net_device *dev, ++ struct receive_queue *rq, ++ void *buf, ++ unsigned int len) + { +- struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb); +- struct page *page; +- int num_buf, i, len; ++ struct skb_vnet_hdr *hdr = page_address(buf); ++ int num_buf = hdr->mhdr.num_buffers; ++ struct page *page = buf; ++ struct sk_buff *skb = page_to_skb(rq, page, len); ++ int i; ++ ++ if (unlikely(!skb)) ++ goto err_skb; + +- num_buf = hdr->mhdr.num_buffers; + while (--num_buf) { + i = skb_shinfo(skb)->nr_frags; + if (i >= MAX_SKB_FRAGS) { + pr_debug("%s: packet too long\n", skb->dev->name); + skb->dev->stats.rx_length_errors++; +- return -EINVAL; ++ return NULL; + } + page = virtqueue_get_buf(rq->vq, &len); + if (!page) { +- pr_debug("%s: rx error: %d buffers missing\n", +- skb->dev->name, hdr->mhdr.num_buffers); +- skb->dev->stats.rx_length_errors++; +- return -EINVAL; ++ pr_debug("%s: rx error: %d buffers %d missing\n", ++ dev->name, hdr->mhdr.num_buffers, num_buf); ++ dev->stats.rx_length_errors++; ++ goto err_buf; + } + + if (len > PAGE_SIZE) +@@ -326,7 +333,25 @@ static int receive_mergeable(struct rece + + --rq->num; + } +- return 0; ++ return skb; ++err_skb: ++ give_pages(rq, page); ++ while (--num_buf) { ++ buf = virtqueue_get_buf(rq->vq, &len); ++ if (unlikely(!buf)) { ++ pr_debug("%s: rx error: %d buffers missing\n", ++ dev->name, num_buf); ++ dev->stats.rx_length_errors++; ++ break; ++ } ++ page = buf; ++ give_pages(rq, page); ++ --rq->num; ++ } ++err_buf: ++ dev->stats.rx_dropped++; ++ dev_kfree_skb(skb); ++ return NULL; + } + + static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len) +@@ -354,17 +379,18 @@ static void receive_buf(struct receive_q + skb_trim(skb, len); + } else { + page = buf; +- skb = page_to_skb(rq, page, len); +- if (unlikely(!skb)) { +- dev->stats.rx_dropped++; +- give_pages(rq, page); +- return; +- } +- if (vi->mergeable_rx_bufs) +- if (receive_mergeable(rq, skb)) { +- dev_kfree_skb(skb); ++ if (vi->mergeable_rx_bufs) { ++ skb = receive_mergeable(dev, rq, page, len); ++ if (unlikely(!skb)) ++ return; ++ } else { ++ skb = page_to_skb(rq, page, len); ++ if (unlikely(!skb)) { ++ dev->stats.rx_dropped++; ++ give_pages(rq, page); + return; + } ++ } + } + + hdr = skb_vnet_hdr(skb); diff --git a/queue-3.12/vlan-fix-header-ops-passthru-when-doing-tx-vlan-offload.patch b/queue-3.12/vlan-fix-header-ops-passthru-when-doing-tx-vlan-offload.patch new file mode 100644 index 00000000000..e6e40bce629 --- /dev/null +++ b/queue-3.12/vlan-fix-header-ops-passthru-when-doing-tx-vlan-offload.patch @@ -0,0 +1,105 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: "David S. Miller" +Date: Tue, 31 Dec 2013 16:23:35 -0500 +Subject: vlan: Fix header ops passthru when doing TX VLAN offload. + +From: "David S. Miller" + +[ Upstream commit 2205369a314e12fcec4781cc73ac9c08fc2b47de ] + +When the vlan code detects that the real device can do TX VLAN offloads +in hardware, it tries to arrange for the real device's header_ops to +be invoked directly. + +But it does so illegally, by simply hooking the real device's +header_ops up to the VLAN device. + +This doesn't work because we will end up invoking a set of header_ops +routines which expect a device type which matches the real device, but +will see a VLAN device instead. + +Fix this by providing a pass-thru set of header_ops which will arrange +to pass the proper real device instead. + +To facilitate this add a dev_rebuild_header(). There are +implementations which provide a ->cache and ->create but not a +->rebuild (f.e. PLIP). So we need a helper function just like +dev_hard_header() to avoid crashes. + +Use this helper in the one existing place where the +header_ops->rebuild was being invoked, the neighbour code. + +With lots of help from Florian Westphal. + +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/netdevice.h | 9 +++++++++ + net/8021q/vlan_dev.c | 19 ++++++++++++++++++- + net/core/neighbour.c | 2 +- + 3 files changed, 28 insertions(+), 2 deletions(-) + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -1872,6 +1872,15 @@ static inline int dev_parse_header(const + return dev->header_ops->parse(skb, haddr); + } + ++static inline int dev_rebuild_header(struct sk_buff *skb) ++{ ++ const struct net_device *dev = skb->dev; ++ ++ if (!dev->header_ops || !dev->header_ops->rebuild) ++ return 0; ++ return dev->header_ops->rebuild(skb); ++} ++ + typedef int gifconf_func_t(struct net_device * dev, char __user * bufptr, int len); + extern int register_gifconf(unsigned int family, gifconf_func_t * gifconf); + static inline int unregister_gifconf(unsigned int family) +--- a/net/8021q/vlan_dev.c ++++ b/net/8021q/vlan_dev.c +@@ -549,6 +549,23 @@ static const struct header_ops vlan_head + .parse = eth_header_parse, + }; + ++static int vlan_passthru_hard_header(struct sk_buff *skb, struct net_device *dev, ++ unsigned short type, ++ const void *daddr, const void *saddr, ++ unsigned int len) ++{ ++ struct vlan_dev_priv *vlan = vlan_dev_priv(dev); ++ struct net_device *real_dev = vlan->real_dev; ++ ++ return dev_hard_header(skb, real_dev, type, daddr, saddr, len); ++} ++ ++static const struct header_ops vlan_passthru_header_ops = { ++ .create = vlan_passthru_hard_header, ++ .rebuild = dev_rebuild_header, ++ .parse = eth_header_parse, ++}; ++ + static struct device_type vlan_type = { + .name = "vlan", + }; +@@ -592,7 +609,7 @@ static int vlan_dev_init(struct net_devi + + dev->needed_headroom = real_dev->needed_headroom; + if (real_dev->features & NETIF_F_HW_VLAN_CTAG_TX) { +- dev->header_ops = real_dev->header_ops; ++ dev->header_ops = &vlan_passthru_header_ops; + dev->hard_header_len = real_dev->hard_header_len; + } else { + dev->header_ops = &vlan_header_ops; +--- a/net/core/neighbour.c ++++ b/net/core/neighbour.c +@@ -1274,7 +1274,7 @@ int neigh_compat_output(struct neighbour + + if (dev_hard_header(skb, dev, ntohs(skb->protocol), NULL, NULL, + skb->len) < 0 && +- dev->header_ops->rebuild(skb)) ++ dev_rebuild_header(skb)) + return 0; + + return dev_queue_xmit(skb); diff --git a/queue-3.12/vxlan-release-rt-when-found-circular-route.patch b/queue-3.12/vxlan-release-rt-when-found-circular-route.patch new file mode 100644 index 00000000000..9d6964d4e95 --- /dev/null +++ b/queue-3.12/vxlan-release-rt-when-found-circular-route.patch @@ -0,0 +1,32 @@ +From foo@baz Mon Jan 13 09:44:41 PST 2014 +From: Fan Du +Date: Mon, 9 Dec 2013 10:33:53 +0800 +Subject: vxlan: release rt when found circular route + +From: Fan Du + +[ Upstream commit fffc15a5012e9052d3b236efc56840841a125416 ] + +Otherwise causing dst memory leakage. +Have Checked all other type tunnel device transmit implementation, +no such things happens anymore. + +Signed-off-by: Fan Du +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/vxlan.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/vxlan.c ++++ b/drivers/net/vxlan.c +@@ -1672,7 +1672,7 @@ static void vxlan_xmit_one(struct sk_buf + netdev_dbg(dev, "circular route to %pI4\n", + &dst->sin.sin_addr.s_addr); + dev->stats.collisions++; +- goto tx_error; ++ goto rt_tx_error; + } + + /* Bypass encapsulation if the destination is local */