diff options
author | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-04-25 14:10:41 -0400 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-04-28 00:10:01 -0400 |
commit | 6ff5abbf4e4aa88feb9c2367d4fbd9ea081bf98c (patch) | |
tree | 05848e91d3ac481432b3c0718dbb9fd91a5067c1 | |
parent | 8c1d787be4b62d2d1b6f04953eca4bcf7c839d44 (diff) |
Bluetooth: Fix memory leak with L2CAP channels
A new l2cap_chan_free() is added to free the channels.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
-rw-r--r-- | include/net/bluetooth/l2cap.h | 1 | ||||
-rw-r--r-- | net/bluetooth/l2cap_core.c | 10 | ||||
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 2 |
3 files changed, 9 insertions, 4 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 3de90a91a4e4..0a0134161b1b 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -469,6 +469,7 @@ struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, | |||
469 | void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err); | 469 | void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err); |
470 | struct l2cap_chan *l2cap_chan_alloc(struct sock *sk); | 470 | struct l2cap_chan *l2cap_chan_alloc(struct sock *sk); |
471 | void l2cap_chan_del(struct l2cap_chan *chan, int err); | 471 | void l2cap_chan_del(struct l2cap_chan *chan, int err); |
472 | void l2cap_chan_free(struct l2cap_chan *chan); | ||
472 | int l2cap_chan_connect(struct l2cap_chan *chan); | 473 | int l2cap_chan_connect(struct l2cap_chan *chan); |
473 | 474 | ||
474 | #endif /* __L2CAP_H */ | 475 | #endif /* __L2CAP_H */ |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 8562ac1ba947..338d8c3eedab 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -160,6 +160,11 @@ struct l2cap_chan *l2cap_chan_alloc(struct sock *sk) | |||
160 | return chan; | 160 | return chan; |
161 | } | 161 | } |
162 | 162 | ||
163 | void l2cap_chan_free(struct l2cap_chan *chan) | ||
164 | { | ||
165 | kfree(chan); | ||
166 | } | ||
167 | |||
163 | static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) | 168 | static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) |
164 | { | 169 | { |
165 | struct sock *sk = chan->sk; | 170 | struct sock *sk = chan->sk; |
@@ -236,7 +241,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) | |||
236 | 241 | ||
237 | if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE && | 242 | if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE && |
238 | chan->conf_state & L2CAP_CONF_INPUT_DONE)) | 243 | chan->conf_state & L2CAP_CONF_INPUT_DONE)) |
239 | goto free; | 244 | return; |
240 | 245 | ||
241 | skb_queue_purge(&chan->tx_q); | 246 | skb_queue_purge(&chan->tx_q); |
242 | 247 | ||
@@ -255,9 +260,6 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) | |||
255 | kfree(l); | 260 | kfree(l); |
256 | } | 261 | } |
257 | } | 262 | } |
258 | |||
259 | free: | ||
260 | kfree(chan); | ||
261 | } | 263 | } |
262 | 264 | ||
263 | static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) | 265 | static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 61d93f6c36c8..0e23ebdf7c8f 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -849,6 +849,8 @@ void l2cap_sock_kill(struct sock *sk) | |||
849 | BT_DBG("sk %p state %d", sk, sk->sk_state); | 849 | BT_DBG("sk %p state %d", sk, sk->sk_state); |
850 | 850 | ||
851 | /* Kill poor orphan */ | 851 | /* Kill poor orphan */ |
852 | |||
853 | l2cap_chan_free(l2cap_pi(sk)->chan); | ||
852 | bt_sock_unlink(&l2cap_sk_list, sk); | 854 | bt_sock_unlink(&l2cap_sk_list, sk); |
853 | sock_set_flag(sk, SOCK_DEAD); | 855 | sock_set_flag(sk, SOCK_DEAD); |
854 | sock_put(sk); | 856 | sock_put(sk); |