Bluetooth: Fix memory leak with L2CAP channels
authorGustavo F. Padovan <padovan@profusion.mobi>
Mon, 25 Apr 2011 18:10:41 +0000 (15:10 -0300)
committerGustavo F. Padovan <padovan@profusion.mobi>
Thu, 28 Apr 2011 04:10:01 +0000 (01:10 -0300)
A new l2cap_chan_free() is added to free the channels.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
include/net/bluetooth/l2cap.h
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_sock.c

index 3de90a91a4e452ee14c14b9bdcca4f33c2e354eb..0a0134161b1b30dd64057f8d7251b2d754913875 100644 (file)
@@ -469,6 +469,7 @@ struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
 void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err);
 struct l2cap_chan *l2cap_chan_alloc(struct sock *sk);
 void l2cap_chan_del(struct l2cap_chan *chan, int err);
+void l2cap_chan_free(struct l2cap_chan *chan);
 int l2cap_chan_connect(struct l2cap_chan *chan);
 
 #endif /* __L2CAP_H */
index 8562ac1ba9472db73c7da497429c947b63e9d924..338d8c3eedabcee2184c2ce70e52641d0393a948 100644 (file)
@@ -160,6 +160,11 @@ struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)
        return chan;
 }
 
+void l2cap_chan_free(struct l2cap_chan *chan)
+{
+       kfree(chan);
+}
+
 static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
 {
        struct sock *sk = chan->sk;
@@ -236,7 +241,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
 
        if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE &&
                        chan->conf_state & L2CAP_CONF_INPUT_DONE))
-               goto free;
+               return;
 
        skb_queue_purge(&chan->tx_q);
 
@@ -255,9 +260,6 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
                        kfree(l);
                }
        }
-
-free:
-       kfree(chan);
 }
 
 static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
index 61d93f6c36c89912d6302c85a2db0a40a026c304..0e23ebdf7c8f17170aa20397c528bdd5c6e17c3d 100644 (file)
@@ -849,6 +849,8 @@ void l2cap_sock_kill(struct sock *sk)
        BT_DBG("sk %p state %d", sk, sk->sk_state);
 
        /* Kill poor orphan */
+
+       l2cap_chan_free(l2cap_pi(sk)->chan);
        bt_sock_unlink(&l2cap_sk_list, sk);
        sock_set_flag(sk, SOCK_DEAD);
        sock_put(sk);