]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
tcp: cookie transactions setsockopt memory leak
authorDmitry Popov <dp@highloadlab.com>
Thu, 29 Jul 2010 01:59:36 +0000 (01:59 +0000)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 26 Aug 2010 23:43:42 +0000 (16:43 -0700)
[ Upstream commit a3bdb549e30e7a263f7a589747c40e9c50110315 ]

There is a bug in do_tcp_setsockopt(net/ipv4/tcp.c),
TCP_COOKIE_TRANSACTIONS case.
In some cases (when tp->cookie_values == NULL) new tcp_cookie_values
structure can be allocated (at cvp), but not bound to
tp->cookie_values. So a memory leak occurs.

Signed-off-by: Dmitry Popov <dp@highloadlab.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
net/ipv4/tcp.c

index 296150b2a62f11ac127177b6cdfaf73d1dfc4c6a..4fbf48132869d5202a03173f1055c06452664cbe 100644 (file)
@@ -2175,6 +2175,8 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
                                      GFP_KERNEL);
                        if (cvp == NULL)
                                return -ENOMEM;
+
+                       kref_init(&cvp->kref);
                }
                lock_sock(sk);
                tp->rx_opt.cookie_in_always =
@@ -2189,12 +2191,11 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
                                 */
                                kref_put(&tp->cookie_values->kref,
                                         tcp_cookie_values_release);
-                               kref_init(&cvp->kref);
-                               tp->cookie_values = cvp;
                        } else {
                                cvp = tp->cookie_values;
                        }
                }
+
                if (cvp != NULL) {
                        cvp->cookie_desired = ctd.tcpct_cookie_desired;
 
@@ -2208,6 +2209,8 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
                                cvp->s_data_desired = ctd.tcpct_s_data_desired;
                                cvp->s_data_constant = 0; /* false */
                        }
+
+                       tp->cookie_values = cvp;
                }
                release_sock(sk);
                return err;