summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPauli Virtanen <pav@iki.fi>2026-08-29 17:20:06 +0300
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2026-10-14 13:26:59 -0400
commitb508a2a2d846ccc4c8f691e4e3dfca6f97dfe85a (patch)
treeb4831678ba2a55ed6ae4d259ac548b78ec1375c8
parent889dfdde79e27e0f00b6fa08704e240a42c4ccac (diff)
downloadlinux-next-b508a2a2d846ccc4c8f691e4e3dfca6f97dfe85a.tar.gz
linux-next-b508a2a2d846ccc4c8f691e4e3dfca6f97dfe85a.zip
Bluetooth: L2CAP: hold chan in l2cap_ecred_conn_rsp()
l2cap_chan_del() calls l2cap_chan_put() to drop the conn->chan_l reference. If this was the last reference, UAF follows. l2cap_ecred_conn_rsp() iterates chan_l list and calls l2cap_chan_del() on some members, without holding chan reference. Fix by holding refcount while using chan after l2cap_chan_del(). Since orig is looked up by dcid provided by remote, it's also possible orig == chan, so reference needs to be held also after orig use. Fixes: 41c2713b204e ("Bluetooth: L2CAP: Fix possible crash on l2cap_ecred_conn_rsp") Assisted-by: deepseek-v4-flash Signed-off-by: Pauli Virtanen <pav@iki.fi> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
-rw-r--r--net/bluetooth/l2cap_core.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 68fc14344026..93dade523416 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -5468,12 +5468,14 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
chan->state == BT_CONNECTED)
continue;
+ l2cap_chan_hold(chan);
l2cap_chan_lock(chan);
/* Check that there is a dcid for each pending channel */
if (cmd_len < sizeof(dcid)) {
l2cap_chan_del(chan, ECONNREFUSED);
l2cap_chan_unlock(chan);
+ l2cap_chan_put(chan);
continue;
}
@@ -5512,6 +5514,8 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
__set_chan_timer(orig, 0);
l2cap_chan_unlock(orig);
}
+
+ l2cap_chan_put(chan);
continue;
}
@@ -5557,6 +5561,7 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
}
l2cap_chan_unlock(chan);
+ l2cap_chan_put(chan);
}
return err;