From ee9911081bcd22a97e46c3b3bf9438343a3259bd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 22 Oct 2015 18:28:53 -0700 Subject: [PATCH] 3.10-stable patches added patches: af_unix-convert-the-unix_sk-macro-to-an-inline-function-for-type-safety.patch af_unix-return-data-from-multiple-skbs-on-recv-with-msg_peek-flag.patch asix-do-full-reset-during-ax88772_bind.patch asix-don-t-reset-phy-on-if_up-for-asix-88772.patch ethtool-use-kcalloc-instead-of-kmalloc-for-ethtool_get_strings.patch l2tp-protect-tunnel-del_work-by-ref_count.patch net-add-pfmemalloc-check-in-sk_add_backlog.patch ppp-don-t-override-sk-sk_state-in-pppoe_flush_dev.patch skbuff-fix-skb-checksum-flag-on-skb-pull.patch skbuff-fix-skb-checksum-partial-check.patch --- ...o-an-inline-function-for-type-safety.patch | 35 +++++++++ ...iple-skbs-on-recv-with-msg_peek-flag.patch | 59 ++++++++++++++ ...ix-do-full-reset-during-ax88772_bind.patch | 56 ++++++++++++++ ...-t-reset-phy-on-if_up-for-asix-88772.patch | 38 ++++++++++ ...d-of-kmalloc-for-ethtool_get_strings.patch | 33 ++++++++ ...protect-tunnel-del_work-by-ref_count.patch | 55 ++++++++++++++ ...d-pfmemalloc-check-in-sk_add_backlog.patch | 49 ++++++++++++ ...rride-sk-sk_state-in-pppoe_flush_dev.patch | 76 +++++++++++++++++++ ...ff-fix-skb-checksum-flag-on-skb-pull.patch | 68 +++++++++++++++++ ...kbuff-fix-skb-checksum-partial-check.patch | 58 ++++++++++++++ 10 files changed, 527 insertions(+) create mode 100644 queue-3.10/af_unix-convert-the-unix_sk-macro-to-an-inline-function-for-type-safety.patch create mode 100644 queue-3.10/af_unix-return-data-from-multiple-skbs-on-recv-with-msg_peek-flag.patch create mode 100644 queue-3.10/asix-do-full-reset-during-ax88772_bind.patch create mode 100644 queue-3.10/asix-don-t-reset-phy-on-if_up-for-asix-88772.patch create mode 100644 queue-3.10/ethtool-use-kcalloc-instead-of-kmalloc-for-ethtool_get_strings.patch create mode 100644 queue-3.10/l2tp-protect-tunnel-del_work-by-ref_count.patch create mode 100644 queue-3.10/net-add-pfmemalloc-check-in-sk_add_backlog.patch create mode 100644 queue-3.10/ppp-don-t-override-sk-sk_state-in-pppoe_flush_dev.patch create mode 100644 queue-3.10/skbuff-fix-skb-checksum-flag-on-skb-pull.patch create mode 100644 queue-3.10/skbuff-fix-skb-checksum-partial-check.patch diff --git a/queue-3.10/af_unix-convert-the-unix_sk-macro-to-an-inline-function-for-type-safety.patch b/queue-3.10/af_unix-convert-the-unix_sk-macro-to-an-inline-function-for-type-safety.patch new file mode 100644 index 00000000000..14406323061 --- /dev/null +++ b/queue-3.10/af_unix-convert-the-unix_sk-macro-to-an-inline-function-for-type-safety.patch @@ -0,0 +1,35 @@ +From foo@baz Thu Oct 22 17:26:08 PDT 2015 +From: Aaron Conole +Date: Sat, 26 Sep 2015 18:50:42 -0400 +Subject: af_unix: Convert the unix_sk macro to an inline function for type safety + +From: Aaron Conole + +[ Upstream commit 4613012db1d911f80897f9446a49de817b2c4c47 ] + +As suggested by Eric Dumazet this change replaces the +#define with a static inline function to enjoy +complaints by the compiler when misusing the API. + +Signed-off-by: Aaron Conole +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/net/af_unix.h | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/include/net/af_unix.h ++++ b/include/net/af_unix.h +@@ -63,7 +63,11 @@ struct unix_sock { + #define UNIX_GC_MAYBE_CYCLE 1 + struct socket_wq peer_wq; + }; +-#define unix_sk(__sk) ((struct unix_sock *)__sk) ++ ++static inline struct unix_sock *unix_sk(struct sock *sk) ++{ ++ return (struct unix_sock *)sk; ++} + + #define peer_wait peer_wq.wait + diff --git a/queue-3.10/af_unix-return-data-from-multiple-skbs-on-recv-with-msg_peek-flag.patch b/queue-3.10/af_unix-return-data-from-multiple-skbs-on-recv-with-msg_peek-flag.patch new file mode 100644 index 00000000000..c72dcb180d4 --- /dev/null +++ b/queue-3.10/af_unix-return-data-from-multiple-skbs-on-recv-with-msg_peek-flag.patch @@ -0,0 +1,59 @@ +From foo@baz Thu Oct 22 17:26:08 PDT 2015 +From: Aaron Conole +Date: Sat, 26 Sep 2015 18:50:43 -0400 +Subject: af_unix: return data from multiple SKBs on recv() with MSG_PEEK flag + +From: Aaron Conole + +[ Upstream commit 9f389e35674f5b086edd70ed524ca0f287259725 ] + +AF_UNIX sockets now return multiple skbs from recv() when MSG_PEEK flag +is set. + +This is referenced in kernel bugzilla #12323 @ +https://bugzilla.kernel.org/show_bug.cgi?id=12323 + +As described both in the BZ and lkml thread @ +http://lkml.org/lkml/2008/1/8/444 calling recv() with MSG_PEEK on an +AF_UNIX socket only reads a single skb, where the desired effect is +to return as much skb data has been queued, until hitting the recv +buffer size (whichever comes first). + +The modified MSG_PEEK path will now move to the next skb in the tree +and jump to the again: label, rather than following the natural loop +structure. This requires duplicating some of the loop head actions. + +This was tested using the python socketpair python code attached to +the bugzilla issue. + +Signed-off-by: Aaron Conole +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/unix/af_unix.c | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -2063,8 +2063,20 @@ again: + if (UNIXCB(skb).fp) + siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp); + +- sk_peek_offset_fwd(sk, chunk); ++ if (skip) { ++ sk_peek_offset_fwd(sk, chunk); ++ skip -= chunk; ++ } + ++ if (UNIXCB(skb).fp) ++ break; ++ ++ last = skb; ++ unix_state_lock(sk); ++ skb = skb_peek_next(skb, &sk->sk_receive_queue); ++ if (skb) ++ goto again; ++ unix_state_unlock(sk); + break; + } + } while (size); diff --git a/queue-3.10/asix-do-full-reset-during-ax88772_bind.patch b/queue-3.10/asix-do-full-reset-during-ax88772_bind.patch new file mode 100644 index 00000000000..ae12b1e1f29 --- /dev/null +++ b/queue-3.10/asix-do-full-reset-during-ax88772_bind.patch @@ -0,0 +1,56 @@ +From foo@baz Thu Oct 22 17:26:08 PDT 2015 +From: Charles Keepax +Date: Thu, 6 Nov 2014 15:49:41 +0000 +Subject: asix: Do full reset during ax88772_bind + +From: Charles Keepax + +[ Upstream commit 436c2a5036b6ffe813310df2cf327d3b69be0734 ] + +commit 3cc81d85ee01 ("asix: Don't reset PHY on if_up for ASIX 88772") +causes the ethernet on Arndale to no longer function. This appears to +be because the Arndale ethernet requires a full reset before it will +function correctly, however simply reverting the above patch causes +problems with ethtool settings getting reset. + +It seems the problem is that the ethernet is not properly reset during +bind, and indeed the code in ax88772_bind that resets the device is a +very small subset of the actual ax88772_reset function. This patch uses +ax88772_reset in place of the existing reset code in ax88772_bind which +removes some code duplication and fixes the ethernet on Arndale. + +It is still possible that the original patch causes some issues with +suspend and resume but that seems like a separate issue and I haven't +had a chance to test that yet. + +Signed-off-by: Charles Keepax +Tested-by: Riku Voipio +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/usb/asix_devices.c | 14 +------------- + 1 file changed, 1 insertion(+), 13 deletions(-) + +--- a/drivers/net/usb/asix_devices.c ++++ b/drivers/net/usb/asix_devices.c +@@ -466,19 +466,7 @@ static int ax88772_bind(struct usbnet *d + return ret; + } + +- ret = asix_sw_reset(dev, AX_SWRESET_IPPD | AX_SWRESET_PRL); +- if (ret < 0) +- return ret; +- +- msleep(150); +- +- ret = asix_sw_reset(dev, AX_SWRESET_CLEAR); +- if (ret < 0) +- return ret; +- +- msleep(150); +- +- ret = asix_sw_reset(dev, embd_phy ? AX_SWRESET_IPRL : AX_SWRESET_PRTE); ++ ax88772_reset(dev); + + /* Read PHYID register *AFTER* the PHY was reset properly */ + phyid = asix_get_phyid(dev); diff --git a/queue-3.10/asix-don-t-reset-phy-on-if_up-for-asix-88772.patch b/queue-3.10/asix-don-t-reset-phy-on-if_up-for-asix-88772.patch new file mode 100644 index 00000000000..7666f2d3fee --- /dev/null +++ b/queue-3.10/asix-don-t-reset-phy-on-if_up-for-asix-88772.patch @@ -0,0 +1,38 @@ +From foo@baz Thu Oct 22 17:26:08 PDT 2015 +From: Michel Stam +Date: Thu, 2 Oct 2014 10:22:02 +0200 +Subject: asix: Don't reset PHY on if_up for ASIX 88772 + +From: Michel Stam + +[ Upstream commit 3cc81d85ee01e5a0b7ea2f4190e2ed1165f53c31 ] + +I've noticed every time the interface is set to 'up,', the kernel +reports that the link speed is set to 100 Mbps/Full Duplex, even +when ethtool is used to set autonegotiation to 'off', half +duplex, 10 Mbps. +It can be tested by: + ifconfig eth0 down + ethtool -s eth0 autoneg off speed 10 duplex half + ifconfig eth0 up + +Then checking 'dmesg' for the link speed. + +Signed-off-by: Michel Stam +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/usb/asix_devices.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/usb/asix_devices.c ++++ b/drivers/net/usb/asix_devices.c +@@ -888,7 +888,7 @@ static const struct driver_info ax88772_ + .unbind = ax88772_unbind, + .status = asix_status, + .link_reset = ax88772_link_reset, +- .reset = ax88772_reset, ++ .reset = ax88772_link_reset, + .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | FLAG_MULTI_PACKET, + .rx_fixup = asix_rx_fixup_common, + .tx_fixup = asix_tx_fixup, diff --git a/queue-3.10/ethtool-use-kcalloc-instead-of-kmalloc-for-ethtool_get_strings.patch b/queue-3.10/ethtool-use-kcalloc-instead-of-kmalloc-for-ethtool_get_strings.patch new file mode 100644 index 00000000000..60e0bc648d9 --- /dev/null +++ b/queue-3.10/ethtool-use-kcalloc-instead-of-kmalloc-for-ethtool_get_strings.patch @@ -0,0 +1,33 @@ +From foo@baz Thu Oct 22 17:26:08 PDT 2015 +From: Joe Perches +Date: Wed, 14 Oct 2015 01:09:40 -0700 +Subject: ethtool: Use kcalloc instead of kmalloc for ethtool_get_strings + +From: Joe Perches + +[ Upstream commit 077cb37fcf6f00a45f375161200b5ee0cd4e937b ] + +It seems that kernel memory can leak into userspace by a +kmalloc, ethtool_get_strings, then copy_to_user sequence. + +Avoid this by using kcalloc to zero fill the copied buffer. + +Signed-off-by: Joe Perches +Acked-by: Ben Hutchings +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/core/ethtool.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/core/ethtool.c ++++ b/net/core/ethtool.c +@@ -1066,7 +1066,7 @@ static int ethtool_get_strings(struct ne + + gstrings.len = ret; + +- data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER); ++ data = kcalloc(gstrings.len, ETH_GSTRING_LEN, GFP_USER); + if (!data) + return -ENOMEM; + diff --git a/queue-3.10/l2tp-protect-tunnel-del_work-by-ref_count.patch b/queue-3.10/l2tp-protect-tunnel-del_work-by-ref_count.patch new file mode 100644 index 00000000000..b30c392c4a0 --- /dev/null +++ b/queue-3.10/l2tp-protect-tunnel-del_work-by-ref_count.patch @@ -0,0 +1,55 @@ +From foo@baz Thu Oct 22 17:26:08 PDT 2015 +From: Alexander Couzens +Date: Mon, 28 Sep 2015 11:32:42 +0200 +Subject: l2tp: protect tunnel->del_work by ref_count + +From: Alexander Couzens + +[ Upstream commit 06a15f51cf3618e32a73871ee6a547ef7fd902b5 ] + +There is a small chance that tunnel_free() is called before tunnel->del_work scheduled +resulting in a zero pointer dereference. + +Signed-off-by: Alexander Couzens +Acked-by: James Chapman +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/l2tp/l2tp_core.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/net/l2tp/l2tp_core.c ++++ b/net/l2tp/l2tp_core.c +@@ -1381,7 +1381,7 @@ static void l2tp_tunnel_del_work(struct + tunnel = container_of(work, struct l2tp_tunnel, del_work); + sk = l2tp_tunnel_sock_lookup(tunnel); + if (!sk) +- return; ++ goto out; + + sock = sk->sk_socket; + +@@ -1402,6 +1402,8 @@ static void l2tp_tunnel_del_work(struct + } + + l2tp_tunnel_sock_put(sk); ++out: ++ l2tp_tunnel_dec_refcount(tunnel); + } + + /* Create a socket for the tunnel, if one isn't set up by +@@ -1731,8 +1733,13 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_create); + */ + int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel) + { ++ l2tp_tunnel_inc_refcount(tunnel); + l2tp_tunnel_closeall(tunnel); +- return (false == queue_work(l2tp_wq, &tunnel->del_work)); ++ if (false == queue_work(l2tp_wq, &tunnel->del_work)) { ++ l2tp_tunnel_dec_refcount(tunnel); ++ return 1; ++ } ++ return 0; + } + EXPORT_SYMBOL_GPL(l2tp_tunnel_delete); + diff --git a/queue-3.10/net-add-pfmemalloc-check-in-sk_add_backlog.patch b/queue-3.10/net-add-pfmemalloc-check-in-sk_add_backlog.patch new file mode 100644 index 00000000000..ea08c1c5729 --- /dev/null +++ b/queue-3.10/net-add-pfmemalloc-check-in-sk_add_backlog.patch @@ -0,0 +1,49 @@ +From foo@baz Thu Oct 22 17:26:08 PDT 2015 +From: Eric Dumazet +Date: Tue, 29 Sep 2015 18:52:25 -0700 +Subject: net: add pfmemalloc check in sk_add_backlog() + +From: Eric Dumazet + +[ Upstream commit c7c49b8fde26b74277188bdc6c9dca38db6fa35b ] + +Greg reported crashes hitting the following check in __sk_backlog_rcv() + + BUG_ON(!sock_flag(sk, SOCK_MEMALLOC)); + +The pfmemalloc bit is currently checked in sk_filter(). + +This works correctly for TCP, because sk_filter() is ran in +tcp_v[46]_rcv() before hitting the prequeue or backlog checks. + +For UDP or other protocols, this does not work, because the sk_filter() +is ran from sock_queue_rcv_skb(), which might be called _after_ backlog +queuing if socket is owned by user by the time packet is processed by +softirq handler. + +Fixes: b4b9e35585089 ("netvm: set PF_MEMALLOC as appropriate during SKB processing") +Signed-off-by: Eric Dumazet +Reported-by: Greg Thelen +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/net/sock.h | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -782,6 +782,14 @@ static inline __must_check int sk_add_ba + if (sk_rcvqueues_full(sk, skb, limit)) + return -ENOBUFS; + ++ /* ++ * If the skb was allocated from pfmemalloc reserves, only ++ * allow SOCK_MEMALLOC sockets to use it as this socket is ++ * helping free memory ++ */ ++ if (skb_pfmemalloc(skb) && !sock_flag(sk, SOCK_MEMALLOC)) ++ return -ENOMEM; ++ + __sk_add_backlog(sk, skb); + sk->sk_backlog.len += skb->truesize; + return 0; diff --git a/queue-3.10/ppp-don-t-override-sk-sk_state-in-pppoe_flush_dev.patch b/queue-3.10/ppp-don-t-override-sk-sk_state-in-pppoe_flush_dev.patch new file mode 100644 index 00000000000..cdf08ecd46b --- /dev/null +++ b/queue-3.10/ppp-don-t-override-sk-sk_state-in-pppoe_flush_dev.patch @@ -0,0 +1,76 @@ +From foo@baz Thu Oct 22 17:26:08 PDT 2015 +From: Guillaume Nault +Date: Wed, 30 Sep 2015 11:45:33 +0200 +Subject: ppp: don't override sk->sk_state in pppoe_flush_dev() + +From: Guillaume Nault + +[ Upstream commit e6740165b8f7f06d8caee0fceab3fb9d790a6fed ] + +Since commit 2b018d57ff18 ("pppoe: drop PPPOX_ZOMBIEs in pppoe_release"), +pppoe_release() calls dev_put(po->pppoe_dev) if sk is in the +PPPOX_ZOMBIE state. But pppoe_flush_dev() can set sk->sk_state to +PPPOX_ZOMBIE _and_ reset po->pppoe_dev to NULL. This leads to the +following oops: + +[ 570.140800] BUG: unable to handle kernel NULL pointer dereference at 00000000000004e0 +[ 570.142931] IP: [] pppoe_release+0x50/0x101 [pppoe] +[ 570.144601] PGD 3d119067 PUD 3dbc1067 PMD 0 +[ 570.144601] Oops: 0000 [#1] SMP +[ 570.144601] Modules linked in: l2tp_ppp l2tp_netlink l2tp_core ip6_udp_tunnel udp_tunnel pppoe pppox ppp_generic slhc loop crc32c_intel ghash_clmulni_intel jitterentropy_rng sha256_generic hmac drbg ansi_cprng aesni_intel aes_x86_64 ablk_helper cryptd lrw gf128mul glue_helper acpi_cpufreq evdev serio_raw processor button ext4 crc16 mbcache jbd2 virtio_net virtio_blk virtio_pci virtio_ring virtio +[ 570.144601] CPU: 1 PID: 15738 Comm: ppp-apitest Not tainted 4.2.0 #1 +[ 570.144601] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Debian-1.8.2-1 04/01/2014 +[ 570.144601] task: ffff88003d30d600 ti: ffff880036b60000 task.ti: ffff880036b60000 +[ 570.144601] RIP: 0010:[] [] pppoe_release+0x50/0x101 [pppoe] +[ 570.144601] RSP: 0018:ffff880036b63e08 EFLAGS: 00010202 +[ 570.144601] RAX: 0000000000000000 RBX: ffff880034340000 RCX: 0000000000000206 +[ 570.144601] RDX: 0000000000000006 RSI: ffff88003d30dd20 RDI: ffff88003d30dd20 +[ 570.144601] RBP: ffff880036b63e28 R08: 0000000000000001 R09: 0000000000000000 +[ 570.144601] R10: 00007ffee9b50420 R11: ffff880034340078 R12: ffff8800387ec780 +[ 570.144601] R13: ffff8800387ec7b0 R14: ffff88003e222aa0 R15: ffff8800387ec7b0 +[ 570.144601] FS: 00007f5672f48700(0000) GS:ffff88003fc80000(0000) knlGS:0000000000000000 +[ 570.144601] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 570.144601] CR2: 00000000000004e0 CR3: 0000000037f7e000 CR4: 00000000000406a0 +[ 570.144601] Stack: +[ 570.144601] ffffffffa018f240 ffff8800387ec780 ffffffffa018f240 ffff8800387ec7b0 +[ 570.144601] ffff880036b63e48 ffffffff812caabe ffff880039e4e000 0000000000000008 +[ 570.144601] ffff880036b63e58 ffffffff812cabad ffff880036b63ea8 ffffffff811347f5 +[ 570.144601] Call Trace: +[ 570.144601] [] sock_release+0x1a/0x75 +[ 570.144601] [] sock_close+0xd/0x11 +[ 570.144601] [] __fput+0xff/0x1a5 +[ 570.144601] [] ____fput+0x9/0xb +[ 570.144601] [] task_work_run+0x66/0x90 +[ 570.144601] [] prepare_exit_to_usermode+0x8c/0xa7 +[ 570.144601] [] syscall_return_slowpath+0x16d/0x19b +[ 570.144601] [] int_ret_from_sys_call+0x25/0x9f +[ 570.144601] Code: 48 8b 83 c8 01 00 00 a8 01 74 12 48 89 df e8 8b 27 14 e1 b8 f7 ff ff ff e9 b7 00 00 00 8a 43 12 a8 0b 74 1c 48 8b 83 a8 04 00 00 <48> 8b 80 e0 04 00 00 65 ff 08 48 c7 83 a8 04 00 00 00 00 00 00 +[ 570.144601] RIP [] pppoe_release+0x50/0x101 [pppoe] +[ 570.144601] RSP +[ 570.144601] CR2: 00000000000004e0 +[ 570.200518] ---[ end trace 46956baf17349563 ]--- + +pppoe_flush_dev() has no reason to override sk->sk_state with +PPPOX_ZOMBIE. pppox_unbind_sock() already sets sk->sk_state to +PPPOX_DEAD, which is the correct state given that sk is unbound and +po->pppoe_dev is NULL. + +Fixes: 2b018d57ff18 ("pppoe: drop PPPOX_ZOMBIEs in pppoe_release") +Tested-by: Oleksii Berezhniak +Signed-off-by: Guillaume Nault +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ppp/pppoe.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/net/ppp/pppoe.c ++++ b/drivers/net/ppp/pppoe.c +@@ -313,7 +313,6 @@ static void pppoe_flush_dev(struct net_d + if (po->pppoe_dev == dev && + sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) { + pppox_unbind_sock(sk); +- sk->sk_state = PPPOX_ZOMBIE; + sk->sk_state_change(sk); + po->pppoe_dev = NULL; + dev_put(dev); diff --git a/queue-3.10/skbuff-fix-skb-checksum-flag-on-skb-pull.patch b/queue-3.10/skbuff-fix-skb-checksum-flag-on-skb-pull.patch new file mode 100644 index 00000000000..d88a6762be3 --- /dev/null +++ b/queue-3.10/skbuff-fix-skb-checksum-flag-on-skb-pull.patch @@ -0,0 +1,68 @@ +From foo@baz Thu Oct 22 17:26:08 PDT 2015 +From: Pravin B Shelar +Date: Tue, 22 Sep 2015 12:57:53 -0700 +Subject: skbuff: Fix skb checksum flag on skb pull + +From: Pravin B Shelar + +[ Upstream commit 6ae459bdaaeebc632b16e54dcbabb490c6931d61 ] + +VXLAN device can receive skb with checksum partial. But the checksum +offset could be in outer header which is pulled on receive. This results +in negative checksum offset for the skb. Such skb can cause the assert +failure in skb_checksum_help(). Following patch fixes the bug by setting +checksum-none while pulling outer header. + +Following is the kernel panic msg from old kernel hitting the bug. + +------------[ cut here ]------------ +kernel BUG at net/core/dev.c:1906! +RIP: 0010:[] skb_checksum_help+0x144/0x150 +Call Trace: + +[] queue_userspace_packet+0x408/0x470 [openvswitch] +[] ovs_dp_upcall+0x5d/0x60 [openvswitch] +[] ovs_dp_process_packet_with_key+0xe6/0x100 [openvswitch] +[] ovs_dp_process_received_packet+0x4b/0x80 [openvswitch] +[] ovs_vport_receive+0x2a/0x30 [openvswitch] +[] vxlan_rcv+0x53/0x60 [openvswitch] +[] vxlan_udp_encap_recv+0x8b/0xf0 [openvswitch] +[] udp_queue_rcv_skb+0x2dc/0x3b0 +[] __udp4_lib_rcv+0x1cf/0x6c0 +[] udp_rcv+0x1a/0x20 +[] ip_local_deliver_finish+0xdd/0x280 +[] ip_local_deliver+0x88/0x90 +[] ip_rcv_finish+0x10d/0x370 +[] ip_rcv+0x235/0x300 +[] __netif_receive_skb+0x55d/0x620 +[] netif_receive_skb+0x80/0x90 +[] virtnet_poll+0x555/0x6f0 +[] net_rx_action+0x134/0x290 +[] __do_softirq+0xa8/0x210 +[] call_softirq+0x1c/0x30 +[] do_softirq+0x65/0xa0 +[] irq_exit+0x8e/0xb0 +[] do_IRQ+0x63/0xe0 +[] common_interrupt+0x6e/0x6e + +Reported-by: Anupam Chanda +Signed-off-by: Pravin B Shelar +Acked-by: Tom Herbert +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/skbuff.h | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -2363,6 +2363,9 @@ static inline void skb_postpull_rcsum(st + { + if (skb->ip_summed == CHECKSUM_COMPLETE) + skb->csum = csum_sub(skb->csum, csum_partial(start, len, 0)); ++ else if (skb->ip_summed == CHECKSUM_PARTIAL && ++ skb_checksum_start_offset(skb) <= len) ++ skb->ip_summed = CHECKSUM_NONE; + } + + unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len); diff --git a/queue-3.10/skbuff-fix-skb-checksum-partial-check.patch b/queue-3.10/skbuff-fix-skb-checksum-partial-check.patch new file mode 100644 index 00000000000..217e4ccac42 --- /dev/null +++ b/queue-3.10/skbuff-fix-skb-checksum-partial-check.patch @@ -0,0 +1,58 @@ +From foo@baz Thu Oct 22 17:26:08 PDT 2015 +From: Pravin B Shelar +Date: Mon, 28 Sep 2015 17:24:25 -0700 +Subject: skbuff: Fix skb checksum partial check. + +From: Pravin B Shelar + +[ Upstream commit 31b33dfb0a144469dd805514c9e63f4993729a48 ] + +Earlier patch 6ae459bda tried to detect void ckecksum partial +skb by comparing pull length to checksum offset. But it does +not work for all cases since checksum-offset depends on +updates to skb->data. + +Following patch fixes it by validating checksum start offset +after skb-data pointer is updated. Negative value of checksum +offset start means there is no need to checksum. + +Fixes: 6ae459bda ("skbuff: Fix skb checksum flag on skb pull") +Reported-by: Andrew Vagin +Signed-off-by: Pravin B Shelar +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/skbuff.h | 2 +- + net/core/skbuff.c | 9 +++++---- + 2 files changed, 6 insertions(+), 5 deletions(-) + +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -2364,7 +2364,7 @@ static inline void skb_postpull_rcsum(st + if (skb->ip_summed == CHECKSUM_COMPLETE) + skb->csum = csum_sub(skb->csum, csum_partial(start, len, 0)); + else if (skb->ip_summed == CHECKSUM_PARTIAL && +- skb_checksum_start_offset(skb) <= len) ++ skb_checksum_start_offset(skb) < 0) + skb->ip_summed = CHECKSUM_NONE; + } + +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -2711,11 +2711,12 @@ EXPORT_SYMBOL(skb_append_datato_frags); + */ + unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len) + { ++ unsigned char *data = skb->data; ++ + BUG_ON(len > skb->len); +- skb->len -= len; +- BUG_ON(skb->len < skb->data_len); +- skb_postpull_rcsum(skb, skb->data, len); +- return skb->data += len; ++ __skb_pull(skb, len); ++ skb_postpull_rcsum(skb, data, len); ++ return skb->data; + } + EXPORT_SYMBOL_GPL(skb_pull_rcsum); + -- 2.47.2