From 47e66b1ed0803d510e19d18d80f19e8e9a880472 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 3 Jun 2012 05:44:05 -0700 Subject: [PATCH] 3.0-stable patches added patches: ipv4-do-not-use-dead-fib_info-entries.patch ipv4-fix-the-rcu-race-between-free_fib_info-and-ip_route_output_slow.patch ipv6-fix-incorrect-ipsec-fragment.patch l2tp-fix-oops-in-l2tp-ip-sockets-for-connect-af_unspec-case.patch pktgen-fix-crash-at-module-unload.patch pktgen-fix-module-unload-for-good.patch revert-net-maintain-namespace-isolation-between-vlan-and-real-device.patch sctp-check-cached-dst-before-using-it.patch skb-avoid-unnecessary-reallocations-in-__skb_cow.patch xfrm-take-net-hdr-len-into-account-for-esp-payload-size-calculation.patch --- ...pv4-do-not-use-dead-fib_info-entries.patch | 34 ++++ ...ee_fib_info-and-ip_route_output_slow.patch | 97 ++++++++++ .../ipv6-fix-incorrect-ipsec-fragment.patch | 174 ++++++++++++++++++ ...p-sockets-for-connect-af_unspec-case.patch | 110 +++++++++++ .../pktgen-fix-crash-at-module-unload.patch | 70 +++++++ .../pktgen-fix-module-unload-for-good.patch | 46 +++++ ...olation-between-vlan-and-real-device.patch | 129 +++++++++++++ ...ctp-check-cached-dst-before-using-it.patch | 82 +++++++++ queue-3.0/series | 10 + ...necessary-reallocations-in-__skb_cow.patch | 40 ++++ ...unt-for-esp-payload-size-calculation.patch | 95 ++++++++++ 11 files changed, 887 insertions(+) create mode 100644 queue-3.0/ipv4-do-not-use-dead-fib_info-entries.patch create mode 100644 queue-3.0/ipv4-fix-the-rcu-race-between-free_fib_info-and-ip_route_output_slow.patch create mode 100644 queue-3.0/ipv6-fix-incorrect-ipsec-fragment.patch create mode 100644 queue-3.0/l2tp-fix-oops-in-l2tp-ip-sockets-for-connect-af_unspec-case.patch create mode 100644 queue-3.0/pktgen-fix-crash-at-module-unload.patch create mode 100644 queue-3.0/pktgen-fix-module-unload-for-good.patch create mode 100644 queue-3.0/revert-net-maintain-namespace-isolation-between-vlan-and-real-device.patch create mode 100644 queue-3.0/sctp-check-cached-dst-before-using-it.patch create mode 100644 queue-3.0/skb-avoid-unnecessary-reallocations-in-__skb_cow.patch create mode 100644 queue-3.0/xfrm-take-net-hdr-len-into-account-for-esp-payload-size-calculation.patch diff --git a/queue-3.0/ipv4-do-not-use-dead-fib_info-entries.patch b/queue-3.0/ipv4-do-not-use-dead-fib_info-entries.patch new file mode 100644 index 00000000000..0967f6b1c62 --- /dev/null +++ b/queue-3.0/ipv4-do-not-use-dead-fib_info-entries.patch @@ -0,0 +1,34 @@ +From ea50b667b36506c51cbc60361a68e0ef1c84d9dc Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Thu, 10 May 2012 22:16:32 -0400 +Subject: ipv4: Do not use dead fib_info entries. + + +From: "David S. Miller" + +[ Upstream commit dccd9ecc374462e5d6a5b8f8110415a86c2213d8 ] + +Due to RCU lookups and RCU based release, fib_info objects can +be found during lookup which have fi->fib_dead set. + +We must ignore these entries, otherwise we risk dereferencing +the parts of the entry which are being torn down. + +Reported-by: Yevgen Pronenko +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/fib_trie.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/ipv4/fib_trie.c ++++ b/net/ipv4/fib_trie.c +@@ -1371,6 +1371,8 @@ static int check_leaf(struct fib_table * + + if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos) + continue; ++ if (fi->fib_dead) ++ continue; + if (fa->fa_info->fib_scope < flp->flowi4_scope) + continue; + fib_alias_accessed(fa); diff --git a/queue-3.0/ipv4-fix-the-rcu-race-between-free_fib_info-and-ip_route_output_slow.patch b/queue-3.0/ipv4-fix-the-rcu-race-between-free_fib_info-and-ip_route_output_slow.patch new file mode 100644 index 00000000000..97e765e9985 --- /dev/null +++ b/queue-3.0/ipv4-fix-the-rcu-race-between-free_fib_info-and-ip_route_output_slow.patch @@ -0,0 +1,97 @@ +From b0b8cb5c6afab6a7783eb8005a6e2f677b002994 Mon Sep 17 00:00:00 2001 +From: Yanmin Zhang +Date: Wed, 23 May 2012 15:39:45 +0000 +Subject: ipv4: fix the rcu race between free_fib_info and ip_route_output_slow + + +From: Yanmin Zhang + +[ Upstream commit e49cc0da7283088c5e03d475ffe2fdcb24a6d5b1 ] + +We hit a kernel OOPS. + +<3>[23898.789643] BUG: sleeping function called from invalid context at +/data/buildbot/workdir/ics/hardware/intel/linux-2.6/arch/x86/mm/fault.c:1103 +<3>[23898.862215] in_atomic(): 0, irqs_disabled(): 0, pid: 10526, name: +Thread-6683 +<4>[23898.967805] HSU serial 0000:00:05.1: 0000:00:05.2:HSU serial prevented me +to suspend... +<4>[23899.258526] Pid: 10526, comm: Thread-6683 Tainted: G W +3.0.8-137685-ge7742f9 #1 +<4>[23899.357404] HSU serial 0000:00:05.1: 0000:00:05.2:HSU serial prevented me +to suspend... +<4>[23899.904225] Call Trace: +<4>[23899.989209] [] ? pgtable_bad+0x130/0x130 +<4>[23900.000416] [] __might_sleep+0x10a/0x110 +<4>[23900.007357] [] do_page_fault+0xd1/0x3c0 +<4>[23900.013764] [] ? restore_all+0xf/0xf +<4>[23900.024024] [] ? napi_complete+0x8b/0x690 +<4>[23900.029297] [] ? pgtable_bad+0x130/0x130 +<4>[23900.123739] [] ? pgtable_bad+0x130/0x130 +<4>[23900.128955] [] error_code+0x5f/0x64 +<4>[23900.133466] [] ? pgtable_bad+0x130/0x130 +<4>[23900.138450] [] ? __ip_route_output_key+0x698/0x7c0 +<4>[23900.144312] [] ? __ip_route_output_key+0x38d/0x7c0 +<4>[23900.150730] [] ip_route_output_flow+0x1f/0x60 +<4>[23900.156261] [] ip4_datagram_connect+0x188/0x2b0 +<4>[23900.161960] [] ? _raw_spin_unlock_bh+0x1f/0x30 +<4>[23900.167834] [] inet_dgram_connect+0x36/0x80 +<4>[23900.173224] [] ? _copy_from_user+0x48/0x140 +<4>[23900.178817] [] sys_connect+0x9a/0xd0 +<4>[23900.183538] [] ? alloc_file+0xdc/0x240 +<4>[23900.189111] [] ? sub_preempt_count+0x3d/0x50 + +Function free_fib_info resets nexthop_nh->nh_dev to NULL before releasing +fi. Other cpu might be accessing fi. Fixing it by delaying the releasing. + +With the patch, we ran MTBF testing on Android mobile for 12 hours +and didn't trigger the issue. + +Thank Eric for very detailed review/checking the issue. + +Signed-off-by: Yanmin Zhang +Signed-off-by: Kun Jiang +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/fib_semantics.c | 20 +++++++++++++------- + 1 file changed, 13 insertions(+), 7 deletions(-) + +--- a/net/ipv4/fib_semantics.c ++++ b/net/ipv4/fib_semantics.c +@@ -142,6 +142,18 @@ const struct fib_prop fib_props[RTN_MAX + }; + + /* Release a nexthop info record */ ++static void free_fib_info_rcu(struct rcu_head *head) ++{ ++ struct fib_info *fi = container_of(head, struct fib_info, rcu); ++ ++ change_nexthops(fi) { ++ if (nexthop_nh->nh_dev) ++ dev_put(nexthop_nh->nh_dev); ++ } endfor_nexthops(fi); ++ ++ release_net(fi->fib_net); ++ kfree(fi); ++} + + void free_fib_info(struct fib_info *fi) + { +@@ -149,14 +161,8 @@ void free_fib_info(struct fib_info *fi) + pr_warning("Freeing alive fib_info %p\n", fi); + return; + } +- change_nexthops(fi) { +- if (nexthop_nh->nh_dev) +- dev_put(nexthop_nh->nh_dev); +- nexthop_nh->nh_dev = NULL; +- } endfor_nexthops(fi); + fib_info_cnt--; +- release_net(fi->fib_net); +- kfree_rcu(fi, rcu); ++ call_rcu(&fi->rcu, free_fib_info_rcu); + } + + void fib_release_info(struct fib_info *fi) diff --git a/queue-3.0/ipv6-fix-incorrect-ipsec-fragment.patch b/queue-3.0/ipv6-fix-incorrect-ipsec-fragment.patch new file mode 100644 index 00000000000..d4ec54c793d --- /dev/null +++ b/queue-3.0/ipv6-fix-incorrect-ipsec-fragment.patch @@ -0,0 +1,174 @@ +From 3e03d3364f90cc792e81bbd60da606736209d3ee Mon Sep 17 00:00:00 2001 +From: Gao feng +Date: Sat, 26 May 2012 01:30:53 +0000 +Subject: ipv6: fix incorrect ipsec fragment + + +From: Gao feng + +[ Upstream commit 0c1833797a5a6ec23ea9261d979aa18078720b74 ] + +Since commit ad0081e43a +"ipv6: Fragment locally generated tunnel-mode IPSec6 packets as needed" +the fragment of packets is incorrect. +because tunnel mode needs IPsec headers and trailer for all fragments, +while on transport mode it is sufficient to add the headers to the +first fragment and the trailer to the last. + +so modify mtu and maxfraglen base on ipsec mode and if fragment is first +or last. + +with my test,it work well(every fragment's size is the mtu) +and does not trigger slow fragment path. + +Changes from v1: + though optimization, mtu_prev and maxfraglen_prev can be delete. + replace xfrm mode codes with dst_entry's new frag DST_XFRM_TUNNEL. + add fuction ip6_append_data_mtu to make codes clearer. + +Signed-off-by: Gao feng +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/net/dst.h | 1 + net/ipv6/ip6_output.c | 68 ++++++++++++++++++++++++++++++++++++------------- + net/xfrm/xfrm_policy.c | 3 ++ + 3 files changed, 54 insertions(+), 18 deletions(-) + +--- a/include/net/dst.h ++++ b/include/net/dst.h +@@ -78,6 +78,7 @@ struct dst_entry { + #define DST_NOHASH 0x0008 + #define DST_NOCACHE 0x0010 + #define DST_NOCOUNT 0x0020 ++#define DST_XFRM_TUNNEL 0x0100 + union { + struct dst_entry *next; + struct rtable __rcu *rt_next; +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1194,6 +1194,29 @@ static inline struct ipv6_rt_hdr *ip6_rt + return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL; + } + ++static void ip6_append_data_mtu(int *mtu, ++ int *maxfraglen, ++ unsigned int fragheaderlen, ++ struct sk_buff *skb, ++ struct rt6_info *rt) ++{ ++ if (!(rt->dst.flags & DST_XFRM_TUNNEL)) { ++ if (skb == NULL) { ++ /* first fragment, reserve header_len */ ++ *mtu = *mtu - rt->dst.header_len; ++ ++ } else { ++ /* ++ * this fragment is not first, the headers ++ * space is regarded as data space. ++ */ ++ *mtu = dst_mtu(rt->dst.path); ++ } ++ *maxfraglen = ((*mtu - fragheaderlen) & ~7) ++ + fragheaderlen - sizeof(struct frag_hdr); ++ } ++} ++ + int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, + int offset, int len, int odd, struct sk_buff *skb), + void *from, int length, int transhdrlen, +@@ -1203,7 +1226,7 @@ int ip6_append_data(struct sock *sk, int + struct inet_sock *inet = inet_sk(sk); + struct ipv6_pinfo *np = inet6_sk(sk); + struct inet_cork *cork; +- struct sk_buff *skb; ++ struct sk_buff *skb, *skb_prev = NULL; + unsigned int maxfraglen, fragheaderlen; + int exthdrlen; + int hh_len; +@@ -1260,8 +1283,12 @@ int ip6_append_data(struct sock *sk, int + inet->cork.fl.u.ip6 = *fl6; + np->cork.hop_limit = hlimit; + np->cork.tclass = tclass; +- mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? +- rt->dst.dev->mtu : dst_mtu(rt->dst.path); ++ if (rt->dst.flags & DST_XFRM_TUNNEL) ++ mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? ++ rt->dst.dev->mtu : dst_mtu(&rt->dst); ++ else ++ mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? ++ rt->dst.dev->mtu : dst_mtu(rt->dst.path); + if (np->frag_size < mtu) { + if (np->frag_size) + mtu = np->frag_size; +@@ -1356,38 +1383,43 @@ int ip6_append_data(struct sock *sk, int + unsigned int fraglen; + unsigned int fraggap; + unsigned int alloclen; +- struct sk_buff *skb_prev; + alloc_new_skb: +- skb_prev = skb; +- + /* There's no room in the current skb */ +- if (skb_prev) +- fraggap = skb_prev->len - maxfraglen; ++ if (skb) ++ fraggap = skb->len - maxfraglen; + else + fraggap = 0; ++ /* update mtu and maxfraglen if necessary */ ++ if (skb == NULL || skb_prev == NULL) ++ ip6_append_data_mtu(&mtu, &maxfraglen, ++ fragheaderlen, skb, rt); ++ ++ skb_prev = skb; + + /* + * If remaining data exceeds the mtu, + * we know we need more fragment(s). + */ + datalen = length + fraggap; +- if (datalen > (cork->length <= mtu && !(cork->flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - fragheaderlen) +- datalen = maxfraglen - fragheaderlen; + +- fraglen = datalen + fragheaderlen; ++ if (datalen > (cork->length <= mtu && !(cork->flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - fragheaderlen) ++ datalen = maxfraglen - fragheaderlen - rt->dst.trailer_len; + if ((flags & MSG_MORE) && + !(rt->dst.dev->features&NETIF_F_SG)) + alloclen = mtu; + else + alloclen = datalen + fragheaderlen; + +- /* +- * The last fragment gets additional space at tail. +- * Note: we overallocate on fragments with MSG_MODE +- * because we have no idea if we're the last one. +- */ +- if (datalen == length + fraggap) +- alloclen += rt->dst.trailer_len; ++ if (datalen != length + fraggap) { ++ /* ++ * this is not the last fragment, the trailer ++ * space is regarded as data space. ++ */ ++ datalen += rt->dst.trailer_len; ++ } ++ ++ alloclen += rt->dst.trailer_len; ++ fraglen = datalen + fragheaderlen; + + /* + * We just reserve space for fragment header. +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -1917,6 +1917,9 @@ no_transform: + } + ok: + xfrm_pols_put(pols, drop_pols); ++ if (dst && dst->xfrm && ++ dst->xfrm->props.mode == XFRM_MODE_TUNNEL) ++ dst->flags |= DST_XFRM_TUNNEL; + return dst; + + nopol: diff --git a/queue-3.0/l2tp-fix-oops-in-l2tp-ip-sockets-for-connect-af_unspec-case.patch b/queue-3.0/l2tp-fix-oops-in-l2tp-ip-sockets-for-connect-af_unspec-case.patch new file mode 100644 index 00000000000..5cc5bd07e12 --- /dev/null +++ b/queue-3.0/l2tp-fix-oops-in-l2tp-ip-sockets-for-connect-af_unspec-case.patch @@ -0,0 +1,110 @@ +From fa234d2b07ed72b503ff55446fbfaea475d06fa2 Mon Sep 17 00:00:00 2001 +From: James Chapman +Date: Tue, 29 May 2012 23:13:23 +0000 +Subject: l2tp: fix oops in L2TP IP sockets for connect() AF_UNSPEC case + + +From: James Chapman + +[ Upstream commit c51ce49735c183ef2592db70f918ee698716276b ] + +An application may call connect() to disconnect a socket using an +address with family AF_UNSPEC. The L2TP IP sockets were not handling +this case when the socket is not bound and an attempt to connect() +using AF_UNSPEC in such cases would result in an oops. This patch +addresses the problem by protecting the sk_prot->disconnect() call +against trying to unhash the socket before it is bound. + +The patch also adds more checks that the sockaddr supplied to bind() +and connect() calls is valid. + + RIP: 0010:[] [] inet_unhash+0x50/0xd0 + RSP: 0018:ffff88001989be28 EFLAGS: 00010293 + Stack: + ffff8800407a8000 0000000000000000 ffff88001989be78 ffffffff82e3a249 + ffffffff82e3a050 ffff88001989bec8 ffff88001989be88 ffff8800407a8000 + 0000000000000010 ffff88001989bec8 ffff88001989bea8 ffffffff82e42639 + Call Trace: + [] udp_disconnect+0x1f9/0x290 + [] inet_dgram_connect+0x29/0x80 + [] sys_connect+0x9c/0x100 + +Reported-by: Sasha Levin +Signed-off-by: James Chapman +Signed-off-by: Greg Kroah-Hartman +--- + net/l2tp/l2tp_ip.c | 30 ++++++++++++++++++++++++------ + 1 file changed, 24 insertions(+), 6 deletions(-) + +--- a/net/l2tp/l2tp_ip.c ++++ b/net/l2tp/l2tp_ip.c +@@ -251,9 +251,16 @@ static int l2tp_ip_bind(struct sock *sk, + { + struct inet_sock *inet = inet_sk(sk); + struct sockaddr_l2tpip *addr = (struct sockaddr_l2tpip *) uaddr; +- int ret = -EINVAL; ++ int ret; + int chk_addr_ret; + ++ if (!sock_flag(sk, SOCK_ZAPPED)) ++ return -EINVAL; ++ if (addr_len < sizeof(struct sockaddr_l2tpip)) ++ return -EINVAL; ++ if (addr->l2tp_family != AF_INET) ++ return -EINVAL; ++ + ret = -EADDRINUSE; + read_lock_bh(&l2tp_ip_lock); + if (__l2tp_ip_bind_lookup(&init_net, addr->l2tp_addr.s_addr, sk->sk_bound_dev_if, addr->l2tp_conn_id)) +@@ -283,6 +290,8 @@ static int l2tp_ip_bind(struct sock *sk, + sk_del_node_init(sk); + write_unlock_bh(&l2tp_ip_lock); + ret = 0; ++ sock_reset_flag(sk, SOCK_ZAPPED); ++ + out: + release_sock(sk); + +@@ -303,13 +312,14 @@ static int l2tp_ip_connect(struct sock * + __be32 saddr; + int oif, rc; + +- rc = -EINVAL; ++ if (sock_flag(sk, SOCK_ZAPPED)) /* Must bind first - autobinding does not work */ ++ return -EINVAL; ++ + if (addr_len < sizeof(*lsa)) +- goto out; ++ return -EINVAL; + +- rc = -EAFNOSUPPORT; + if (lsa->l2tp_family != AF_INET) +- goto out; ++ return -EAFNOSUPPORT; + + lock_sock(sk); + +@@ -363,6 +373,14 @@ out: + return rc; + } + ++static int l2tp_ip_disconnect(struct sock *sk, int flags) ++{ ++ if (sock_flag(sk, SOCK_ZAPPED)) ++ return 0; ++ ++ return udp_disconnect(sk, flags); ++} ++ + static int l2tp_ip_getname(struct socket *sock, struct sockaddr *uaddr, + int *uaddr_len, int peer) + { +@@ -591,7 +609,7 @@ static struct proto l2tp_ip_prot = { + .close = l2tp_ip_close, + .bind = l2tp_ip_bind, + .connect = l2tp_ip_connect, +- .disconnect = udp_disconnect, ++ .disconnect = l2tp_ip_disconnect, + .ioctl = udp_ioctl, + .destroy = l2tp_ip_destroy_sock, + .setsockopt = ip_setsockopt, diff --git a/queue-3.0/pktgen-fix-crash-at-module-unload.patch b/queue-3.0/pktgen-fix-crash-at-module-unload.patch new file mode 100644 index 00000000000..fee4c883fa0 --- /dev/null +++ b/queue-3.0/pktgen-fix-crash-at-module-unload.patch @@ -0,0 +1,70 @@ +From e36258658f4efc6c8a160839d0f7d3c987c10f7f Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 9 May 2012 13:29:51 +0000 +Subject: pktgen: fix crash at module unload + + +From: Eric Dumazet + +[ Upstream commit c57b54684060c8aced64a5b78ff69ff289af97b9 ] + +commit 7d3d43dab4e9 (net: In unregister_netdevice_notifier unregister +the netdevices.) makes pktgen crashing at module unload. + +[ 296.820578] BUG: spinlock bad magic on CPU#6, rmmod/3267 +[ 296.820719] lock: ffff880310c38000, .magic: ffff8803, .owner: /-1, .owner_cpu: -1 +[ 296.820943] Pid: 3267, comm: rmmod Not tainted 3.4.0-rc5+ #254 +[ 296.821079] Call Trace: +[ 296.821211] [] spin_dump+0x8a/0x8f +[ 296.821345] [] spin_bug+0x21/0x26 +[ 296.821507] [] do_raw_spin_lock+0x131/0x140 +[ 296.821648] [] _raw_spin_lock+0x1e/0x20 +[ 296.821786] [] __pktgen_NN_threads+0x4d/0x140 [pktgen] +[ 296.821928] [] pktgen_device_event+0x10d/0x1e0 [pktgen] +[ 296.822073] [] unregister_netdevice_notifier+0x7f/0x100 +[ 296.822216] [] pg_cleanup+0x48/0x73 [pktgen] +[ 296.822357] [] sys_delete_module+0x17e/0x2a0 +[ 296.822502] [] system_call_fastpath+0x16/0x1b + +Hold the pktgen_thread_lock while splicing pktgen_threads, and test +pktgen_exiting in pktgen_device_event() to make unload faster. + +Signed-off-by: Eric Dumazet +Cc: Eric W. Biederman +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/core/pktgen.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +--- a/net/core/pktgen.c ++++ b/net/core/pktgen.c +@@ -1932,7 +1932,7 @@ static int pktgen_device_event(struct no + { + struct net_device *dev = ptr; + +- if (!net_eq(dev_net(dev), &init_net)) ++ if (!net_eq(dev_net(dev), &init_net) || pktgen_exiting) + return NOTIFY_DONE; + + /* It is OK that we do not hold the group lock right now, +@@ -3755,12 +3755,18 @@ static void __exit pg_cleanup(void) + { + struct pktgen_thread *t; + struct list_head *q, *n; ++ struct list_head list; + + /* Stop all interfaces & threads */ + pktgen_exiting = true; + +- list_for_each_safe(q, n, &pktgen_threads) { ++ mutex_lock(&pktgen_thread_lock); ++ list_splice(&list, &pktgen_threads); ++ mutex_unlock(&pktgen_thread_lock); ++ ++ list_for_each_safe(q, n, &list) { + t = list_entry(q, struct pktgen_thread, th_list); ++ list_del(&t->th_list); + kthread_stop(t->tsk); + kfree(t); + } diff --git a/queue-3.0/pktgen-fix-module-unload-for-good.patch b/queue-3.0/pktgen-fix-module-unload-for-good.patch new file mode 100644 index 00000000000..73aeb6ddd32 --- /dev/null +++ b/queue-3.0/pktgen-fix-module-unload-for-good.patch @@ -0,0 +1,46 @@ +From abbb9a8e8d836294c6cffe2b77eeef66f7336c57 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Thu, 17 May 2012 23:52:26 +0000 +Subject: pktgen: fix module unload for good + + +From: Eric Dumazet + +[ Upstream commit d4b1133558e0d417342d5d2c49e4c35b428ff20d ] + +commit c57b5468406 (pktgen: fix crash at module unload) did a very poor +job with list primitives. + +1) list_splice() arguments were in the wrong order + +2) list_splice(list, head) has undefined behavior if head is not +initialized. + +3) We should use the list_splice_init() variant to clear pktgen_threads +list. + +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/core/pktgen.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/net/core/pktgen.c ++++ b/net/core/pktgen.c +@@ -3755,13 +3755,13 @@ static void __exit pg_cleanup(void) + { + struct pktgen_thread *t; + struct list_head *q, *n; +- struct list_head list; ++ LIST_HEAD(list); + + /* Stop all interfaces & threads */ + pktgen_exiting = true; + + mutex_lock(&pktgen_thread_lock); +- list_splice(&list, &pktgen_threads); ++ list_splice_init(&pktgen_threads, &list); + mutex_unlock(&pktgen_thread_lock); + + list_for_each_safe(q, n, &list) { diff --git a/queue-3.0/revert-net-maintain-namespace-isolation-between-vlan-and-real-device.patch b/queue-3.0/revert-net-maintain-namespace-isolation-between-vlan-and-real-device.patch new file mode 100644 index 00000000000..2a598946a81 --- /dev/null +++ b/queue-3.0/revert-net-maintain-namespace-isolation-between-vlan-and-real-device.patch @@ -0,0 +1,129 @@ +From 1366d227b34c557424280b3da4ea03ec84a285c2 Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Thu, 10 May 2012 23:03:34 -0400 +Subject: Revert "net: maintain namespace isolation between vlan and real device" + + +From: "David S. Miller" + +[ Upstream commit 59b9997baba5242997ddc7bd96b1391f5275a5a4 ] + +This reverts commit 8a83a00b0735190384a348156837918271034144. + +It causes regressions for S390 devices, because it does an +unconditional DST drop on SKBs for vlans and the QETH device +needs the neighbour entry hung off the DST for certain things +on transmit. + +Arnd can't remember exactly why he even needed this change. + +Conflicts: + + drivers/net/macvlan.c + net/8021q/vlan_dev.c + net/core/dev.c + +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/macvlan.c | 2 +- + include/linux/netdevice.h | 9 --------- + net/8021q/vlan_dev.c | 2 +- + net/core/dev.c | 36 +++++------------------------------- + 4 files changed, 7 insertions(+), 42 deletions(-) + +--- a/drivers/net/macvlan.c ++++ b/drivers/net/macvlan.c +@@ -247,7 +247,7 @@ static int macvlan_queue_xmit(struct sk_ + + xmit_world: + skb->ip_summed = ip_summed; +- skb_set_dev(skb, vlan->lowerdev); ++ skb->dev = vlan->lowerdev; + return dev_queue_xmit(skb); + } + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -1453,15 +1453,6 @@ static inline bool netdev_uses_dsa_tags( + return 0; + } + +-#ifndef CONFIG_NET_NS +-static inline void skb_set_dev(struct sk_buff *skb, struct net_device *dev) +-{ +- skb->dev = dev; +-} +-#else /* CONFIG_NET_NS */ +-void skb_set_dev(struct sk_buff *skb, struct net_device *dev); +-#endif +- + static inline bool netdev_uses_trailer_tags(struct net_device *dev) + { + #ifdef CONFIG_NET_DSA_TAG_TRAILER +--- a/net/8021q/vlan_dev.c ++++ b/net/8021q/vlan_dev.c +@@ -154,7 +154,7 @@ static netdev_tx_t vlan_dev_hard_start_x + skb = __vlan_hwaccel_put_tag(skb, vlan_tci); + } + +- skb_set_dev(skb, vlan_dev_info(dev)->real_dev); ++ skb->dev = vlan_dev_info(dev)->real_dev; + len = skb->len; + ret = dev_queue_xmit(skb); + +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -1533,10 +1533,14 @@ int dev_forward_skb(struct net_device *d + kfree_skb(skb); + return NET_RX_DROP; + } +- skb_set_dev(skb, dev); ++ skb->dev = dev; ++ skb_dst_drop(skb); + skb->tstamp.tv64 = 0; + skb->pkt_type = PACKET_HOST; + skb->protocol = eth_type_trans(skb, dev); ++ skb->mark = 0; ++ secpath_reset(skb); ++ nf_reset(skb); + return netif_rx(skb); + } + EXPORT_SYMBOL_GPL(dev_forward_skb); +@@ -1791,36 +1795,6 @@ void netif_device_attach(struct net_devi + } + EXPORT_SYMBOL(netif_device_attach); + +-/** +- * skb_dev_set -- assign a new device to a buffer +- * @skb: buffer for the new device +- * @dev: network device +- * +- * If an skb is owned by a device already, we have to reset +- * all data private to the namespace a device belongs to +- * before assigning it a new device. +- */ +-#ifdef CONFIG_NET_NS +-void skb_set_dev(struct sk_buff *skb, struct net_device *dev) +-{ +- skb_dst_drop(skb); +- if (skb->dev && !net_eq(dev_net(skb->dev), dev_net(dev))) { +- secpath_reset(skb); +- nf_reset(skb); +- skb_init_secmark(skb); +- skb->mark = 0; +- skb->priority = 0; +- skb->nf_trace = 0; +- skb->ipvs_property = 0; +-#ifdef CONFIG_NET_SCHED +- skb->tc_index = 0; +-#endif +- } +- skb->dev = dev; +-} +-EXPORT_SYMBOL(skb_set_dev); +-#endif /* CONFIG_NET_NS */ +- + /* + * Invalidate hardware checksum when packet is to be mangled, and + * complete checksum manually on outgoing path. diff --git a/queue-3.0/sctp-check-cached-dst-before-using-it.patch b/queue-3.0/sctp-check-cached-dst-before-using-it.patch new file mode 100644 index 00000000000..4360e210460 --- /dev/null +++ b/queue-3.0/sctp-check-cached-dst-before-using-it.patch @@ -0,0 +1,82 @@ +From 4180bf86f186496e2b8b3dccd2edc010f4be2eb5 Mon Sep 17 00:00:00 2001 +From: Nicolas Dichtel +Date: Fri, 4 May 2012 05:24:54 +0000 +Subject: sctp: check cached dst before using it + + +From: Nicolas Dichtel + +[ Upstream commit e0268868ba064980488fc8c194db3d8e9fb2959c ] + +dst_check() will take care of SA (and obsolete field), hence +IPsec rekeying scenario is taken into account. + +Signed-off-by: Nicolas Dichtel +Acked-by: Vlad Yaseivch +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/net/sctp/sctp.h | 13 +++++++++++++ + net/sctp/output.c | 4 +--- + net/sctp/transport.c | 17 ----------------- + 3 files changed, 14 insertions(+), 20 deletions(-) + +--- a/include/net/sctp/sctp.h ++++ b/include/net/sctp/sctp.h +@@ -700,4 +700,17 @@ static inline void sctp_v4_map_v6(union + addr->v6.sin6_addr.s6_addr32[2] = htonl(0x0000ffff); + } + ++/* The cookie is always 0 since this is how it's used in the ++ * pmtu code. ++ */ ++static inline struct dst_entry *sctp_transport_dst_check(struct sctp_transport *t) ++{ ++ if (t->dst && !dst_check(t->dst, 0)) { ++ dst_release(t->dst); ++ t->dst = NULL; ++ } ++ ++ return t->dst; ++} ++ + #endif /* __net_sctp_h__ */ +--- a/net/sctp/output.c ++++ b/net/sctp/output.c +@@ -377,9 +377,7 @@ int sctp_packet_transmit(struct sctp_pac + */ + skb_set_owner_w(nskb, sk); + +- /* The 'obsolete' field of dst is set to 2 when a dst is freed. */ +- if (!dst || (dst->obsolete > 1)) { +- dst_release(dst); ++ if (!sctp_transport_dst_check(tp)) { + sctp_transport_route(tp, NULL, sctp_sk(sk)); + if (asoc && (asoc->param_flags & SPP_PMTUD_ENABLE)) { + sctp_assoc_sync_pmtu(asoc); +--- a/net/sctp/transport.c ++++ b/net/sctp/transport.c +@@ -226,23 +226,6 @@ void sctp_transport_pmtu(struct sctp_tra + transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT; + } + +-/* this is a complete rip-off from __sk_dst_check +- * the cookie is always 0 since this is how it's used in the +- * pmtu code +- */ +-static struct dst_entry *sctp_transport_dst_check(struct sctp_transport *t) +-{ +- struct dst_entry *dst = t->dst; +- +- if (dst && dst->obsolete && dst->ops->check(dst, 0) == NULL) { +- dst_release(t->dst); +- t->dst = NULL; +- return NULL; +- } +- +- return dst; +-} +- + void sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu) + { + struct dst_entry *dst; diff --git a/queue-3.0/series b/queue-3.0/series index 194119a862f..6c1d935e142 100644 --- a/queue-3.0/series +++ b/queue-3.0/series @@ -27,3 +27,13 @@ mtd-nand-fix-scan_read_raw_oob.patch drm-radeon-properly-program-gart-on-rv740-juniper-cypress-barts-hemlock.patch drm-radeon-fix-hd6790-hd6570-backend-programming.patch drm-ttm-fix-spinlock-imbalance.patch +ipv4-do-not-use-dead-fib_info-entries.patch +ipv4-fix-the-rcu-race-between-free_fib_info-and-ip_route_output_slow.patch +ipv6-fix-incorrect-ipsec-fragment.patch +l2tp-fix-oops-in-l2tp-ip-sockets-for-connect-af_unspec-case.patch +pktgen-fix-crash-at-module-unload.patch +pktgen-fix-module-unload-for-good.patch +revert-net-maintain-namespace-isolation-between-vlan-and-real-device.patch +sctp-check-cached-dst-before-using-it.patch +skb-avoid-unnecessary-reallocations-in-__skb_cow.patch +xfrm-take-net-hdr-len-into-account-for-esp-payload-size-calculation.patch diff --git a/queue-3.0/skb-avoid-unnecessary-reallocations-in-__skb_cow.patch b/queue-3.0/skb-avoid-unnecessary-reallocations-in-__skb_cow.patch new file mode 100644 index 00000000000..140e35bc235 --- /dev/null +++ b/queue-3.0/skb-avoid-unnecessary-reallocations-in-__skb_cow.patch @@ -0,0 +1,40 @@ +From c6474e362d069c91400d0e0486c76d2ee31667b6 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Tue, 29 May 2012 03:35:08 +0000 +Subject: skb: avoid unnecessary reallocations in __skb_cow + + +From: Felix Fietkau + +[ Upstream commit 617c8c11236716dcbda877e764b7bf37c6fd8063 ] + +At the beginning of __skb_cow, headroom gets set to a minimum of +NET_SKB_PAD. This causes unnecessary reallocations if the buffer was not +cloned and the headroom is just below NET_SKB_PAD, but still more than the +amount requested by the caller. +This was showing up frequently in my tests on VLAN tx, where +vlan_insert_tag calls skb_cow_head(skb, VLAN_HLEN). + +Locally generated packets should have enough headroom, and for forward +paths, we already have NET_SKB_PAD bytes of headroom, so we don't need to +add any extra space here. + +Signed-off-by: Felix Fietkau +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/skbuff.h | 2 -- + 1 file changed, 2 deletions(-) + +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -1633,8 +1633,6 @@ static inline int __skb_cow(struct sk_bu + { + int delta = 0; + +- if (headroom < NET_SKB_PAD) +- headroom = NET_SKB_PAD; + if (headroom > skb_headroom(skb)) + delta = headroom - skb_headroom(skb); + diff --git a/queue-3.0/xfrm-take-net-hdr-len-into-account-for-esp-payload-size-calculation.patch b/queue-3.0/xfrm-take-net-hdr-len-into-account-for-esp-payload-size-calculation.patch new file mode 100644 index 00000000000..c01f092c84d --- /dev/null +++ b/queue-3.0/xfrm-take-net-hdr-len-into-account-for-esp-payload-size-calculation.patch @@ -0,0 +1,95 @@ +From 4e60eb6ceaf79b7320908b825e64ec5df8550ffd Mon Sep 17 00:00:00 2001 +From: Benjamin Poirier +Date: Thu, 24 May 2012 11:32:38 +0000 +Subject: xfrm: take net hdr len into account for esp payload size calculation + + +From: Benjamin Poirier + +[ Upstream commit 91657eafb64b4cb53ec3a2fbc4afc3497f735788 ] + +Corrects the function that determines the esp payload size. The calculations +done in esp{4,6}_get_mtu() lead to overlength frames in transport mode for +certain mtu values and suboptimal frames for others. + +According to what is done, mainly in esp{,6}_output() and tcp_mtu_to_mss(), +net_header_len must be taken into account before doing the alignment +calculation. + +Signed-off-by: Benjamin Poirier +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/esp4.c | 24 +++++++++--------------- + net/ipv6/esp6.c | 18 +++++++----------- + 2 files changed, 16 insertions(+), 26 deletions(-) + +--- a/net/ipv4/esp4.c ++++ b/net/ipv4/esp4.c +@@ -457,28 +457,22 @@ static u32 esp4_get_mtu(struct xfrm_stat + struct esp_data *esp = x->data; + u32 blksize = ALIGN(crypto_aead_blocksize(esp->aead), 4); + u32 align = max_t(u32, blksize, esp->padlen); +- u32 rem; +- +- mtu -= x->props.header_len + crypto_aead_authsize(esp->aead); +- rem = mtu & (align - 1); +- mtu &= ~(align - 1); ++ unsigned int net_adj; + + switch (x->props.mode) { +- case XFRM_MODE_TUNNEL: +- break; +- default: + case XFRM_MODE_TRANSPORT: +- /* The worst case */ +- mtu -= blksize - 4; +- mtu += min_t(u32, blksize - 4, rem); +- break; + case XFRM_MODE_BEET: +- /* The worst case. */ +- mtu += min_t(u32, IPV4_BEET_PHMAXLEN, rem); ++ net_adj = sizeof(struct iphdr); ++ break; ++ case XFRM_MODE_TUNNEL: ++ net_adj = 0; + break; ++ default: ++ BUG(); + } + +- return mtu - 2; ++ return ((mtu - x->props.header_len - crypto_aead_authsize(esp->aead) - ++ net_adj) & ~(align - 1)) + (net_adj - 2); + } + + static void esp4_err(struct sk_buff *skb, u32 info) +--- a/net/ipv6/esp6.c ++++ b/net/ipv6/esp6.c +@@ -411,19 +411,15 @@ static u32 esp6_get_mtu(struct xfrm_stat + struct esp_data *esp = x->data; + u32 blksize = ALIGN(crypto_aead_blocksize(esp->aead), 4); + u32 align = max_t(u32, blksize, esp->padlen); +- u32 rem; ++ unsigned int net_adj; + +- mtu -= x->props.header_len + crypto_aead_authsize(esp->aead); +- rem = mtu & (align - 1); +- mtu &= ~(align - 1); ++ if (x->props.mode != XFRM_MODE_TUNNEL) ++ net_adj = sizeof(struct ipv6hdr); ++ else ++ net_adj = 0; + +- if (x->props.mode != XFRM_MODE_TUNNEL) { +- u32 padsize = ((blksize - 1) & 7) + 1; +- mtu -= blksize - padsize; +- mtu += min_t(u32, blksize - padsize, rem); +- } +- +- return mtu - 2; ++ return ((mtu - x->props.header_len - crypto_aead_authsize(esp->aead) - ++ net_adj) & ~(align - 1)) + (net_adj - 2); + } + + static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, -- 2.47.3