Commit 6ff5abbf authored by Gustavo F. Padovan's avatar Gustavo F. Padovan

Bluetooth: Fix memory leak with L2CAP channels

A new l2cap_chan_free() is added to free the channels.
Signed-off-by: default avatarGustavo F. Padovan <padovan@profusion.mobi>
parent 8c1d787b
...@@ -469,6 +469,7 @@ struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, ...@@ -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); void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err);
struct l2cap_chan *l2cap_chan_alloc(struct sock *sk); struct l2cap_chan *l2cap_chan_alloc(struct sock *sk);
void l2cap_chan_del(struct l2cap_chan *chan, int err); 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); int l2cap_chan_connect(struct l2cap_chan *chan);
#endif /* __L2CAP_H */ #endif /* __L2CAP_H */
...@@ -160,6 +160,11 @@ struct l2cap_chan *l2cap_chan_alloc(struct sock *sk) ...@@ -160,6 +160,11 @@ struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)
return chan; 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) static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
{ {
struct sock *sk = chan->sk; struct sock *sk = chan->sk;
...@@ -236,7 +241,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) ...@@ -236,7 +241,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE && if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE &&
chan->conf_state & L2CAP_CONF_INPUT_DONE)) chan->conf_state & L2CAP_CONF_INPUT_DONE))
goto free; return;
skb_queue_purge(&chan->tx_q); skb_queue_purge(&chan->tx_q);
...@@ -255,9 +260,6 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) ...@@ -255,9 +260,6 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
kfree(l); kfree(l);
} }
} }
free:
kfree(chan);
} }
static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
......
...@@ -849,6 +849,8 @@ void l2cap_sock_kill(struct sock *sk) ...@@ -849,6 +849,8 @@ void l2cap_sock_kill(struct sock *sk)
BT_DBG("sk %p state %d", sk, sk->sk_state); BT_DBG("sk %p state %d", sk, sk->sk_state);
/* Kill poor orphan */ /* Kill poor orphan */
l2cap_chan_free(l2cap_pi(sk)->chan);
bt_sock_unlink(&l2cap_sk_list, sk); bt_sock_unlink(&l2cap_sk_list, sk);
sock_set_flag(sk, SOCK_DEAD); sock_set_flag(sk, SOCK_DEAD);
sock_put(sk); sock_put(sk);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment