]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.0-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 19 Mar 2012 23:34:21 +0000 (16:34 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 19 Mar 2012 23:34:21 +0000 (16:34 -0700)
added patches:
ipv6-don-t-dev_hold-dev-in-ip6_mc_find_dev_rcu.patch
tcp-fix-syncookie-regression.patch

queue-3.0/ipv6-don-t-dev_hold-dev-in-ip6_mc_find_dev_rcu.patch [new file with mode: 0644]
queue-3.0/series
queue-3.0/tcp-fix-syncookie-regression.patch [new file with mode: 0644]

diff --git a/queue-3.0/ipv6-don-t-dev_hold-dev-in-ip6_mc_find_dev_rcu.patch b/queue-3.0/ipv6-don-t-dev_hold-dev-in-ip6_mc_find_dev_rcu.patch
new file mode 100644 (file)
index 0000000..1729781
--- /dev/null
@@ -0,0 +1,34 @@
+From af00059acc17645d97b2966bbb091a6ca0fba858 Mon Sep 17 00:00:00 2001
+From: "RongQing.Li" <roy.qing.li@gmail.com>
+Date: Thu, 15 Mar 2012 22:54:14 +0000
+Subject: ipv6: Don't dev_hold(dev) in ip6_mc_find_dev_rcu.
+
+
+From: RongQing.Li <roy.qing.li@gmail.com>
+
+[ Upstream commit c577923756b7fe9071f28a76b66b83b306d1d001 ]
+
+ip6_mc_find_dev_rcu() is called with rcu_read_lock(), so don't
+need to dev_hold().
+With dev_hold(), not corresponding dev_put(), will lead to leak.
+
+[ bug introduced in 96b52e61be1 (ipv6: mcast: RCU conversions) ]
+
+Signed-off-by: RongQing.Li <roy.qing.li@gmail.com>
+Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/mcast.c |    1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/net/ipv6/mcast.c
++++ b/net/ipv6/mcast.c
+@@ -257,7 +257,6 @@ static struct inet6_dev *ip6_mc_find_dev
+               if (rt) {
+                       dev = rt->rt6i_dev;
+-                      dev_hold(dev);
+                       dst_release(&rt->dst);
+               }
+       } else
index eba7aec8b1f0a0798e8cc4abacf7dee2368c1b7b..e01c950b009b3bdcc3f8ec6c73733e5c76ba5d5e 100644 (file)
@@ -2,3 +2,5 @@ nilfs2-fix-null-pointer-dereference-in-nilfs_load_super_block.patch
 afs-read-of-file-returns-ebadmsg.patch
 afs-remote-abort-can-cause-bug-in-rxrpc-code.patch
 perf-tools-incorrect-use-of-snprintf-results-in-segv.patch
