diff options
author | Mat Martineau <mathewm@codeaurora.org> | 2012-04-27 16:50:50 -0700 |
---|---|---|
committer | Gustavo Padovan <gustavo@padovan.org> | 2012-05-09 01:40:49 -0300 |
commit | 61d6ef3e3408cdf7e622646fb90a9f7f9560b943 (patch) | |
tree | b8a711d6cb948ec81749aa8b06a53a8e2dac0b37 /net/bluetooth/l2cap_core.c | |
parent | dbd89fddc1f1fc96085deb164b7b9b2361241dd3 (diff) |
Bluetooth: Make better use of l2cap_chan reference counting
L2CAP sockets contain a pointer to l2cap_chan that needs to be
reference counted in order to prevent a possible dangling pointer when
the channel is freed.
There were a few other cases where an l2cap_chan pointer on the stack
was dereferenced after a call to l2cap_chan_del. Those pointers are
also now reference counted.
Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
Signed-off-by: Gustavo Padovan <gustavo@padovan.org>
Diffstat (limited to 'net/bluetooth/l2cap_core.c')
-rw-r--r-- | net/bluetooth/l2cap_core.c | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 1192c943bf8..b854d284d42 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1256,6 +1256,7 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) /* Kill channels */ list_for_each_entry_safe(chan, l, &conn->chan_l, list) { + l2cap_chan_hold(chan); l2cap_chan_lock(chan); l2cap_chan_del(chan, err); @@ -1263,6 +1264,7 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) l2cap_chan_unlock(chan); chan->ops->close(chan->data); + l2cap_chan_put(chan); } mutex_unlock(&conn->chan_lock); @@ -3375,11 +3377,13 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd sk->sk_shutdown = SHUTDOWN_MASK; release_sock(sk); + l2cap_chan_hold(chan); l2cap_chan_del(chan, ECONNRESET); l2cap_chan_unlock(chan); chan->ops->close(chan->data); + l2cap_chan_put(chan); mutex_unlock(&conn->chan_lock); @@ -3407,11 +3411,13 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd l2cap_chan_lock(chan); + l2cap_chan_hold(chan); l2cap_chan_del(chan, 0); l2cap_chan_unlock(chan); chan->ops->close(chan->data); + l2cap_chan_put(chan); mutex_unlock(&conn->chan_lock); |