diff options
| author | Pauli Virtanen <pav@iki.fi> | 2026-09-02 00:04:33 +0300 |
|---|---|---|
| committer | Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | 2026-10-14 13:28:03 -0400 |
| commit | dc1ddc65f06df44dfcfe51955c82a132acb3ab8d (patch) | |
| tree | 447763f5f91fbaf8a9b8425ce75f3d911f778d55 /include | |
| parent | 6098ed784e2cade6eb39e20254e98cec54084194 (diff) | |
| download | linux-dc1ddc65f06df44dfcfe51955c82a132acb3ab8d.tar.gz linux-dc1ddc65f06df44dfcfe51955c82a132acb3ab8d.zip | |
Bluetooth: L2CAP: take lock for l2cap_chan_del in l2cap_ecred_rsp_defer
l2cap_ecred_rsp_defer() calls l2cap_chan_del without holding chan->lock,
which ends up calling ops->teardown() with wrong lock context.
Fix by taking chan->lock in l2cap_ecred_rsp_defer(). AB-BA deadlocks
between sibling l2cap_chan are avoided here via requiring l2cap_conn::lock
to serialize all nested l2cap_chan locking on same nesting level.
In current code, there is no nested l2cap_chan locking on same nesting
level, so we can add this new requirement.
Also return early from __l2cap_ecred_conn_rsp_defer() if chan did not
have FLAG_DEFER_SETUP, as then no RSP shall be sent for it, to make sure
SMP channels are excluded.
Also hold chan reference over l2cap_chan_del(), in case chan_l reference
was the last.
Signed-off-by: Pauli Virtanen <pav@iki.fi>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Diffstat (limited to 'include')
| -rw-r--r-- | include/net/bluetooth/l2cap.h | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 2315a3993c7b..c7e642abe404 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -758,6 +758,10 @@ enum { * otherwise considers all channels equal and will e.g. complain about a * connection oriented channel triggering SMP procedures or a listening * channel creating and locking a child channel. + * + * Lock nesting of channels at the same nesting level is allowed if the channels + * have the same l2cap_chan::conn and l2cap_chan::conn.lock is taken before the + * nested locks. l2cap_chan_try_sibling_lock() must be used. */ enum { L2CAP_NESTING_SMP, |