+tcp-fix-syncookie-regression.patch
+ipv6-don-t-dev_hold-dev-in-ip6_mc_find_dev_rcu.patch
diff --git a/queue-3.0/tcp-fix-syncookie-regression.patch b/queue-3.0/tcp-fix-syncookie-regression.patch
new file mode 100644 (file)
index 0000000..838c7ac
--- /dev/null
@@ -0,0 +1,107 @@
+From 0a00912df20e6b30404d5fc25d7f4e839c812849 Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <eric.dumazet@gmail.com>
+Date: Sat, 10 Mar 2012 09:20:21 +0000
+Subject: tcp: fix syncookie regression
+
+
+From: Eric Dumazet <eric.dumazet@gmail.com>
+
+[ Upstream commit dfd25ffffc132c00070eed64200e8950da5d7e9d ]
+
+commit ea4fc0d619 (ipv4: Don't use rt->rt_{src,dst} in ip_queue_xmit())
+added a serious regression on synflood handling.
+
+Simon Kirby discovered a successful connection was delayed by 20 seconds
+before being responsive.
+
+In my tests, I discovered that xmit frames were lost, and needed ~4
+retransmits and a socket dst rebuild before being really sent.
+
+In case of syncookie initiated connection, we use a different path to
+initialize the socket dst, and inet->cork.fl.u.ip4 is left cleared.
+
+As ip_queue_xmit() now depends on inet flow being setup, fix this by
+copying the temp flowi4 we use in cookie_v4_check().
+
+Reported-by: Simon Kirby <sim@netnation.com>
+Bisected-by: Simon Kirby <sim@netnation.com>
+Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
+Tested-by: Eric Dumazet <eric.dumazet@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/syncookies.c |   30 ++++++++++++++++--------------
+ net/ipv4/tcp_ipv4.c   |   10 +++++++---
+ 2 files changed, 23 insertions(+), 17 deletions(-)
+
+--- a/net/ipv4/syncookies.c
++++ b/net/ipv4/syncookies.c
+@@ -277,6 +277,7 @@ struct sock *cookie_v4_check(struct sock
+       struct rtable *rt;
+       __u8 rcv_wscale;
+       bool ecn_ok = false;
++      struct flowi4 fl4;
+       if (!sysctl_tcp_syncookies || !th->ack || th->rst)
+               goto out;
+@@ -344,20 +345,16 @@ struct sock *cookie_v4_check(struct sock
+        * hasn't changed since we received the original syn, but I see
+        * no easy way to do this.
+        */
+-      {
+-              struct flowi4 fl4;
+-
+-              flowi4_init_output(&fl4, 0, sk->sk_mark, RT_CONN_FLAGS(sk),
+-                                 RT_SCOPE_UNIVERSE, IPPROTO_TCP,
+-                                 inet_sk_flowi_flags(sk),
+-                                 (opt && opt->srr) ? opt->faddr : ireq->rmt_addr,
+-                                 ireq->loc_addr, th->source, th->dest);
+-              security_req_classify_flow(req, flowi4_to_flowi(&fl4));
+-              rt = ip_route_output_key(sock_net(sk), &fl4);
+-              if (IS_ERR(rt)) {
+-                      reqsk_free(req);
+-                      goto out;
+-              }
++      flowi4_init_output(&fl4, 0, sk->sk_mark, RT_CONN_FLAGS(sk),
++                         RT_SCOPE_UNIVERSE, IPPROTO_TCP,
++                         inet_sk_flowi_flags(sk),
++                         (opt && opt->srr) ? opt->faddr : ireq->rmt_addr,
++                         ireq->loc_addr, th->source, th->dest);
++      security_req_classify_flow(req, flowi4_to_flowi(&fl4));
++      rt = ip_route_output_key(sock_net(sk), &fl4);
++      if (IS_ERR(rt)) {
++              reqsk_free(req);
++              goto out;
+       }
+       /* Try to redo what tcp_v4_send_synack did. */
+@@ -371,5 +368,10 @@ struct sock *cookie_v4_check(struct sock
+       ireq->rcv_wscale  = rcv_wscale;
+       ret = get_cookie_sock(sk, skb, req, &rt->dst);
++      /* ip_queue_xmit() depends on our flow being setup
++       * Normal sockets get it right from inet_csk_route_child_sock()
++       */
++      if (ret)
++              inet_sk(ret)->cork.fl.u.ip4 = fl4;
+ out:  return ret;
+ }
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -1454,9 +1454,13 @@ struct sock *tcp_v4_syn_recv_sock(struct
+               inet_csk(newsk)->icsk_ext_hdr_len = inet_opt->opt.optlen;
+       newinet->inet_id = newtp->write_seq ^ jiffies;
+-      if (!dst && (dst = inet_csk_route_child_sock(sk, newsk, req)) == NULL)
+-              goto put_and_exit;
+-
++      if (!dst) {
++              dst = inet_csk_route_child_sock(sk, newsk, req);
++              if (!dst)
++                      goto put_and_exit;
++      } else {
++              /* syncookie case : see end of cookie_v4_check() */
++      }
+       sk_setup_caps(newsk, dst);
+       tcp_mtup_init(newsk);