Bluetooth: Fix possible access of hci_chan after it is deleted
When the connection is not in BT_CONNECTED state it was possible for code in hci_chan_modify() to attempt to access the hci_chan structure after it had already been deleted by hci_chan_put(). Change-Id: I5ae352ac12aa3b456e7bcf30633015d98b03e44b CRs-fixed: 319934 Signed-off-by: Peter Krystad <pkrystad@codeaurora.org>
This commit is contained in:
@@ -576,7 +576,7 @@ static inline void hci_chan_hold(struct hci_chan *chan)
|
|||||||
{
|
{
|
||||||
atomic_inc(&chan->refcnt);
|
atomic_inc(&chan->refcnt);
|
||||||
}
|
}
|
||||||
void hci_chan_put(struct hci_chan *chan);
|
int hci_chan_put(struct hci_chan *chan);
|
||||||
|
|
||||||
struct hci_chan *hci_chan_accept(struct hci_conn *hcon,
|
struct hci_chan *hci_chan_accept(struct hci_conn *hcon,
|
||||||
struct hci_ext_fs *tx_fs,
|
struct hci_ext_fs *tx_fs,
|
||||||
|
|||||||
@@ -505,13 +505,13 @@ int hci_chan_del(struct hci_chan *chan)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hci_chan_put(struct hci_chan *chan)
|
int hci_chan_put(struct hci_chan *chan)
|
||||||
{
|
{
|
||||||
struct hci_cp_disconn_logical_link cp;
|
struct hci_cp_disconn_logical_link cp;
|
||||||
|
|
||||||
BT_DBG("chan %p refcnt %d", chan, atomic_read(&chan->refcnt));
|
BT_DBG("chan %p refcnt %d", chan, atomic_read(&chan->refcnt));
|
||||||
if (!atomic_dec_and_test(&chan->refcnt))
|
if (!atomic_dec_and_test(&chan->refcnt))
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
BT_DBG("chan->conn->state %d", chan->conn->state);
|
BT_DBG("chan->conn->state %d", chan->conn->state);
|
||||||
if (chan->conn->state == BT_CONNECTED) {
|
if (chan->conn->state == BT_CONNECTED) {
|
||||||
@@ -520,6 +520,8 @@ void hci_chan_put(struct hci_chan *chan)
|
|||||||
sizeof(cp), &cp);
|
sizeof(cp), &cp);
|
||||||
} else
|
} else
|
||||||
hci_chan_del(chan);
|
hci_chan_del(chan);
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(hci_chan_put);
|
EXPORT_SYMBOL(hci_chan_put);
|
||||||
|
|
||||||
|
|||||||
@@ -549,8 +549,7 @@ void l2cap_chan_del(struct sock *sk, int err)
|
|||||||
l2cap_pi(sk)->ampcon->l2cap_data = NULL;
|
l2cap_pi(sk)->ampcon->l2cap_data = NULL;
|
||||||
l2cap_pi(sk)->ampcon = NULL;
|
l2cap_pi(sk)->ampcon = NULL;
|
||||||
if (l2cap_pi(sk)->ampchan) {
|
if (l2cap_pi(sk)->ampchan) {
|
||||||
hci_chan_put(l2cap_pi(sk)->ampchan);
|
if (!hci_chan_put(l2cap_pi(sk)->ampchan))
|
||||||
if (atomic_read(&l2cap_pi(sk)->ampchan->refcnt))
|
|
||||||
l2cap_deaggregate(l2cap_pi(sk)->ampchan,
|
l2cap_deaggregate(l2cap_pi(sk)->ampchan,
|
||||||
l2cap_pi(sk));
|
l2cap_pi(sk));
|
||||||
}
|
}
|
||||||
@@ -5056,8 +5055,7 @@ static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
|
|||||||
if ((!l2cap_pi(sk)->amp_id) &&
|
if ((!l2cap_pi(sk)->amp_id) &&
|
||||||
(l2cap_pi(sk)->ampchan)) {
|
(l2cap_pi(sk)->ampchan)) {
|
||||||
/* Have moved off of AMP, free the channel */
|
/* Have moved off of AMP, free the channel */
|
||||||
hci_chan_put(l2cap_pi(sk)->ampchan);
|
if (!hci_chan_put(l2cap_pi(sk)->ampchan))
|
||||||
if (atomic_read(&l2cap_pi(sk)->ampchan->refcnt))
|
|
||||||
l2cap_deaggregate(l2cap_pi(sk)->ampchan,
|
l2cap_deaggregate(l2cap_pi(sk)->ampchan,
|
||||||
l2cap_pi(sk));
|
l2cap_pi(sk));
|
||||||
l2cap_pi(sk)->ampchan = NULL;
|
l2cap_pi(sk)->ampchan = NULL;
|
||||||
@@ -5115,8 +5113,7 @@ static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
|
|||||||
/* Have moved off of AMP, free the channel */
|
/* Have moved off of AMP, free the channel */
|
||||||
l2cap_pi(sk)->ampcon = NULL;
|
l2cap_pi(sk)->ampcon = NULL;
|
||||||
if (l2cap_pi(sk)->ampchan) {
|
if (l2cap_pi(sk)->ampchan) {
|
||||||
hci_chan_put(l2cap_pi(sk)->ampchan);
|
if (!hci_chan_put(l2cap_pi(sk)->ampchan))
|
||||||
if (atomic_read(&l2cap_pi(sk)->ampchan->refcnt))
|
|
||||||
l2cap_deaggregate(l2cap_pi(sk)->ampchan,
|
l2cap_deaggregate(l2cap_pi(sk)->ampchan,
|
||||||
l2cap_pi(sk));
|
l2cap_pi(sk));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user