]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.0-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 3 Jun 2012 12:44:05 +0000 (05:44 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 3 Jun 2012 12:44:05 +0000 (05:44 -0700)
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

queue-3.0/ipv4-do-not-use-dead-fib_info-entries.patch [new file with mode: 0644]
queue-3.0/ipv4-fix-the-rcu-race-between-free_fib_info-and-ip_route_output_slow.patch [new file with mode: 0644]
queue-3.0/ipv6-fix-incorrect-ipsec-fragment.patch [new file with mode: 0644]
queue-3.0/l2tp-fix-oops-in-l2tp-ip-sockets-for-connect-af_unspec-case.patch [new file with mode: 0644]
queue-3.0/pktgen-fix-crash-at-module-unload.patch [new file with mode: 0644]
queue-3.0/pktgen-fix-module-unload-for-good.patch [new file with mode: 0644]
queue-3.0/revert-net-maintain-namespace-isolation-between-vlan-and-real-device.patch [new file with mode: 0644]
queue-3.0/sctp-check-cached-dst-before-using-it.patch [new file with mode: 0644]
queue-3.0/series
queue-3.0/skb-avoid-unnecessary-reallocations-in-__skb_cow.patch [new file with mode: 0644]
queue-3.0/xfrm-take-net-hdr-len-into-account-for-esp-payload-size-calculation.patch [new file with mode: 0644]

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 (file)
index 0000000..0967f6b
--- /dev/null
@@ -0,0 +1,34 @@
+From ea50b667b36506c51cbc60361a68e0ef1c84d9dc Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Thu, 10 May 2012 22:16:32 -0400
+Subject: ipv4: Do not use dead fib_info entries.
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ 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 <yevgen.pronenko@sonymobile.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..97e765e
--- /dev/null
@@ -0,0 +1,97 @@
+From b0b8cb5c6afab6a7783eb8005a6e2f677b002994 Mon Sep 17 00:00:00 2001
+From: Yanmin Zhang <yanmin_zhang@linux.intel.com>
+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 <yanmin_zhang@linux.intel.com>
+
+[ 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]  [<c1227f50>] ? pgtable_bad+0x130/0x130
+<4>[23900.000416]  [<c1238c2a>] __might_sleep+0x10a/0x110
+<4>[23900.007357]  [<c1228021>] do_page_fault+0xd1/0x3c0
+<4>[23900.013764]  [<c18e9ba9>] ? restore_all+0xf/0xf
+<4>[23900.024024]  [<c17c007b>] ? napi_complete+0x8b/0x690
+<4>[23900.029297]  [<c1227f50>] ? pgtable_bad+0x130/0x130
+<4>[23900.123739]  [<c1227f50>] ? pgtable_bad+0x130/0x130
+<4>[23900.128955]  [<c18ea0c3>] error_code+0x5f/0x64
+<4>[23900.133466]  [<c1227f50>] ? pgtable_bad+0x130/0x130
+<4>[23900.138450]  [<c17f6298>] ? __ip_route_output_key+0x698/0x7c0
+<4>[23900.144312]  [<c17f5f8d>] ? __ip_route_output_key+0x38d/0x7c0
+<4>[23900.150730]  [<c17f63df>] ip_route_output_flow+0x1f/0x60
+<4>[23900.156261]  [<c181de58>] ip4_datagram_connect+0x188/0x2b0
+<4>[23900.161960]  [<c18e981f>] ? _raw_spin_unlock_bh+0x1f/0x30
+<4>[23900.167834]  [<c18298d6>] inet_dgram_connect+0x36/0x80
+<4>[23900.173224]  [<c14f9e88>] ? _copy_from_user+0x48/0x140
+<4>[23900.178817]  [<c17ab9da>] sys_connect+0x9a/0xd0
+<4>[23900.183538]  [<c132e93c>] ? alloc_file+0xdc/0x240
+<4>[23900.189111]  [<c123925d>] ? 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 <yanmin_zhang@linux.intel.com>
+Signed-off-by: Kun Jiang <kunx.jiang@intel.com>
+Acked-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..d4ec54c
--- /dev/null
@@ -0,0 +1,174 @@
+From 3e03d3364f90cc792e81bbd60da606736209d3ee Mon Sep 17 00:00:00 2001
+From: Gao feng <gaofeng@cn.fujitsu.com>
+Date: Sat, 26 May 2012 01:30:53 +0000
+Subject: ipv6: fix incorrect ipsec fragment
+
+
+From: Gao feng <gaofeng@cn.fujitsu.com>
+
+[ 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 <gaofeng@cn.fujitsu.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..5cc5bd0
--- /dev/null
@@ -0,0 +1,110 @@
+From fa234d2b07ed72b503ff55446fbfaea475d06fa2 Mon Sep 17 00:00:00 2001
+From: James Chapman <jchapman@katalix.com>
+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 <jchapman@katalix.com>
+
+[ 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:[<ffffffff82e133b0>]  [<ffffffff82e133b0>] inet_unhash+0x50/0xd0
+ RSP: 0018:ffff88001989be28  EFLAGS: 00010293
+ Stack:
+  ffff8800407a8000 0000000000000000 ffff88001989be78 ffffffff82e3a249
+  ffffffff82e3a050 ffff88001989bec8 ffff88001989be88 ffff8800407a8000
+  0000000000000010 ffff88001989bec8 ffff88001989bea8 ffffffff82e42639
+ Call Trace:
+ [<ffffffff82e3a249>] udp_disconnect+0x1f9/0x290
+ [<ffffffff82e42639>] inet_dgram_connect+0x29/0x80
+ [<ffffffff82d012fc>] sys_connect+0x9c/0x100
+
+Reported-by: Sasha Levin <levinsasha928@gmail.com>
+Signed-off-by: James Chapman <jchapman@katalix.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..fee4c88
--- /dev/null
@@ -0,0 +1,70 @@
+From e36258658f4efc6c8a160839d0f7d3c987c10f7f Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <eric.dumazet@gmail.com>
+Date: Wed, 9 May 2012 13:29:51 +0000
+Subject: pktgen: fix crash at module unload
+
+
+From: Eric Dumazet <eric.dumazet@gmail.com>
+
+[ 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: <none>/-1, .owner_cpu: -1
+[  296.820943] Pid: 3267, comm: rmmod Not tainted 3.4.0-rc5+ #254
+[  296.821079] Call Trace:
+[  296.821211]  [<ffffffff8168a715>] spin_dump+0x8a/0x8f
+[  296.821345]  [<ffffffff8168a73b>] spin_bug+0x21/0x26
+[  296.821507]  [<ffffffff812b4741>] do_raw_spin_lock+0x131/0x140
+[  296.821648]  [<ffffffff8169188e>] _raw_spin_lock+0x1e/0x20
+[  296.821786]  [<ffffffffa00cc0fd>] __pktgen_NN_threads+0x4d/0x140 [pktgen]
+[  296.821928]  [<ffffffffa00ccf8d>] pktgen_device_event+0x10d/0x1e0 [pktgen]
+[  296.822073]  [<ffffffff8154ed4f>] unregister_netdevice_notifier+0x7f/0x100
+[  296.822216]  [<ffffffffa00d2a0b>] pg_cleanup+0x48/0x73 [pktgen]
+[  296.822357]  [<ffffffff8109528e>] sys_delete_module+0x17e/0x2a0
+[  296.822502]  [<ffffffff81699652>] 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 <edumazet@google.com>
+Cc: Eric W. Biederman <ebiederm@xmission.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..73aeb6d
--- /dev/null
@@ -0,0 +1,46 @@
+From abbb9a8e8d836294c6cffe2b77eeef66f7336c57 Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Thu, 17 May 2012 23:52:26 +0000
+Subject: pktgen: fix module unload for good
+
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ 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 <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..2a59894
--- /dev/null
@@ -0,0 +1,129 @@
+From 1366d227b34c557424280b3da4ea03ec84a285c2 Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Thu, 10 May 2012 23:03:34 -0400
+Subject: Revert "net: maintain namespace isolation between vlan and real device"
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ 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 <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..4360e21
--- /dev/null
@@ -0,0 +1,82 @@
+From 4180bf86f186496e2b8b3dccd2edc010f4be2eb5 Mon Sep 17 00:00:00 2001
+From: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Date: Fri, 4 May 2012 05:24:54 +0000
+Subject: sctp: check cached dst before using it
+
+
+From: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+
+[ 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 <nicolas.dichtel@6wind.com>
+Acked-by: Vlad Yaseivch <vyasevich@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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;
index 194119a862fab28aaea8978dbd50d9885e02c53b..6c1d935e142bfdb5f10963d1c8a19c4929cd516a 100644 (file)
@@ -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 (file)
index 0000000..140e35b
--- /dev/null
@@ -0,0 +1,40 @@
+From c6474e362d069c91400d0e0486c76d2ee31667b6 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Tue, 29 May 2012 03:35:08 +0000
+Subject: skb: avoid unnecessary reallocations in __skb_cow
+
+
+From: Felix Fietkau <nbd@openwrt.org>
+
+[ 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 <nbd@openwrt.org>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..c01f092
--- /dev/null
@@ -0,0 +1,95 @@
+From 4e60eb6ceaf79b7320908b825e64ec5df8550ffd Mon Sep 17 00:00:00 2001
+From: Benjamin Poirier <bpoirier@suse.de>
+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 <bpoirier@suse.de>
+
+[ 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 <bpoirier@suse.de>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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,