Bluetooth: L2CAP: make concurrent l2cap_set_timer() refcounting safe

Since l2cap_set_timer() does not check return value of
schedule_delayed_work(), two concurrent calls may result to l2cap_chan
refcount leak.

Change the refcounting by using mod_delayed_work() and checking its
return value.

Code paths aside from l2cap_chan_busy() hold chan->lock, so this has
little correctness impact.

Signed-off-by: Pauli Virtanen <pav@iki.fi>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
Pauli Virtanen 2026-08-29 17:20:09 +03:00 committed by Luiz Augusto von Dentz
parent b508a2a2d8
commit aba67d585b

View File

@ -847,12 +847,11 @@ static inline void l2cap_set_timer(struct l2cap_chan *chan,
BT_DBG("chan %p state %s timeout %ld", chan,
state_to_string(chan->state), timeout);
/* If delayed work cancelled do not hold(chan)
since it is already done with previous set_timer */
if (!cancel_delayed_work(work))
l2cap_chan_hold(chan);
l2cap_chan_hold(chan);
schedule_delayed_work(work, timeout);
/* put(chan) if timer was already queued so it already has a ref */
if (mod_delayed_work(system_percpu_wq, work, timeout))
l2cap_chan_put(chan);
}
static inline bool l2cap_clear_timer(struct l2cap_chan *chan,