]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.0-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 24 Jun 2013 21:06:53 +0000 (14:06 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 24 Jun 2013 21:06:53 +0000 (14:06 -0700)
added patches:
gianfar-add-missing-iounmap-on-error-in-gianfar_ptp_probe.patch
ip_tunnel-fix-kernel-panic-with-icmp_dest_unreach.patch
ipv6-assign-rt6_info-to-inet6_ifaddr-in-init_loopback.patch
ipv6-fix-possible-crashes-in-ip6_cork_release.patch
l2tp-fix-ppp-header-erasure-and-memory-leak.patch
l2tp-fix-sendmsg-return-value.patch
net-block-msg_cmsg_compat-in-send-m-msg-and-recv-m-msg.patch
net-force-a-reload-of-first-item-in-hlist_nulls_for_each_entry_rcu.patch
netlabel-improve-domain-mapping-validation.patch
net-sctp-fix-null-pointer-dereference-in-socket-destruction.patch
packet-packet_getname_spkt-make-sure-string-is-always-0-terminated.patch
tcp-fix-tcp_md5_hash_skb_data.patch
tcp-xps-fix-reordering-issues.patch

14 files changed:
queue-3.0/gianfar-add-missing-iounmap-on-error-in-gianfar_ptp_probe.patch [new file with mode: 0644]
queue-3.0/ip_tunnel-fix-kernel-panic-with-icmp_dest_unreach.patch [new file with mode: 0644]
queue-3.0/ipv6-assign-rt6_info-to-inet6_ifaddr-in-init_loopback.patch [new file with mode: 0644]
queue-3.0/ipv6-fix-possible-crashes-in-ip6_cork_release.patch [new file with mode: 0644]
queue-3.0/l2tp-fix-ppp-header-erasure-and-memory-leak.patch [new file with mode: 0644]
queue-3.0/l2tp-fix-sendmsg-return-value.patch [new file with mode: 0644]
queue-3.0/net-block-msg_cmsg_compat-in-send-m-msg-and-recv-m-msg.patch [new file with mode: 0644]
queue-3.0/net-force-a-reload-of-first-item-in-hlist_nulls_for_each_entry_rcu.patch [new file with mode: 0644]
queue-3.0/net-sctp-fix-null-pointer-dereference-in-socket-destruction.patch [new file with mode: 0644]
queue-3.0/netlabel-improve-domain-mapping-validation.patch [new file with mode: 0644]
queue-3.0/packet-packet_getname_spkt-make-sure-string-is-always-0-terminated.patch [new file with mode: 0644]
queue-3.0/series
queue-3.0/tcp-fix-tcp_md5_hash_skb_data.patch [new file with mode: 0644]
queue-3.0/tcp-xps-fix-reordering-issues.patch [new file with mode: 0644]

diff --git a/queue-3.0/gianfar-add-missing-iounmap-on-error-in-gianfar_ptp_probe.patch b/queue-3.0/gianfar-add-missing-iounmap-on-error-in-gianfar_ptp_probe.patch
new file mode 100644 (file)
index 0000000..7cf9054
--- /dev/null
@@ -0,0 +1,29 @@
+From 273c3d4944f2b77a132a587b5ff7a134646b3de8 Mon Sep 17 00:00:00 2001
+From: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
+Date: Thu, 16 May 2013 22:25:34 +0000
+Subject: gianfar: add missing iounmap() on error in gianfar_ptp_probe()
+
+From: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
+
+[ Upstream commit e5f5e380e0f3bb11f04ca5bc66a551e58e0ad26e ]
+
+Add the missing iounmap() before return from gianfar_ptp_probe()
+in the error handling case.
+
+Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/gianfar_ptp.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/gianfar_ptp.c
++++ b/drivers/net/gianfar_ptp.c
+@@ -521,6 +521,7 @@ static int gianfar_ptp_probe(struct plat
+       return 0;
+ no_clock:
++      iounmap(etsects->regs);
+ no_ioremap:
+       release_resource(etsects->rsrc);
+ no_resource:
diff --git a/queue-3.0/ip_tunnel-fix-kernel-panic-with-icmp_dest_unreach.patch b/queue-3.0/ip_tunnel-fix-kernel-panic-with-icmp_dest_unreach.patch
new file mode 100644 (file)
index 0000000..af2b431
--- /dev/null
@@ -0,0 +1,72 @@
+From 5ea8887f9c6a80a35f470f61a744fe3febc99e54 Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Fri, 24 May 2013 05:49:58 +0000
+Subject: ip_tunnel: fix kernel panic with icmp_dest_unreach
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit a622260254ee481747cceaaa8609985b29a31565 ]
+
+Daniel Petre reported crashes in icmp_dst_unreach() with following call
+graph:
+
+Daniel found a similar problem mentioned in
+ http://lkml.indiana.edu/hypermail/linux/kernel/1007.0/00961.html
+
+And indeed this is the root cause : skb->cb[] contains data fooling IP
+stack.
+
+We must clear IPCB in ip_tunnel_xmit() sooner in case dst_link_failure()
+is called. Or else skb->cb[] might contain garbage from GSO segmentation
+layer.
+
+A similar fix was tested on linux-3.9, but gre code was refactored in
+linux-3.10. I'll send patches for stable kernels as well.
+
+Many thanks to Daniel for providing reports, patches and testing !
+
+Reported-by: Daniel Petre <daniel.petre@rcs-rds.ro>
+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/ipv4/ip_gre.c |    2 +-
+ net/ipv4/ipip.c   |    2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/net/ipv4/ip_gre.c
++++ b/net/ipv4/ip_gre.c
+@@ -716,6 +716,7 @@ static netdev_tx_t ipgre_tunnel_xmit(str
+               tiph = &tunnel->parms.iph;
+       }
++      memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+       if ((dst = tiph->daddr) == 0) {
+               /* NBMA tunnel */
+@@ -853,7 +854,6 @@ static netdev_tx_t ipgre_tunnel_xmit(str
+       skb_reset_transport_header(skb);
+       skb_push(skb, gre_hlen);
+       skb_reset_network_header(skb);
+-      memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+       IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED |
+                             IPSKB_REROUTED);
+       skb_dst_drop(skb);
+--- a/net/ipv4/ipip.c
++++ b/net/ipv4/ipip.c
+@@ -448,6 +448,7 @@ static netdev_tx_t ipip_tunnel_xmit(stru
+       if (tos & 1)
+               tos = old_iph->tos;
++      memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+       if (!dst) {
+               /* NBMA tunnel */
+               if ((rt = skb_rtable(skb)) == NULL) {
+@@ -531,7 +532,6 @@ static netdev_tx_t ipip_tunnel_xmit(stru
+       skb->transport_header = skb->network_header;
+       skb_push(skb, sizeof(struct iphdr));
+       skb_reset_network_header(skb);
+-      memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+       IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED |
+                             IPSKB_REROUTED);
+       skb_dst_drop(skb);
diff --git a/queue-3.0/ipv6-assign-rt6_info-to-inet6_ifaddr-in-init_loopback.patch b/queue-3.0/ipv6-assign-rt6_info-to-inet6_ifaddr-in-init_loopback.patch
new file mode 100644 (file)
index 0000000..4e26ea9
--- /dev/null
@@ -0,0 +1,40 @@
+From e25759b91bfc1d09d71e2843e2c0f3b0e308fdca Mon Sep 17 00:00:00 2001
+From: Gao feng <gaofeng@cn.fujitsu.com>
+Date: Sun, 2 Jun 2013 22:16:21 +0000
+Subject: ipv6: assign rt6_info to inet6_ifaddr in init_loopback
+
+From: Gao feng <gaofeng@cn.fujitsu.com>
+
+[ Upstream commit 534c877928a16ae5f9776436a497109639bf67dc ]
+
+Commit 25fb6ca4ed9cad72f14f61629b68dc03c0d9713f
+"net IPv6 : Fix broken IPv6 routing table after loopback down-up"
+forgot to assign rt6_info to the inet6_ifaddr.
+When disable the net device, the rt6_info which allocated
+in init_loopback will not be destroied in __ipv6_ifa_notify.
+
+This will trigger the waring message below
+[23527.916091] unregister_netdevice: waiting for tap0 to become free. Usage count = 1
+
+Reported-by: Arkadiusz Miskiewicz <a.miskiewicz@gmail.com>
+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>
+---
+ net/ipv6/addrconf.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -2360,8 +2360,10 @@ static void init_loopback(struct net_dev
+                       sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0);
+                       /* Failure cases are ignored */
+-                      if (!IS_ERR(sp_rt))
++                      if (!IS_ERR(sp_rt)) {
++                              sp_ifa->rt = sp_rt;
+                               ip6_ins_rt(sp_rt);
++                      }
+               }
+               read_unlock_bh(&idev->lock);
+       }
diff --git a/queue-3.0/ipv6-fix-possible-crashes-in-ip6_cork_release.patch b/queue-3.0/ipv6-fix-possible-crashes-in-ip6_cork_release.patch
new file mode 100644 (file)
index 0000000..1c9494e
--- /dev/null
@@ -0,0 +1,36 @@
+From 6079422bffc1704cf69686ce7a1409dbb419deaf Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Fri, 17 May 2013 04:53:13 +0000
+Subject: ipv6: fix possible crashes in ip6_cork_release()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 284041ef21fdf2e0d216ab6b787bc9072b4eb58a ]
+
+commit 0178b695fd6b4 ("ipv6: Copy cork options in ip6_append_data")
+added some code duplication and bad error recovery, leading to potential
+crash in ip6_cork_release() as kfree() could be called with garbage.
+
+use kzalloc() to make sure this wont happen.
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Cc: Herbert Xu <herbert@gondor.apana.org.au>
+Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
+Cc: Neal Cardwell <ncardwell@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/ip6_output.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -1248,7 +1248,7 @@ int ip6_append_data(struct sock *sk, int
+                       if (WARN_ON(np->cork.opt))
+                               return -EINVAL;
+-                      np->cork.opt = kmalloc(opt->tot_len, sk->sk_allocation);
++                      np->cork.opt = kzalloc(opt->tot_len, sk->sk_allocation);
+                       if (unlikely(np->cork.opt == NULL))
+                               return -ENOBUFS;
diff --git a/queue-3.0/l2tp-fix-ppp-header-erasure-and-memory-leak.patch b/queue-3.0/l2tp-fix-ppp-header-erasure-and-memory-leak.patch
new file mode 100644 (file)
index 0000000..0d2c869
--- /dev/null
@@ -0,0 +1,37 @@
+From 7728091d69e5b36a9b28e8219ad9af606015fe91 Mon Sep 17 00:00:00 2001
+From: Guillaume Nault <g.nault@alphalink.fr>
+Date: Wed, 12 Jun 2013 16:07:23 +0200
+Subject: l2tp: Fix PPP header erasure and memory leak
+
+From: Guillaume Nault <g.nault@alphalink.fr>
+
+[ Upstream commit 55b92b7a11690bc377b5d373872a6b650ae88e64 ]
+
+Copy user data after PPP framing header. This prevents erasure of the
+added PPP header and avoids leaking two bytes of uninitialised memory
+at the end of skb's data buffer.
+
+Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/l2tp/l2tp_ppp.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/net/l2tp/l2tp_ppp.c
++++ b/net/l2tp/l2tp_ppp.c
+@@ -350,12 +350,12 @@ static int pppol2tp_sendmsg(struct kiocb
+       skb_put(skb, 2);
+       /* Copy user data into skb */
+-      error = memcpy_fromiovec(skb->data, m->msg_iov, total_len);
++      error = memcpy_fromiovec(skb_put(skb, total_len), m->msg_iov,
++                               total_len);
+       if (error < 0) {
+               kfree_skb(skb);
+               goto error_put_sess_tun;
+       }
+-      skb_put(skb, total_len);
+       l2tp_xmit_skb(session, skb, session->hdr_len);
diff --git a/queue-3.0/l2tp-fix-sendmsg-return-value.patch b/queue-3.0/l2tp-fix-sendmsg-return-value.patch
new file mode 100644 (file)
index 0000000..97e54be
--- /dev/null
@@ -0,0 +1,30 @@
+From e350a94b13a1b078cac50d0b836b96f38937b6e0 Mon Sep 17 00:00:00 2001
+From: Guillaume Nault <g.nault@alphalink.fr>
+Date: Wed, 12 Jun 2013 16:07:36 +0200
+Subject: l2tp: Fix sendmsg() return value
+
+From: Guillaume Nault <g.nault@alphalink.fr>
+
+[ Upstream commit a6f79d0f26704214b5b702bbac525cb72997f984 ]
+
+PPPoL2TP sockets should comply with the standard send*() return values
+(i.e. return number of bytes sent instead of 0 upon success).
+
+Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/l2tp/l2tp_ppp.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/l2tp/l2tp_ppp.c
++++ b/net/l2tp/l2tp_ppp.c
+@@ -362,7 +362,7 @@ static int pppol2tp_sendmsg(struct kiocb
+       sock_put(ps->tunnel_sock);
+       sock_put(sk);
+-      return error;
++      return total_len;
+ error_put_sess_tun:
+       sock_put(ps->tunnel_sock);
diff --git a/queue-3.0/net-block-msg_cmsg_compat-in-send-m-msg-and-recv-m-msg.patch b/queue-3.0/net-block-msg_cmsg_compat-in-send-m-msg-and-recv-m-msg.patch
new file mode 100644 (file)
index 0000000..3390511
--- /dev/null
@@ -0,0 +1,267 @@
+From 4ff46b1f5e98db5c456c331267099f2183b496dc Mon Sep 17 00:00:00 2001
+From: Andy Lutomirski <luto@amacapital.net>
+Date: Wed, 22 May 2013 14:07:44 -0700
+Subject: net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg
+
+From: Andy Lutomirski <luto@amacapital.net>
+
+[ Upstream commits 1be374a0518a288147c6a7398792583200a67261 and
+  a7526eb5d06b0084ef12d7b168d008fcf516caab ]
+
+MSG_CMSG_COMPAT is (AFAIK) not intended to be part of the API --
+it's a hack that steals a bit to indicate to other networking code
+that a compat entry was used.  So don't allow it from a non-compat
+syscall.
+
+This prevents an oops when running this code:
+
+int main()
+{
+       int s;
+       struct sockaddr_in addr;
+       struct msghdr *hdr;
+
+       char *highpage = mmap((void*)(TASK_SIZE_MAX - 4096), 4096,
+                             PROT_READ | PROT_WRITE,
+                             MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+       if (highpage == MAP_FAILED)
+               err(1, "mmap");
+
+       s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+       if (s == -1)
+               err(1, "socket");
+
+        addr.sin_family = AF_INET;
+        addr.sin_port = htons(1);
+        addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+       if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) != 0)
+               err(1, "connect");
+
+       void *evil = highpage + 4096 - COMPAT_MSGHDR_SIZE;
+       printf("Evil address is %p\n", evil);
+
+       if (syscall(__NR_sendmmsg, s, evil, 1, MSG_CMSG_COMPAT) < 0)
+               err(1, "sendmmsg");
+
+       return 0;
+}
+
+Cc: David S. Miller <davem@davemloft.net>
+Signed-off-by: Andy Lutomirski <luto@amacapital.net>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/socket.h |    3 ++
+ net/compat.c           |   13 ++++++++-
+ net/socket.c           |   67 ++++++++++++++++++++++++++++++++-----------------
+ 3 files changed, 59 insertions(+), 24 deletions(-)
+
+--- a/include/linux/socket.h
++++ b/include/linux/socket.h
+@@ -332,6 +332,9 @@ extern int put_cmsg(struct msghdr*, int
+ struct timespec;
++/* The __sys_...msg variants allow MSG_CMSG_COMPAT */
++extern long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags);
++extern long __sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags);
+ extern int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
+                         unsigned int flags, struct timespec *timeout);
+ extern int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg,
+--- a/net/compat.c
++++ b/net/compat.c
+@@ -732,19 +732,25 @@ static unsigned char nas[21] = {
+ asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned flags)
+ {
+-      return sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
++      if (flags & MSG_CMSG_COMPAT)
++              return -EINVAL;
++      return __sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
+ }
+ asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg,
+                                   unsigned vlen, unsigned int flags)
+ {
++      if (flags & MSG_CMSG_COMPAT)
++              return -EINVAL;
+       return __sys_sendmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
+                             flags | MSG_CMSG_COMPAT);
+ }
+ asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags)
+ {
+-      return sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
++      if (flags & MSG_CMSG_COMPAT)
++              return -EINVAL;
++      return __sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
+ }
+ asmlinkage long compat_sys_recv(int fd, void __user *buf, size_t len, unsigned flags)
+@@ -766,6 +772,9 @@ asmlinkage long compat_sys_recvmmsg(int
+       int datagrams;
+       struct timespec ktspec;
++      if (flags & MSG_CMSG_COMPAT)
++              return -EINVAL;
++
+       if (timeout == NULL)
+               return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
+                                     flags | MSG_CMSG_COMPAT, NULL);
+--- a/net/socket.c
++++ b/net/socket.c
+@@ -1876,9 +1876,9 @@ struct used_address {
+       unsigned int name_len;
+ };
+-static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
+-                       struct msghdr *msg_sys, unsigned flags,
+-                       struct used_address *used_address)
++static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
++                        struct msghdr *msg_sys, unsigned flags,
++                        struct used_address *used_address)
+ {
+       struct compat_msghdr __user *msg_compat =
+           (struct compat_msghdr __user *)msg;
+@@ -1998,22 +1998,30 @@ out:
+  *    BSD sendmsg interface
+  */
+-SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags)
++long __sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
+ {
+       int fput_needed, err;
+       struct msghdr msg_sys;
+-      struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
++      struct socket *sock;
++      sock = sockfd_lookup_light(fd, &err, &fput_needed);
+       if (!sock)
+               goto out;
+-      err = __sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
++      err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
+       fput_light(sock->file, fput_needed);
+ out:
+       return err;
+ }
++SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags)
++{
++      if (flags & MSG_CMSG_COMPAT)
++              return -EINVAL;
++      return __sys_sendmsg(fd, msg, flags);
++}
++
+ /*
+  *    Linux sendmmsg interface
+  */
+@@ -2044,15 +2052,16 @@ int __sys_sendmmsg(int fd, struct mmsghd
+       while (datagrams < vlen) {
+               if (MSG_CMSG_COMPAT & flags) {
+-                      err = __sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
+-                                          &msg_sys, flags, &used_address);
++                      err = ___sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
++                                           &msg_sys, flags, &used_address);
+                       if (err < 0)
+                               break;
+                       err = __put_user(err, &compat_entry->msg_len);
+                       ++compat_entry;
+               } else {
+-                      err = __sys_sendmsg(sock, (struct msghdr __user *)entry,
+-                                          &msg_sys, flags, &used_address);
++                      err = ___sys_sendmsg(sock,
++                                           (struct msghdr __user *)entry,
++                                           &msg_sys, flags, &used_address);
+                       if (err < 0)
+                               break;
+                       err = put_user(err, &entry->msg_len);
+@@ -2076,11 +2085,13 @@ int __sys_sendmmsg(int fd, struct mmsghd
+ SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
+               unsigned int, vlen, unsigned int, flags)
+ {
++      if (flags & MSG_CMSG_COMPAT)
++              return -EINVAL;
+       return __sys_sendmmsg(fd, mmsg, vlen, flags);
+ }
+-static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
+-                       struct msghdr *msg_sys, unsigned flags, int nosec)
++static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
++                        struct msghdr *msg_sys, unsigned flags, int nosec)
+ {
+       struct compat_msghdr __user *msg_compat =
+           (struct compat_msghdr __user *)msg;
+@@ -2177,23 +2188,31 @@ out:
+  *    BSD recvmsg interface
+  */
+-SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
+-              unsigned int, flags)
++long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags)
+ {
+       int fput_needed, err;
+       struct msghdr msg_sys;
+-      struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
++      struct socket *sock;
++      sock = sockfd_lookup_light(fd, &err, &fput_needed);
+       if (!sock)
+               goto out;
+-      err = __sys_recvmsg(sock, msg, &msg_sys, flags, 0);
++      err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
+       fput_light(sock->file, fput_needed);
+ out:
+       return err;
+ }
++SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
++              unsigned int, flags)
++{
++      if (flags & MSG_CMSG_COMPAT)
++              return -EINVAL;
++      return __sys_recvmsg(fd, msg, flags);
++}
++
+ /*
+  *     Linux recvmmsg interface
+  */
+@@ -2231,17 +2250,18 @@ int __sys_recvmmsg(int fd, struct mmsghd
+                * No need to ask LSM for more than the first datagram.
+                */
+               if (MSG_CMSG_COMPAT & flags) {
+-                      err = __sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
+-                                          &msg_sys, flags & ~MSG_WAITFORONE,
+-                                          datagrams);
++                      err = ___sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
++                                           &msg_sys, flags & ~MSG_WAITFORONE,
++                                           datagrams);
+                       if (err < 0)
+                               break;
+                       err = __put_user(err, &compat_entry->msg_len);
+                       ++compat_entry;
+               } else {
+-                      err = __sys_recvmsg(sock, (struct msghdr __user *)entry,
+-                                          &msg_sys, flags & ~MSG_WAITFORONE,
+-                                          datagrams);
++                      err = ___sys_recvmsg(sock,
++                                           (struct msghdr __user *)entry,
++                                           &msg_sys, flags & ~MSG_WAITFORONE,
++                                           datagrams);
+                       if (err < 0)
+                               break;
+                       err = put_user(err, &entry->msg_len);
+@@ -2308,6 +2328,9 @@ SYSCALL_DEFINE5(recvmmsg, int, fd, struc
+       int datagrams;
+       struct timespec timeout_sys;
++      if (flags & MSG_CMSG_COMPAT)
++              return -EINVAL;
++
+       if (!timeout)
+               return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL);
diff --git a/queue-3.0/net-force-a-reload-of-first-item-in-hlist_nulls_for_each_entry_rcu.patch b/queue-3.0/net-force-a-reload-of-first-item-in-hlist_nulls_for_each_entry_rcu.patch
new file mode 100644 (file)
index 0000000..fca3492
--- /dev/null
@@ -0,0 +1,53 @@
+From bf0713f4462b8dcb8c2cb64ed653e198eeae7fce Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <eric.dumazet@gmail.com>
+Date: Wed, 29 May 2013 09:06:27 +0000
+Subject: net: force a reload of first item in hlist_nulls_for_each_entry_rcu
+
+From: Eric Dumazet <eric.dumazet@gmail.com>
+
+[ Upstream commit c87a124a5d5e8cf8e21c4363c3372bcaf53ea190 ]
+
+Roman Gushchin discovered that udp4_lib_lookup2() was not reloading
+first item in the rcu protected list, in case the loop was restarted.
+
+This produced soft lockups as in https://lkml.org/lkml/2013/4/16/37
+
+rcu_dereference(X)/ACCESS_ONCE(X) seem to not work as intended if X is
+ptr->field :
+
+In some cases, gcc caches the value or ptr->field in a register.
+
+Use a barrier() to disallow such caching, as documented in
+Documentation/atomic_ops.txt line 114
+
+Thanks a lot to Roman for providing analysis and numerous patches.
+
+Diagnosed-by: Roman Gushchin <klamm@yandex-team.ru>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reported-by: Boris Zhmurov <zhmurov@yandex-team.ru>
+Signed-off-by: Roman Gushchin <klamm@yandex-team.ru>
+Acked-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/rculist_nulls.h |    7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/include/linux/rculist_nulls.h
++++ b/include/linux/rculist_nulls.h
+@@ -105,9 +105,14 @@ static inline void hlist_nulls_add_head_
+  * @head:     the head for your list.
+  * @member:   the name of the hlist_nulls_node within the struct.
+  *
++ * The barrier() is needed to make sure compiler doesn't cache first element [1],
++ * as this loop can be restarted [2]
++ * [1] Documentation/atomic_ops.txt around line 114
++ * [2] Documentation/RCU/rculist_nulls.txt around line 146
+  */
+ #define hlist_nulls_for_each_entry_rcu(tpos, pos, head, member)                       \
+-      for (pos = rcu_dereference_raw(hlist_nulls_first_rcu(head));            \
++      for (({barrier();}),                                                    \
++           pos = rcu_dereference_raw(hlist_nulls_first_rcu(head));            \
+               (!is_a_nulls(pos)) &&                                           \
+               ({ tpos = hlist_nulls_entry(pos, typeof(*tpos), member); 1; }); \
+               pos = rcu_dereference_raw(hlist_nulls_next_rcu(pos)))
diff --git a/queue-3.0/net-sctp-fix-null-pointer-dereference-in-socket-destruction.patch b/queue-3.0/net-sctp-fix-null-pointer-dereference-in-socket-destruction.patch
new file mode 100644 (file)
index 0000000..cdaf80f
--- /dev/null
@@ -0,0 +1,95 @@
+From 147124af20745c950812d6f071ff8aa9affb65cc Mon Sep 17 00:00:00 2001
+From: Daniel Borkmann <dborkman@redhat.com>
+Date: Thu, 6 Jun 2013 15:53:47 +0200
+Subject: net: sctp: fix NULL pointer dereference in socket destruction
+
+From: Daniel Borkmann <dborkman@redhat.com>
+
+[ Upstream commit 1abd165ed757db1afdefaac0a4bc8a70f97d258c ]
+
+While stress testing sctp sockets, I hit the following panic:
+
+BUG: unable to handle kernel NULL pointer dereference at 0000000000000020
+IP: [<ffffffffa0490c4e>] sctp_endpoint_free+0xe/0x40 [sctp]
+PGD 7cead067 PUD 7ce76067 PMD 0
+Oops: 0000 [#1] SMP
+Modules linked in: sctp(F) libcrc32c(F) [...]
+CPU: 7 PID: 2950 Comm: acc Tainted: GF            3.10.0-rc2+ #1
+Hardware name: Dell Inc. PowerEdge T410/0H19HD, BIOS 1.6.3 02/01/2011
+task: ffff88007ce0e0c0 ti: ffff88007b568000 task.ti: ffff88007b568000
+RIP: 0010:[<ffffffffa0490c4e>]  [<ffffffffa0490c4e>] sctp_endpoint_free+0xe/0x40 [sctp]
+RSP: 0018:ffff88007b569e08  EFLAGS: 00010292
+RAX: 0000000000000000 RBX: ffff88007db78a00 RCX: dead000000200200
+RDX: ffffffffa049fdb0 RSI: ffff8800379baf38 RDI: 0000000000000000
+RBP: ffff88007b569e18 R08: ffff88007c230da0 R09: 0000000000000001
+R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000
+R13: ffff880077990d00 R14: 0000000000000084 R15: ffff88007db78a00
+FS:  00007fc18ab61700(0000) GS:ffff88007fc60000(0000) knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
+CR2: 0000000000000020 CR3: 000000007cf9d000 CR4: 00000000000007e0
+DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
+Stack:
+ ffff88007b569e38 ffff88007db78a00 ffff88007b569e38 ffffffffa049fded
+ ffffffff81abf0c0 ffff88007db78a00 ffff88007b569e58 ffffffff8145b60e
+ 0000000000000000 0000000000000000 ffff88007b569eb8 ffffffff814df36e
+Call Trace:
+ [<ffffffffa049fded>] sctp_destroy_sock+0x3d/0x80 [sctp]
+ [<ffffffff8145b60e>] sk_common_release+0x1e/0xf0
+ [<ffffffff814df36e>] inet_create+0x2ae/0x350
+ [<ffffffff81455a6f>] __sock_create+0x11f/0x240
+ [<ffffffff81455bf0>] sock_create+0x30/0x40
+ [<ffffffff8145696c>] SyS_socket+0x4c/0xc0
+ [<ffffffff815403be>] ? do_page_fault+0xe/0x10
+ [<ffffffff8153cb32>] ? page_fault+0x22/0x30
+ [<ffffffff81544e02>] system_call_fastpath+0x16/0x1b
+Code: 0c c9 c3 66 2e 0f 1f 84 00 00 00 00 00 e8 fb fe ff ff c9 c3 66 0f
+      1f 84 00 00 00 00 00 55 48 89 e5 53 48 83 ec 08 66 66 66 66 90 <48>
+      8b 47 20 48 89 fb c6 47 1c 01 c6 40 12 07 e8 9e 68 01 00 48
+RIP  [<ffffffffa0490c4e>] sctp_endpoint_free+0xe/0x40 [sctp]
+ RSP <ffff88007b569e08>
+CR2: 0000000000000020
+---[ end trace e0d71ec1108c1dd9 ]---
+
+I did not hit this with the lksctp-tools functional tests, but with a
+small, multi-threaded test program, that heavily allocates, binds,
+listens and waits in accept on sctp sockets, and then randomly kills
+some of them (no need for an actual client in this case to hit this).
+Then, again, allocating, binding, etc, and then killing child processes.
+
+This panic then only occurs when ``echo 1 > /proc/sys/net/sctp/auth_enable''
+is set. The cause for that is actually very simple: in sctp_endpoint_init()
+we enter the path of sctp_auth_init_hmacs(). There, we try to allocate
+our crypto transforms through crypto_alloc_hash(). In our scenario,
+it then can happen that crypto_alloc_hash() fails with -EINTR from
+crypto_larval_wait(), thus we bail out and release the socket via
+sk_common_release(), sctp_destroy_sock() and hit the NULL pointer
+dereference as soon as we try to access members in the endpoint during
+sctp_endpoint_free(), since endpoint at that time is still NULL. Now,
+if we have that case, we do not need to do any cleanup work and just
+leave the destruction handler.
+
+Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
+Acked-by: Neil Horman <nhorman@tuxdriver.com>
+Acked-by: Vlad Yasevich <vyasevich@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sctp/socket.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -3809,6 +3809,12 @@ SCTP_STATIC void sctp_destroy_sock(struc
+       /* Release our hold on the endpoint. */
+       ep = sctp_sk(sk)->ep;
++      /* This could happen during socket init, thus we bail out
++       * early, since the rest of the below is not setup either.
++       */
++      if (ep == NULL)
++              return;
++
+       sctp_endpoint_free(ep);
+       local_bh_disable();
+       percpu_counter_dec(&sctp_sockets_allocated);
diff --git a/queue-3.0/netlabel-improve-domain-mapping-validation.patch b/queue-3.0/netlabel-improve-domain-mapping-validation.patch
new file mode 100644 (file)
index 0000000..fe23104
--- /dev/null
@@ -0,0 +1,116 @@
+From d66a61908f507b1457f4d4c40457c90272f34a46 Mon Sep 17 00:00:00 2001
+From: Paul Moore <pmoore@redhat.com>
+Date: Fri, 17 May 2013 09:08:50 +0000
+Subject: netlabel: improve domain mapping validation
+
+From: Paul Moore <pmoore@redhat.com>
+
+[ Upstream commit 6b21e1b77d1a3d58ebfd513264c885695e8a0ba5 ]
+
+The net/netlabel/netlabel_domainhash.c:netlbl_domhsh_add() function
+does not properly validate new domain hash entries resulting in
+potential problems when an administrator attempts to add an invalid
+entry.  One such problem, as reported by Vlad Halilov, is a kernel
+BUG (found in netlabel_domainhash.c:netlbl_domhsh_audit_add()) when
+adding an IPv6 outbound mapping with a CIPSO configuration.
+
+This patch corrects this problem by adding the necessary validation
+code to netlbl_domhsh_add() via the newly created
+netlbl_domhsh_validate() function.
+
+Ideally this patch should also be pushed to the currently active
+-stable trees.
+
+Reported-by: Vlad Halilov <vlad.halilov@gmail.com>
+Signed-off-by: Paul Moore <pmoore@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/netlabel/netlabel_domainhash.c |   69 +++++++++++++++++++++++++++++++++++++
+ 1 file changed, 69 insertions(+)
+
+--- a/net/netlabel/netlabel_domainhash.c
++++ b/net/netlabel/netlabel_domainhash.c
+@@ -246,6 +246,71 @@ static void netlbl_domhsh_audit_add(stru
+       }
+ }
++/**
++ * netlbl_domhsh_validate - Validate a new domain mapping entry
++ * @entry: the entry to validate
++ *
++ * This function validates the new domain mapping entry to ensure that it is
++ * a valid entry.  Returns zero on success, negative values on failure.
++ *
++ */
++static int netlbl_domhsh_validate(const struct netlbl_dom_map *entry)
++{
++      struct netlbl_af4list *iter4;
++      struct netlbl_domaddr4_map *map4;
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++      struct netlbl_af6list *iter6;
++      struct netlbl_domaddr6_map *map6;
++#endif /* IPv6 */
++
++      if (entry == NULL)
++              return -EINVAL;
++
++      switch (entry->type) {
++      case NETLBL_NLTYPE_UNLABELED:
++              if (entry->type_def.cipsov4 != NULL ||
++                  entry->type_def.addrsel != NULL)
++                      return -EINVAL;
++              break;
++      case NETLBL_NLTYPE_CIPSOV4:
++              if (entry->type_def.cipsov4 == NULL)
++                      return -EINVAL;
++              break;
++      case NETLBL_NLTYPE_ADDRSELECT:
++              netlbl_af4list_foreach(iter4, &entry->type_def.addrsel->list4) {
++                      map4 = netlbl_domhsh_addr4_entry(iter4);
++                      switch (map4->type) {
++                      case NETLBL_NLTYPE_UNLABELED:
++                              if (map4->type_def.cipsov4 != NULL)
++                                      return -EINVAL;
++                              break;
++                      case NETLBL_NLTYPE_CIPSOV4:
++                              if (map4->type_def.cipsov4 == NULL)
++                                      return -EINVAL;
++                              break;
++                      default:
++                              return -EINVAL;
++                      }
++              }
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++              netlbl_af6list_foreach(iter6, &entry->type_def.addrsel->list6) {
++                      map6 = netlbl_domhsh_addr6_entry(iter6);
++                      switch (map6->type) {
++                      case NETLBL_NLTYPE_UNLABELED:
++                              break;
++                      default:
++                              return -EINVAL;
++                      }
++              }
++#endif /* IPv6 */
++              break;
++      default:
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
+ /*
+  * Domain Hash Table Functions
+  */
+@@ -312,6 +377,10 @@ int netlbl_domhsh_add(struct netlbl_dom_
+       struct netlbl_af6list *tmp6;
+ #endif /* IPv6 */
++      ret_val = netlbl_domhsh_validate(entry);
++      if (ret_val != 0)
++              return ret_val;
++
+       /* XXX - we can remove this RCU read lock as the spinlock protects the
+        *       entire function, but before we do we need to fixup the
+        *       netlbl_af[4,6]list RCU functions to do "the right thing" with
diff --git a/queue-3.0/packet-packet_getname_spkt-make-sure-string-is-always-0-terminated.patch b/queue-3.0/packet-packet_getname_spkt-make-sure-string-is-always-0-terminated.patch
new file mode 100644 (file)
index 0000000..6f37b26
--- /dev/null
@@ -0,0 +1,41 @@
+From 75e9eaf51fdb2ad4d047594642394d276ed8360c Mon Sep 17 00:00:00 2001
+From: Daniel Borkmann <dborkman@redhat.com>
+Date: Wed, 12 Jun 2013 16:02:27 +0200
+Subject: packet: packet_getname_spkt: make sure string is always 0-terminated
+
+From: Daniel Borkmann <dborkman@redhat.com>
+
+[ Upstream commit 2dc85bf323515e59e15dfa858d1472bb25cad0fe ]
+
+uaddr->sa_data is exactly of size 14, which is hard-coded here and
+passed as a size argument to strncpy(). A device name can be of size
+IFNAMSIZ (== 16), meaning we might leave the destination string
+unterminated. Thus, use strlcpy() and also sizeof() while we're
+at it. We need to memset the data area beforehand, since strlcpy
+does not padd the remaining buffer with zeroes for user space, so
+that we do not possibly leak anything.
+
+Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/packet/af_packet.c |    5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+--- a/net/packet/af_packet.c
++++ b/net/packet/af_packet.c
+@@ -1767,12 +1767,11 @@ static int packet_getname_spkt(struct so
+               return -EOPNOTSUPP;
+       uaddr->sa_family = AF_PACKET;
++      memset(uaddr->sa_data, 0, sizeof(uaddr->sa_data));
+       rcu_read_lock();
+       dev = dev_get_by_index_rcu(sock_net(sk), pkt_sk(sk)->ifindex);
+       if (dev)
+-              strncpy(uaddr->sa_data, dev->name, 14);
+-      else
+-              memset(uaddr->sa_data, 0, 14);
++              strlcpy(uaddr->sa_data, dev->name, sizeof(uaddr->sa_data));
+       rcu_read_unlock();
+       *uaddr_len = sizeof(*uaddr);
index 60f56d6b2d0f433baa0ee8d350729fcb3e8d4ba7..170de9620eca6f73f1b1c71874885e39111a8436 100644 (file)
@@ -1,3 +1,16 @@
 alsa-usb-audio-work-around-android-accessory-firmware-bug.patch
 tilepro-work-around-module-link-error-with-gcc-4.7.patch
 kvm-x86-remove-vcpu-s-cpl-check-in-host-invoked-xcr-set.patch
+tcp-fix-tcp_md5_hash_skb_data.patch
+gianfar-add-missing-iounmap-on-error-in-gianfar_ptp_probe.patch
+ipv6-fix-possible-crashes-in-ip6_cork_release.patch
+netlabel-improve-domain-mapping-validation.patch
+tcp-xps-fix-reordering-issues.patch
+ip_tunnel-fix-kernel-panic-with-icmp_dest_unreach.patch
+net-block-msg_cmsg_compat-in-send-m-msg-and-recv-m-msg.patch
+net-force-a-reload-of-first-item-in-hlist_nulls_for_each_entry_rcu.patch
+ipv6-assign-rt6_info-to-inet6_ifaddr-in-init_loopback.patch
+net-sctp-fix-null-pointer-dereference-in-socket-destruction.patch
+packet-packet_getname_spkt-make-sure-string-is-always-0-terminated.patch
+l2tp-fix-ppp-header-erasure-and-memory-leak.patch
+l2tp-fix-sendmsg-return-value.patch
diff --git a/queue-3.0/tcp-fix-tcp_md5_hash_skb_data.patch b/queue-3.0/tcp-fix-tcp_md5_hash_skb_data.patch
new file mode 100644 (file)
index 0000000..5f6ce76
--- /dev/null
@@ -0,0 +1,46 @@
+From c3f00fd432bdd2e5e12f384a72e7ec48124c2690 Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Mon, 13 May 2013 21:25:52 +0000
+Subject: tcp: fix tcp_md5_hash_skb_data()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 54d27fcb338bd9c42d1dfc5a39e18f6f9d373c2e ]
+
+TCP md5 communications fail [1] for some devices, because sg/crypto code
+assume page offsets are below PAGE_SIZE.
+
+This was discovered using mlx4 driver [2], but I suspect loopback
+might trigger the same bug now we use order-3 pages in tcp_sendmsg()
+
+[1] Failure is giving following messages.
+
+huh, entered softirq 3 NET_RX ffffffff806ad230 preempt_count 00000100,
+exited with 00000101?
+
+[2] mlx4 driver uses order-2 pages to allocate RX frags
+
+Reported-by: Matt Schnall <mischnal@google.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Bernhard Beck <bbeck@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/tcp.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -3043,7 +3043,11 @@ int tcp_md5_hash_skb_data(struct tcp_md5
+       for (i = 0; i < shi->nr_frags; ++i) {
+               const struct skb_frag_struct *f = &shi->frags[i];
+-              sg_set_page(&sg, f->page, f->size, f->page_offset);
++              unsigned int offset = f->page_offset;
++              struct page *page = f->page + (offset >> PAGE_SHIFT);
++
++              sg_set_page(&sg, page, f->size,
++                          offset_in_page(offset));
+               if (crypto_hash_update(desc, &sg, f->size))
+                       return 1;
+       }
diff --git a/queue-3.0/tcp-xps-fix-reordering-issues.patch b/queue-3.0/tcp-xps-fix-reordering-issues.patch
new file mode 100644 (file)
index 0000000..1016d9b
--- /dev/null
@@ -0,0 +1,47 @@
+From 0572ccda874850a4155d0a9bc621486fa2675b2e Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Thu, 23 May 2013 07:44:20 +0000
+Subject: tcp: xps: fix reordering issues
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 547669d483e5783d722772af1483fa474da7caf9 ]
+
+commit 3853b5841c01a ("xps: Improvements in TX queue selection")
+introduced ooo_okay flag, but the condition to set it is slightly wrong.
+
+In our traces, we have seen ACK packets being received out of order,
+and RST packets sent in response.
+
+We should test if we have any packets still in host queue.
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Tom Herbert <therbert@google.com>
+Cc: Yuchung Cheng <ycheng@google.com>
+Cc: Neal Cardwell <ncardwell@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/tcp_output.c |   10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/net/ipv4/tcp_output.c
++++ b/net/ipv4/tcp_output.c
+@@ -833,11 +833,13 @@ static int tcp_transmit_skb(struct sock
+                                                          &md5);
+       tcp_header_size = tcp_options_size + sizeof(struct tcphdr);
+-      if (tcp_packets_in_flight(tp) == 0) {
++      if (tcp_packets_in_flight(tp) == 0)
+               tcp_ca_event(sk, CA_EVENT_TX_START);
+-              skb->ooo_okay = 1;
+-      } else
+-              skb->ooo_okay = 0;
++
++      /* if no packet is in qdisc/device queue, then allow XPS to select
++       * another queue.
++       */
++      skb->ooo_okay = sk_wmem_alloc_get(sk) == 0;
+       skb_push(skb, tcp_header_size);
+       skb_reset_transport_header(skb);