aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGustavo F. Padovan <padovan@profusion.mobi>2011-04-25 14:10:41 -0400
committerGustavo F. Padovan <padovan@profusion.mobi>2011-04-28 00:10:01 -0400
commit6ff5abbf4e4aa88feb9c2367d4fbd9ea081bf98c (patch)
tree05848e91d3ac481432b3c0718dbb9fd91a5067c1
parent8c1d787be4b62d2d1b6f04953eca4bcf7c839d44 (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.h1
-rw-r--r--net/bluetooth/l2cap_core.c10
-rw-r--r--net/bluetooth/l2cap_sock.c2
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,
469void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err); 469void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err);
470struct l2cap_chan *l2cap_chan_alloc(struct sock *sk); 470struct l2cap_chan *l2cap_chan_alloc(struct sock *sk);
471void l2cap_chan_del(struct l2cap_chan *chan, int err); 471void l2cap_chan_del(struct l2cap_chan *chan, int err);
472void l2cap_chan_free(struct l2cap_chan *chan);
472int l2cap_chan_connect(struct l2cap_chan *chan); 473int 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
163void l2cap_chan_free(struct l2cap_chan *chan)
164{
165 kfree(chan);
166}
167
163static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 168static 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
259free:
260 kfree(chan);
261} 263}
262 264
263static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) 265static 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);