3.18-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Eric Dumazet <eduma...@google.com>

commit 607065bad9931e72207b0cac365d7d4abc06bd99 upstream.

When using large tcp_rmem[2] values (I did tests with 500 MB),
I noticed overflows while computing rcvwin.

Lets fix this before the following patch.

Signed-off-by: Eric Dumazet <eduma...@google.com>
Acked-by: Soheil Hassas Yeganeh <soh...@google.com>
Acked-by: Wei Wang <wei...@google.com>
Acked-by: Neal Cardwell <ncardw...@google.com>
Signed-off-by: David S. Miller <da...@davemloft.net>
[Backport: sysctl_tcp_rmem is not Namespace-ify'd in older kernels]
Signed-off-by: Guenter Roeck <li...@roeck-us.net>
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>

---
 include/linux/tcp.h  |    2 +-
 net/ipv4/tcp_input.c |   10 ++++++----
 2 files changed, 7 insertions(+), 5 deletions(-)

--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -292,7 +292,7 @@ struct tcp_sock {
 
 /* Receiver queue space */
        struct {
-               int     space;
+               u32     space;
                u32     seq;
                u32     time;
        } rcvq_space;
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -550,8 +550,8 @@ static inline void tcp_rcv_rtt_measure_t
 void tcp_rcv_space_adjust(struct sock *sk)
 {
        struct tcp_sock *tp = tcp_sk(sk);
+       u32 copied;
        int time;
-       int copied;
 
        time = tcp_time_stamp - tp->rcvq_space.time;
        if (time < (tp->rcv_rtt_est.rtt >> 3) || tp->rcv_rtt_est.rtt == 0)
@@ -573,12 +573,13 @@ void tcp_rcv_space_adjust(struct sock *s
 
        if (sysctl_tcp_moderate_rcvbuf &&
            !(sk->sk_userlocks & SOCK_RCVBUF_LOCK)) {
-               int rcvwin, rcvmem, rcvbuf;
+               int rcvmem, rcvbuf;
+               u64 rcvwin;
 
                /* minimal window to cope with packet losses, assuming
                 * steady state. Add some cushion because of small variations.
                 */
-               rcvwin = (copied << 1) + 16 * tp->advmss;
+               rcvwin = ((u64)copied << 1) + 16 * tp->advmss;
 
                /* If rate increased by 25%,
                 *      assume slow start, rcvwin = 3 * copied
@@ -598,7 +599,8 @@ void tcp_rcv_space_adjust(struct sock *s
                while (tcp_win_from_space(rcvmem) < tp->advmss)
                        rcvmem += 128;
 
-               rcvbuf = min(rcvwin / tp->advmss * rcvmem, sysctl_tcp_rmem[2]);
+               do_div(rcvwin, tp->advmss);
+               rcvbuf = min_t(u64, rcvwin * rcvmem, sysctl_tcp_rmem[2]);
                if (rcvbuf > sk->sk_rcvbuf) {
                        sk->sk_rcvbuf = rcvbuf;
 


Reply via email to